mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-23 17:22:16 -05:00
added a service to handle the caching, this'll ensure the cache works while no activity is around, which is better for k9mail integration
it also is a more efficient and much smarter cache, not requiring an own timer thread, just a service that sleeps must of the time, it also is more accurate in cleaning up the entries, ensuring that the worst case of too late removal is 5 seconds
This commit is contained in:
parent
371dc31b97
commit
600b44b9fc
@ -128,6 +128,8 @@
|
|||||||
android:label="@string/title_preferences"
|
android:label="@string/title_preferences"
|
||||||
android:configChanges="keyboardHidden|orientation|keyboard"/>
|
android:configChanges="keyboardHidden|orientation|keyboard"/>
|
||||||
|
|
||||||
|
<service android:name=".Service" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS"
|
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS"
|
||||||
android:name="org.thialfihar.android.apg.provider.DataProvider"
|
android:name="org.thialfihar.android.apg.provider.DataProvider"
|
||||||
|
@ -225,19 +225,30 @@ public class Apg {
|
|||||||
return cpp.passPhrase;
|
return cpp.passPhrase;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void cleanUpCache(int ttl) {
|
public static int cleanUpCache(int ttl, int initialDelay) {
|
||||||
|
int delay = initialDelay;
|
||||||
|
long realTtl = ttl * 1000;
|
||||||
long now = new Date().getTime();
|
long now = new Date().getTime();
|
||||||
|
|
||||||
Vector<Long> oldKeys = new Vector<Long>();
|
Vector<Long> oldKeys = new Vector<Long>();
|
||||||
for (Map.Entry<Long, CachedPassPhrase> pair : mPassPhraseCache.entrySet()) {
|
for (Map.Entry<Long, CachedPassPhrase> pair : mPassPhraseCache.entrySet()) {
|
||||||
if ((now - pair.getValue().timestamp) >= 1000 * ttl) {
|
long lived = now - pair.getValue().timestamp;
|
||||||
|
if (lived >= realTtl) {
|
||||||
oldKeys.add(pair.getKey());
|
oldKeys.add(pair.getKey());
|
||||||
|
} else {
|
||||||
|
// see, whether the remaining time for this cache entry improves our
|
||||||
|
// check delay
|
||||||
|
long nextCheck = realTtl - lived + 1000;
|
||||||
|
if (nextCheck < delay) {
|
||||||
|
delay = (int)nextCheck;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (long keyId : oldKeys) {
|
for (long keyId : oldKeys) {
|
||||||
mPassPhraseCache.remove(keyId);
|
mPassPhraseCache.remove(keyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PGPSecretKey createKey(Context context,
|
public static PGPSecretKey createKey(Context context,
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
package org.thialfihar.android.apg;
|
package org.thialfihar.android.apg;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
|
|
||||||
import org.bouncycastle2.bcpg.HashAlgorithmTags;
|
import org.bouncycastle2.bcpg.HashAlgorithmTags;
|
||||||
import org.bouncycastle2.openpgp.PGPEncryptedData;
|
import org.bouncycastle2.openpgp.PGPEncryptedData;
|
||||||
@ -53,8 +51,6 @@ public class BaseActivity extends Activity
|
|||||||
private String mDeleteFile = null;
|
private String mDeleteFile = null;
|
||||||
protected static SharedPreferences mPreferences = null;
|
protected static SharedPreferences mPreferences = null;
|
||||||
|
|
||||||
private static Timer mCacheTimer = new Timer();
|
|
||||||
|
|
||||||
private Handler mHandler = new Handler() {
|
private Handler mHandler = new Handler() {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
@ -80,29 +76,9 @@ public class BaseActivity extends Activity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCacheTimer == null) {
|
Intent intent = new Intent(this, Service.class);
|
||||||
setPassPhraseCacheTimer();
|
intent.putExtra(Service.EXTRA_TTL, getPassPhraseCacheTtl());
|
||||||
}
|
startService(intent);
|
||||||
}
|
|
||||||
|
|
||||||
private void setPassPhraseCacheTimer() {
|
|
||||||
if (mCacheTimer != null) {
|
|
||||||
mCacheTimer.cancel();
|
|
||||||
mCacheTimer = null;
|
|
||||||
}
|
|
||||||
int ttl = getPassPhraseCacheTtl();
|
|
||||||
if (ttl == 0) {
|
|
||||||
// no timer needed
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// check every ttl/2 seconds, which shouldn't be heavy on the device (even if ttl = 15),
|
|
||||||
// and makes sure the longest a pass phrase survives int the cache is 1.5 * ttl
|
|
||||||
mCacheTimer = new Timer();
|
|
||||||
mCacheTimer.scheduleAtFixedRate(new TimerTask() {
|
|
||||||
public void run() {
|
|
||||||
Apg.cleanUpCache(BaseActivity.this.getPassPhraseCacheTtl());
|
|
||||||
}
|
|
||||||
}, 0, ttl * 1000 / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -400,7 +376,9 @@ public class BaseActivity extends Activity
|
|||||||
editor.putInt(Constants.pref.pass_phrase_cache_ttl, value);
|
editor.putInt(Constants.pref.pass_phrase_cache_ttl, value);
|
||||||
editor.commit();
|
editor.commit();
|
||||||
|
|
||||||
setPassPhraseCacheTimer();
|
Intent intent = new Intent(this, Service.class);
|
||||||
|
intent.putExtra(Service.EXTRA_TTL, getPassPhraseCacheTtl());
|
||||||
|
startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDefaultEncryptionAlgorithm() {
|
public int getDefaultEncryptionAlgorithm() {
|
||||||
|
@ -50,7 +50,6 @@ public class PreferencesActivity extends BaseActivity {
|
|||||||
new Choice(180, getString(R.string.choice_3mins)),
|
new Choice(180, getString(R.string.choice_3mins)),
|
||||||
new Choice(300, getString(R.string.choice_5mins)),
|
new Choice(300, getString(R.string.choice_5mins)),
|
||||||
new Choice(600, getString(R.string.choice_10mins)),
|
new Choice(600, getString(R.string.choice_10mins)),
|
||||||
new Choice(0, getString(R.string.choice_untilQuit)),
|
|
||||||
};
|
};
|
||||||
ArrayAdapter<Choice> adapter =
|
ArrayAdapter<Choice> adapter =
|
||||||
new ArrayAdapter<Choice>(this, android.R.layout.simple_spinner_item, choices);
|
new ArrayAdapter<Choice>(this, android.R.layout.simple_spinner_item, choices);
|
||||||
|
79
src/org/thialfihar/android/apg/Service.java
Normal file
79
src/org/thialfihar/android/apg/Service.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package org.thialfihar.android.apg;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
public class Service extends android.app.Service {
|
||||||
|
private final IBinder mBinder = new LocalBinder();
|
||||||
|
|
||||||
|
public static final String EXTRA_TTL = "ttl";
|
||||||
|
|
||||||
|
private int mPassPhraseCacheTtl = 15;
|
||||||
|
private Handler mCacheHandler = new Handler();
|
||||||
|
private Runnable mCacheTask = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
// TODO: I suppose we could read out the time left until the first cache entry
|
||||||
|
// expiration, then use that for the timer...
|
||||||
|
|
||||||
|
// check every ttl/2 seconds, which shouldn't be heavy on the device (even if ttl = 15),
|
||||||
|
// and makes sure the longest a pass phrase survives in the cache is 1.5 * ttl
|
||||||
|
int delay = mPassPhraseCacheTtl * 1000 / 2;
|
||||||
|
// also make sure the delay is not longer than one minute
|
||||||
|
if (delay > 60000) {
|
||||||
|
delay = 60000;
|
||||||
|
}
|
||||||
|
|
||||||
|
delay = Apg.cleanUpCache(mPassPhraseCacheTtl, delay);
|
||||||
|
// don't check too often, even if we were close
|
||||||
|
if (delay < 5000) {
|
||||||
|
delay = 5000;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCacheHandler.postDelayed(this, delay);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static private boolean mIsRunning = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
|
||||||
|
mIsRunning = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
mIsRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart(Intent intent, int startId) {
|
||||||
|
super.onStart(intent, startId);
|
||||||
|
|
||||||
|
mPassPhraseCacheTtl = intent.getIntExtra(EXTRA_TTL, 15);
|
||||||
|
if (mPassPhraseCacheTtl < 15) {
|
||||||
|
mPassPhraseCacheTtl = 15;
|
||||||
|
}
|
||||||
|
mCacheHandler.removeCallbacks(mCacheTask);
|
||||||
|
mCacheHandler.postDelayed(mCacheTask, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public boolean isRunning() {
|
||||||
|
return mIsRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LocalBinder extends Binder {
|
||||||
|
Service getService() {
|
||||||
|
return Service.this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return mBinder;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user