passcache: add support for clear on screen lock (ttl == 0)
This commit is contained in:
@@ -27,6 +27,8 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
|
import android.os.Build.VERSION;
|
||||||
|
import android.os.Build.VERSION_CODES;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
@@ -93,7 +95,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
public static final String EXTRA_MESSENGER = "messenger";
|
public static final String EXTRA_MESSENGER = "messenger";
|
||||||
public static final String EXTRA_USER_ID = "user_id";
|
public static final String EXTRA_USER_ID = "user_id";
|
||||||
|
|
||||||
private static final int DEFAULT_TTL = 15;
|
private static final int DEFAULT_TTL = 0;
|
||||||
|
|
||||||
private static final int MSG_PASSPHRASE_CACHE_GET_OKAY = 1;
|
private static final int MSG_PASSPHRASE_CACHE_GET_OKAY = 1;
|
||||||
private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND = 2;
|
private static final int MSG_PASSPHRASE_CACHE_GET_KEY_NOT_FOUND = 2;
|
||||||
@@ -237,7 +239,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
if (cachedPassphrase == null) {
|
if (cachedPassphrase == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return cachedPassphrase.getPassphrase();
|
return cachedPassphrase.mPassphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to get master key id which is used as an identifier for cached passphrases
|
// try to get master key id which is used as an identifier for cached passphrases
|
||||||
@@ -284,7 +286,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return cachedPassphrase.getPassphrase();
|
return cachedPassphrase.mPassphrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -303,13 +305,18 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
if (action.equals(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE)) {
|
if (action.equals(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE)) {
|
||||||
long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
long keyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
||||||
timeout(keyId);
|
removeTimeoutedPassphrase(keyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
|
||||||
|
removeScreenLockPassphrases();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
|
filter.addAction(BROADCAST_ACTION_PASSPHRASE_CACHE_SERVICE);
|
||||||
|
filter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||||
registerReceiver(mIntentReceiver, filter);
|
registerReceiver(mIntentReceiver, filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -337,35 +344,39 @@ public class PassphraseCacheService extends Service {
|
|||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// register broadcastreceiver
|
|
||||||
registerReceiver();
|
|
||||||
|
|
||||||
String action = intent.getAction();
|
String action = intent.getAction();
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case ACTION_PASSPHRASE_CACHE_ADD: {
|
case ACTION_PASSPHRASE_CACHE_ADD: {
|
||||||
long ttl = intent.getIntExtra(EXTRA_TTL, DEFAULT_TTL);
|
|
||||||
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
long masterKeyId = intent.getLongExtra(EXTRA_KEY_ID, -1);
|
||||||
long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, -1);
|
long subKeyId = intent.getLongExtra(EXTRA_SUBKEY_ID, -1);
|
||||||
|
long timeoutTime = intent.getIntExtra(EXTRA_TTL, DEFAULT_TTL);
|
||||||
|
|
||||||
Passphrase passphrase = intent.getParcelableExtra(EXTRA_PASSPHRASE);
|
Passphrase passphrase = intent.getParcelableExtra(EXTRA_PASSPHRASE);
|
||||||
String primaryUserID = intent.getStringExtra(EXTRA_USER_ID);
|
String primaryUserID = intent.getStringExtra(EXTRA_USER_ID);
|
||||||
|
|
||||||
Log.d(Constants.TAG,
|
Log.d(Constants.TAG,
|
||||||
"PassphraseCacheService: Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with masterkeyId: "
|
"PassphraseCacheService: Received ACTION_PASSPHRASE_CACHE_ADD intent in onStartCommand() with masterkeyId: "
|
||||||
+ masterKeyId + ", subKeyId: " + subKeyId + ", ttl: " + ttl + ", usrId: " + primaryUserID
|
+ masterKeyId + ", subKeyId: " + subKeyId + ", ttl: " + timeoutTime + ", usrId: " + primaryUserID
|
||||||
);
|
);
|
||||||
|
|
||||||
// if we don't cache by specific subkey id, or the requested subkey is the master key,
|
// if we don't cache by specific subkey id, or the requested subkey is the master key,
|
||||||
// just add master key id to the cache, otherwise, add this specific subkey to the cache
|
// just add master key id to the cache, otherwise, add this specific subkey to the cache
|
||||||
long referenceKeyId =
|
long referenceKeyId =
|
||||||
Preferences.getPreferences(mContext).getPassphraseCacheSubs() ? subKeyId : masterKeyId;
|
Preferences.getPreferences(mContext).getPassphraseCacheSubs() ? subKeyId : masterKeyId;
|
||||||
mPassphraseCache.put(referenceKeyId, new CachedPassphrase(passphrase, primaryUserID));
|
|
||||||
if (ttl > 0) {
|
CachedPassphrase cachedPassphrase;
|
||||||
|
if (timeoutTime == 0) {
|
||||||
|
cachedPassphrase = CachedPassphrase.getPassphraseLock(passphrase, primaryUserID);
|
||||||
|
} else {
|
||||||
|
cachedPassphrase = CachedPassphrase.getPassphraseTtlTimeout(passphrase, primaryUserID, timeoutTime);
|
||||||
|
|
||||||
// register new alarm with keyId for this passphrase
|
// register new alarm with keyId for this passphrase
|
||||||
long triggerTime = new Date().getTime() + (ttl * 1000);
|
|
||||||
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
|
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
|
||||||
am.set(AlarmManager.RTC_WAKEUP, triggerTime, buildIntent(this, referenceKeyId));
|
am.set(AlarmManager.RTC_WAKEUP, timeoutTime, buildIntent(this, referenceKeyId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mPassphraseCache.put(referenceKeyId, cachedPassphrase);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ACTION_PASSPHRASE_CACHE_GET: {
|
case ACTION_PASSPHRASE_CACHE_GET: {
|
||||||
@@ -435,16 +446,14 @@ public class PassphraseCacheService extends Service {
|
|||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Called when one specific passphrase for keyId timed out. */
|
||||||
* Called when one specific passphrase for keyId timed out
|
private void removeTimeoutedPassphrase(long keyId) {
|
||||||
*/
|
|
||||||
private void timeout(long keyId) {
|
|
||||||
|
|
||||||
CachedPassphrase cPass = mPassphraseCache.get(keyId);
|
CachedPassphrase cPass = mPassphraseCache.get(keyId);
|
||||||
if (cPass != null) {
|
if (cPass != null) {
|
||||||
if (cPass.getPassphrase() != null) {
|
if (cPass.mPassphrase != null) {
|
||||||
// clean internal char[] from memory!
|
// clean internal char[] from memory!
|
||||||
cPass.getPassphrase().removeFromMemory();
|
cPass.mPassphrase.removeFromMemory();
|
||||||
}
|
}
|
||||||
// remove passphrase object
|
// remove passphrase object
|
||||||
mPassphraseCache.remove(keyId);
|
mPassphraseCache.remove(keyId);
|
||||||
@@ -455,6 +464,24 @@ public class PassphraseCacheService extends Service {
|
|||||||
updateService();
|
updateService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeScreenLockPassphrases() {
|
||||||
|
|
||||||
|
for (int i = 0; i < mPassphraseCache.size(); ) {
|
||||||
|
CachedPassphrase cPass = mPassphraseCache.valueAt(i);
|
||||||
|
if (cPass.mTimeoutMode == TimeoutMode.LOCK) {
|
||||||
|
// remove passphrase object
|
||||||
|
mPassphraseCache.removeAt(i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// only do this if we didn't remove at, which continues loop by reducing size!
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(Constants.TAG, "PassphraseCacheService Removing all cached-until-lock passphrases from memory!");
|
||||||
|
|
||||||
|
updateService();
|
||||||
|
}
|
||||||
|
|
||||||
private void updateService() {
|
private void updateService() {
|
||||||
if (mPassphraseCache.size() > 0) {
|
if (mPassphraseCache.size() > 0) {
|
||||||
startForeground(Constants.Notification.PASSPHRASE_CACHE, getNotification());
|
startForeground(Constants.Notification.PASSPHRASE_CACHE, getNotification());
|
||||||
@@ -479,7 +506,7 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
// Moves events into the big view
|
// Moves events into the big view
|
||||||
for (int i = 0; i < mPassphraseCache.size(); i++) {
|
for (int i = 0; i < mPassphraseCache.size(); i++) {
|
||||||
inboxStyle.addLine(mPassphraseCache.valueAt(i).getPrimaryUserID());
|
inboxStyle.addLine(mPassphraseCache.valueAt(i).mPrimaryUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Moves the big view style object into the notification object.
|
// Moves the big view style object into the notification object.
|
||||||
@@ -512,6 +539,8 @@ public class PassphraseCacheService extends Service {
|
|||||||
super.onCreate();
|
super.onCreate();
|
||||||
mContext = this;
|
mContext = this;
|
||||||
Log.d(Constants.TAG, "PassphraseCacheService, onCreate()");
|
Log.d(Constants.TAG, "PassphraseCacheService, onCreate()");
|
||||||
|
|
||||||
|
registerReceiver();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -535,29 +564,34 @@ public class PassphraseCacheService extends Service {
|
|||||||
|
|
||||||
private final IBinder mBinder = new PassphraseCacheBinder();
|
private final IBinder mBinder = new PassphraseCacheBinder();
|
||||||
|
|
||||||
public class CachedPassphrase {
|
private enum TimeoutMode {
|
||||||
private String primaryUserID;
|
NEVER, TTL, LOCK
|
||||||
private Passphrase passphrase;
|
}
|
||||||
|
|
||||||
public CachedPassphrase(Passphrase passphrase, String primaryUserID) {
|
private static class CachedPassphrase {
|
||||||
setPassphrase(passphrase);
|
private String mPrimaryUserId;
|
||||||
setPrimaryUserID(primaryUserID);
|
private Passphrase mPassphrase;
|
||||||
|
private TimeoutMode mTimeoutMode;
|
||||||
|
private Long mTimeoutTime;
|
||||||
|
|
||||||
|
private CachedPassphrase(Passphrase passphrase, String primaryUserId, TimeoutMode timeoutMode, Long timeoutTime) {
|
||||||
|
mPassphrase = passphrase;
|
||||||
|
mPrimaryUserId = primaryUserId;
|
||||||
|
mTimeoutMode = timeoutMode;
|
||||||
|
mTimeoutTime = timeoutTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPrimaryUserID() {
|
static CachedPassphrase getPassphraseNoTimeout(Passphrase passphrase, String primaryUserId) {
|
||||||
return primaryUserID;
|
return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.NEVER, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Passphrase getPassphrase() {
|
static CachedPassphrase getPassphraseTtlTimeout(Passphrase passphrase, String primaryUserId, long timeoutTime) {
|
||||||
return passphrase;
|
return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.TTL, timeoutTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPrimaryUserID(String primaryUserID) {
|
static CachedPassphrase getPassphraseLock(Passphrase passphrase, String primaryUserId) {
|
||||||
this.primaryUserID = primaryUserID;
|
return new CachedPassphrase(passphrase, primaryUserId, TimeoutMode.LOCK, null);
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassphrase(Passphrase passphrase) {
|
|
||||||
this.passphrase = passphrase;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user