aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml2
-rw-r--r--src/org/thialfihar/android/apg/Apg.java17
-rw-r--r--src/org/thialfihar/android/apg/BaseActivity.java34
-rw-r--r--src/org/thialfihar/android/apg/PreferencesActivity.java1
-rw-r--r--src/org/thialfihar/android/apg/Service.java79
5 files changed, 101 insertions, 32 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0596fc9a4..de5869988 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -128,6 +128,8 @@
android:label="@string/title_preferences"
android:configChanges="keyboardHidden|orientation|keyboard"/>
+ <service android:name=".Service" />
+
<provider
android:readPermission="org.thialfihar.android.apg.permission.READ_KEY_DETAILS"
android:name="org.thialfihar.android.apg.provider.DataProvider"
diff --git a/src/org/thialfihar/android/apg/Apg.java b/src/org/thialfihar/android/apg/Apg.java
index 85663629d..43170e802 100644
--- a/src/org/thialfihar/android/apg/Apg.java
+++ b/src/org/thialfihar/android/apg/Apg.java
@@ -225,19 +225,30 @@ public class Apg {
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();
-
Vector<Long> oldKeys = new Vector<Long>();
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());
+ } 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) {
mPassPhraseCache.remove(keyId);
}
+
+ return delay;
}
public static PGPSecretKey createKey(Context context,
diff --git a/src/org/thialfihar/android/apg/BaseActivity.java b/src/org/thialfihar/android/apg/BaseActivity.java
index 282057975..3e302b6cc 100644
--- a/src/org/thialfihar/android/apg/BaseActivity.java
+++ b/src/org/thialfihar/android/apg/BaseActivity.java
@@ -17,8 +17,6 @@
package org.thialfihar.android.apg;
import java.io.File;
-import java.util.Timer;
-import java.util.TimerTask;
import org.bouncycastle2.bcpg.HashAlgorithmTags;
import org.bouncycastle2.openpgp.PGPEncryptedData;
@@ -53,8 +51,6 @@ public class BaseActivity extends Activity
private String mDeleteFile = null;
protected static SharedPreferences mPreferences = null;
- private static Timer mCacheTimer = new Timer();
-
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -80,29 +76,9 @@ public class BaseActivity extends Activity
}
}
- if (mCacheTimer == null) {
- setPassPhraseCacheTimer();
- }
- }
-
- 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);
+ Intent intent = new Intent(this, Service.class);
+ intent.putExtra(Service.EXTRA_TTL, getPassPhraseCacheTtl());
+ startService(intent);
}
@Override
@@ -400,7 +376,9 @@ public class BaseActivity extends Activity
editor.putInt(Constants.pref.pass_phrase_cache_ttl, value);
editor.commit();
- setPassPhraseCacheTimer();
+ Intent intent = new Intent(this, Service.class);
+ intent.putExtra(Service.EXTRA_TTL, getPassPhraseCacheTtl());
+ startService(intent);
}
public int getDefaultEncryptionAlgorithm() {
diff --git a/src/org/thialfihar/android/apg/PreferencesActivity.java b/src/org/thialfihar/android/apg/PreferencesActivity.java
index fae63d63b..e80e1ad5f 100644
--- a/src/org/thialfihar/android/apg/PreferencesActivity.java
+++ b/src/org/thialfihar/android/apg/PreferencesActivity.java
@@ -50,7 +50,6 @@ public class PreferencesActivity extends BaseActivity {
new Choice(180, getString(R.string.choice_3mins)),
new Choice(300, getString(R.string.choice_5mins)),
new Choice(600, getString(R.string.choice_10mins)),
- new Choice(0, getString(R.string.choice_untilQuit)),
};
ArrayAdapter<Choice> adapter =
new ArrayAdapter<Choice>(this, android.R.layout.simple_spinner_item, choices);
diff --git a/src/org/thialfihar/android/apg/Service.java b/src/org/thialfihar/android/apg/Service.java
new file mode 100644
index 000000000..2c8fd8496
--- /dev/null
+++ b/src/org/thialfihar/android/apg/Service.java
@@ -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;
+ }
+}