From 0d01feebc333cca0bde1a25da2484204d828b859 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Thu, 27 Nov 2014 15:24:26 -0800 Subject: [PATCH] Move directory refresh from a service over to a job. // FREEBIE --- .../api/TextSecureAccountManager.java | 6 +- .../internal/push/PushServiceSocket.java | 17 ++--- .../securesms/jobs/DirectoryRefreshJob.java | 46 +++++++++++++ .../service/DirectoryRefreshListener.java | 8 ++- .../service/DirectoryRefreshService.java | 64 ------------------- .../securesms/util/DirectoryHelper.java | 21 +++--- 6 files changed, 76 insertions(+), 86 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java delete mode 100644 src/org/thoughtcrime/securesms/service/DirectoryRefreshService.java diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureAccountManager.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureAccountManager.java index d912d3ba8..03b397c02 100644 --- a/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureAccountManager.java +++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/api/TextSecureAccountManager.java @@ -22,6 +22,8 @@ import org.whispersystems.libaxolotl.state.SignedPreKeyRecord; import org.whispersystems.libaxolotl.util.guava.Optional; import org.whispersystems.textsecure.api.push.ContactTokenDetails; import org.whispersystems.textsecure.api.push.TrustStore; +import org.whispersystems.textsecure.api.push.exceptions.NonSuccessfulResponseCodeException; +import org.whispersystems.textsecure.api.push.exceptions.PushNetworkException; import org.whispersystems.textsecure.internal.push.PushServiceSocket; import org.whispersystems.textsecure.api.push.SignedPreKeyEntity; @@ -86,7 +88,9 @@ public class TextSecureAccountManager { return Optional.fromNullable(this.pushServiceSocket.getContactTokenDetails(contactToken)); } - public List getContacts(Set contactTokens) { + public List getContacts(Set contactTokens) + throws IOException + { return this.pushServiceSocket.retrieveDirectory(contactTokens); } diff --git a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java index 6b5ef6deb..3cfa3ff4e 100644 --- a/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java +++ b/libtextsecure/src/main/java/org/whispersystems/textsecure/internal/push/PushServiceSocket.java @@ -321,17 +321,14 @@ public class PushServiceSocket { downloadExternalFile(descriptor.getLocation(), destination); } - public List retrieveDirectory(Set contactTokens) { - try { - ContactTokenList contactTokenList = new ContactTokenList(new LinkedList(contactTokens)); - String response = makeRequest(DIRECTORY_TOKENS_PATH, "PUT", new Gson().toJson(contactTokenList)); - ContactTokenDetailsList activeTokens = new Gson().fromJson(response, ContactTokenDetailsList.class); + public List retrieveDirectory(Set contactTokens) + throws NonSuccessfulResponseCodeException, PushNetworkException + { + ContactTokenList contactTokenList = new ContactTokenList(new LinkedList<>(contactTokens)); + String response = makeRequest(DIRECTORY_TOKENS_PATH, "PUT", new Gson().toJson(contactTokenList)); + ContactTokenDetailsList activeTokens = new Gson().fromJson(response, ContactTokenDetailsList.class); - return activeTokens.getContacts(); - } catch (IOException ioe) { - Log.w("PushServiceSocket", ioe); - return null; - } + return activeTokens.getContacts(); } public ContactTokenDetails getContactTokenDetails(String contactToken) throws IOException { diff --git a/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java b/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java new file mode 100644 index 000000000..0cb6580b9 --- /dev/null +++ b/src/org/thoughtcrime/securesms/jobs/DirectoryRefreshJob.java @@ -0,0 +1,46 @@ +package org.thoughtcrime.securesms.jobs; + +import android.content.Context; +import android.os.PowerManager; + +import org.thoughtcrime.securesms.util.DirectoryHelper; +import org.whispersystems.jobqueue.JobParameters; +import org.whispersystems.jobqueue.requirements.NetworkRequirement; +import org.whispersystems.textsecure.api.push.exceptions.PushNetworkException; + +import java.io.IOException; + +public class DirectoryRefreshJob extends ContextJob { + + public DirectoryRefreshJob(Context context) { + super(context, JobParameters.newBuilder() + .withGroupId(DirectoryRefreshJob.class.getSimpleName()) + .withRequirement(new NetworkRequirement(context)) + .create()); + } + + @Override + public void onAdded() {} + + @Override + public void onRun() throws IOException { + PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Directory Refresh"); + + try { + wakeLock.acquire(); + DirectoryHelper.refreshDirectory(context); + } finally { + if (wakeLock.isHeld()) wakeLock.release(); + } + } + + @Override + public boolean onShouldRetry(Exception exception) { + if (exception instanceof PushNetworkException) return true; + return false; + } + + @Override + public void onCanceled() {} +} diff --git a/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java b/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java index d9d9d8288..03e633a58 100644 --- a/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java +++ b/src/org/thoughtcrime/securesms/service/DirectoryRefreshListener.java @@ -8,6 +8,8 @@ import android.content.Context; import android.content.Intent; import android.util.Log; +import org.thoughtcrime.securesms.ApplicationContext; +import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; import org.thoughtcrime.securesms.util.TextSecurePreferences; public class DirectoryRefreshListener extends BroadcastReceiver { @@ -41,9 +43,9 @@ public class DirectoryRefreshListener extends BroadcastReceiver { if (time <= System.currentTimeMillis()) { if (time != 0) { - Intent serviceIntent = new Intent(context, DirectoryRefreshService.class); - serviceIntent.setAction(DirectoryRefreshService.REFRESH_ACTION); - context.startService(serviceIntent); + ApplicationContext.getInstance(context) + .getJobManager() + .add(new DirectoryRefreshJob(context)); } time = System.currentTimeMillis() + INTERVAL; diff --git a/src/org/thoughtcrime/securesms/service/DirectoryRefreshService.java b/src/org/thoughtcrime/securesms/service/DirectoryRefreshService.java deleted file mode 100644 index 2c5b4a899..000000000 --- a/src/org/thoughtcrime/securesms/service/DirectoryRefreshService.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.thoughtcrime.securesms.service; - -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.os.IBinder; -import android.os.PowerManager; -import android.util.Log; - -import org.thoughtcrime.securesms.util.DirectoryHelper; - -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; - -public class DirectoryRefreshService extends Service { - - public static final String REFRESH_ACTION = "org.whispersystems.whisperpush.REFRESH_ACTION"; - - private static final Executor executor = Executors.newSingleThreadExecutor(); - - @Override - public int onStartCommand (Intent intent, int flags, int startId) { - if (REFRESH_ACTION.equals(intent.getAction())) { - handleRefreshAction(); - } - return START_NOT_STICKY; - } - - @Override - public IBinder onBind(Intent intent) { - return null; - } - - private void handleRefreshAction() { - PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); - PowerManager.WakeLock wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Directory Refresh"); - wakeLock.acquire(); - - executor.execute(new RefreshRunnable(wakeLock)); - } - - private class RefreshRunnable implements Runnable { - private final PowerManager.WakeLock wakeLock; - private final Context context; - - public RefreshRunnable(PowerManager.WakeLock wakeLock) { - this.wakeLock = wakeLock; - this.context = DirectoryRefreshService.this.getApplicationContext(); - } - - public void run() { - try { - Log.w("DirectoryRefreshService", "Refreshing directory..."); - - DirectoryHelper.refreshDirectory(context); - - Log.w("DirectoryRefreshService", "Directory refresh complete..."); - } finally { - if (wakeLock != null && wakeLock.isHeld()) - wakeLock.release(); - } - } - } -} diff --git a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java index f152aa102..aeb5216cf 100644 --- a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java +++ b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java @@ -13,6 +13,7 @@ import org.whispersystems.textsecure.api.TextSecureAccountManager; import org.whispersystems.textsecure.api.push.ContactTokenDetails; import org.whispersystems.textsecure.api.util.InvalidNumberException; +import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Set; @@ -20,10 +21,6 @@ import java.util.Set; public class DirectoryHelper { private static final String TAG = DirectoryHelper.class.getSimpleName(); - public static void refreshDirectoryWithProgressDialog(final Context context) { - refreshDirectoryWithProgressDialog(context, null); - } - public static void refreshDirectoryWithProgressDialog(final Context context, final DirectoryUpdateFinishedListener listener) { if (!TextSecurePreferences.isPushRegistered(context)) { Toast.makeText(context.getApplicationContext(), @@ -38,7 +35,11 @@ public class DirectoryHelper { { @Override protected Void doInBackground(Void... voids) { - DirectoryHelper.refreshDirectory(context.getApplicationContext()); + try { + DirectoryHelper.refreshDirectory(context.getApplicationContext()); + } catch (IOException e) { + Log.w(TAG, e); + } return null; } @@ -51,15 +52,19 @@ public class DirectoryHelper { } - public static void refreshDirectory(final Context context) { + public static void refreshDirectory(final Context context) throws IOException { refreshDirectory(context, TextSecureCommunicationFactory.createManager(context)); } - public static void refreshDirectory(final Context context, final TextSecureAccountManager accountManager) { + public static void refreshDirectory(final Context context, final TextSecureAccountManager accountManager) + throws IOException + { refreshDirectory(context, accountManager, TextSecurePreferences.getLocalNumber(context)); } - public static void refreshDirectory(final Context context, final TextSecureAccountManager accountManager, final String localNumber) { + public static void refreshDirectory(final Context context, final TextSecureAccountManager accountManager, final String localNumber) + throws IOException + { TextSecureDirectory directory = TextSecureDirectory.getInstance(context); Set eligibleContactNumbers = directory.getPushEligibleContactNumbers(localNumber); Map tokenMap = DirectoryUtil.getDirectoryServerTokenMap(eligibleContactNumbers);