Added UI thread methods to AndroidExecutor.

This commit is contained in:
akwizgran
2016-08-20 17:06:52 +01:00
parent dbdf567d4e
commit 28be7d5de3
10 changed files with 97 additions and 45 deletions

View File

@@ -9,6 +9,7 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.support.annotation.UiThread;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder; import android.support.v4.app.TaskStackBuilder;
@@ -105,7 +106,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
private final BroadcastReceiver receiver = new DeleteIntentReceiver(); private final BroadcastReceiver receiver = new DeleteIntentReceiver();
private final AtomicBoolean used = new AtomicBoolean(false); private final AtomicBoolean used = new AtomicBoolean(false);
// The following must only be accessed on the AndroidExecutor thread // The following must only be accessed on the main UI thread
private final Map<GroupId, Integer> contactCounts = new HashMap<>(); private final Map<GroupId, Integer> contactCounts = new HashMap<>();
private final Map<GroupId, Integer> forumCounts = new HashMap<>(); private final Map<GroupId, Integer> forumCounts = new HashMap<>();
private final Map<GroupId, Integer> blogCounts = new HashMap<>(); private final Map<GroupId, Integer> blogCounts = new HashMap<>();
@@ -139,7 +140,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
throw new ServiceException(e); throw new ServiceException(e);
} }
// Register a broadcast receiver for notifications being dismissed // Register a broadcast receiver for notifications being dismissed
Future<Void> f = androidExecutor.submit(new Callable<Void>() { Future<Void> f = androidExecutor.runOnUiThread(new Callable<Void>() {
@Override @Override
public Void call() { public Void call() {
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
@@ -161,7 +162,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void stopService() throws ServiceException { public void stopService() throws ServiceException {
// Clear all notifications and unregister the broadcast receiver // Clear all notifications and unregister the broadcast receiver
Future<Void> f = androidExecutor.submit(new Callable<Void>() { Future<Void> f = androidExecutor.runOnUiThread(new Callable<Void>() {
@Override @Override
public Void call() { public Void call() {
clearPrivateMessageNotification(); clearPrivateMessageNotification();
@@ -179,6 +180,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
} }
} }
@UiThread
private void clearPrivateMessageNotification() { private void clearPrivateMessageNotification() {
contactCounts.clear(); contactCounts.clear();
contactTotal = 0; contactTotal = 0;
@@ -187,6 +189,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
nm.cancel(PRIVATE_MESSAGE_NOTIFICATION_ID); nm.cancel(PRIVATE_MESSAGE_NOTIFICATION_ID);
} }
@UiThread
private void clearForumPostNotification() { private void clearForumPostNotification() {
forumCounts.clear(); forumCounts.clear();
forumTotal = 0; forumTotal = 0;
@@ -195,6 +198,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
nm.cancel(FORUM_POST_NOTIFICATION_ID); nm.cancel(FORUM_POST_NOTIFICATION_ID);
} }
@UiThread
private void clearBlogPostNotification() { private void clearBlogPostNotification() {
blogCounts.clear(); blogCounts.clear();
blogTotal = 0; blogTotal = 0;
@@ -203,6 +207,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
nm.cancel(BLOG_POST_NOTIFICATION_ID); nm.cancel(BLOG_POST_NOTIFICATION_ID);
} }
@UiThread
private void clearIntroductionSuccessNotification() { private void clearIntroductionSuccessNotification() {
introductionTotal = 0; introductionTotal = 0;
Object o = appContext.getSystemService(NOTIFICATION_SERVICE); Object o = appContext.getSystemService(NOTIFICATION_SERVICE);
@@ -256,7 +261,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
} }
private void showPrivateMessageNotification(final GroupId g) { private void showPrivateMessageNotification(final GroupId g) {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (blockContacts) return; if (blockContacts) return;
@@ -272,7 +277,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearPrivateMessageNotification(final GroupId g) { public void clearPrivateMessageNotification(final GroupId g) {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
Integer count = contactCounts.remove(g); Integer count = contactCounts.remove(g);
@@ -283,6 +288,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
}); });
} }
@UiThread
private void updatePrivateMessageNotification() { private void updatePrivateMessageNotification() {
if (contactTotal == 0) { if (contactTotal == 0) {
clearPrivateMessageNotification(); clearPrivateMessageNotification();
@@ -339,6 +345,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
} }
} }
@UiThread
private int getDefaults() { private int getDefaults() {
int defaults = DEFAULT_LIGHTS; int defaults = DEFAULT_LIGHTS;
boolean sound = settings.getBoolean("notifySound", true); boolean sound = settings.getBoolean("notifySound", true);
@@ -352,7 +359,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearAllContactNotifications() { public void clearAllContactNotifications() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
clearPrivateMessageNotification(); clearPrivateMessageNotification();
@@ -361,8 +368,9 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
}); });
} }
@UiThread
private void showForumPostNotification(final GroupId g) { private void showForumPostNotification(final GroupId g) {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (blockForums) return; if (blockForums) return;
@@ -378,7 +386,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearForumPostNotification(final GroupId g) { public void clearForumPostNotification(final GroupId g) {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
Integer count = forumCounts.remove(g); Integer count = forumCounts.remove(g);
@@ -389,6 +397,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
}); });
} }
@UiThread
private void updateForumPostNotification() { private void updateForumPostNotification() {
if (forumTotal == 0) { if (forumTotal == 0) {
clearForumPostNotification(); clearForumPostNotification();
@@ -446,7 +455,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearAllForumPostNotifications() { public void clearAllForumPostNotifications() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
clearForumPostNotification(); clearForumPostNotification();
@@ -454,8 +463,9 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
}); });
} }
@UiThread
private void showBlogPostNotification(final GroupId g) { private void showBlogPostNotification(final GroupId g) {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (blockBlogs) return; if (blockBlogs) return;
@@ -471,7 +481,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearBlogPostNotification(final GroupId g) { public void clearBlogPostNotification(final GroupId g) {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
Integer count = blogCounts.remove(g); Integer count = blogCounts.remove(g);
@@ -482,6 +492,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
}); });
} }
@UiThread
private void updateBlogPostNotification() { private void updateBlogPostNotification() {
if (blogTotal == 0) { if (blogTotal == 0) {
clearBlogPostNotification(); clearBlogPostNotification();
@@ -525,7 +536,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void clearAllBlogPostNotifications() { public void clearAllBlogPostNotifications() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
clearBlogPostNotification(); clearBlogPostNotification();
@@ -534,7 +545,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
} }
private void showIntroductionNotification() { private void showIntroductionNotification() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (blockIntroductions) return; if (blockIntroductions) return;
@@ -544,6 +555,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
}); });
} }
@UiThread
private void updateIntroductionNotification() { private void updateIntroductionNotification() {
NotificationCompat.Builder b = NotificationCompat.Builder b =
new NotificationCompat.Builder(appContext); new NotificationCompat.Builder(appContext);
@@ -583,7 +595,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void blockNotification(final GroupId g) { public void blockNotification(final GroupId g) {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
blockedGroup = g; blockedGroup = g;
@@ -593,7 +605,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void unblockNotification(final GroupId g) { public void unblockNotification(final GroupId g) {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (g.equals(blockedGroup)) blockedGroup = null; if (g.equals(blockedGroup)) blockedGroup = null;
@@ -603,7 +615,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void blockAllContactNotifications() { public void blockAllContactNotifications() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
blockContacts = true; blockContacts = true;
@@ -614,7 +626,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void unblockAllContactNotifications() { public void unblockAllContactNotifications() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
blockContacts = false; blockContacts = false;
@@ -625,7 +637,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void blockAllForumPostNotifications() { public void blockAllForumPostNotifications() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
blockForums = true; blockForums = true;
@@ -635,7 +647,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void unblockAllForumPostNotifications() { public void unblockAllForumPostNotifications() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
blockForums = false; blockForums = false;
@@ -645,7 +657,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void blockAllBlogPostNotifications() { public void blockAllBlogPostNotifications() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
blockBlogs = true; blockBlogs = true;
@@ -655,7 +667,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void unblockAllBlogPostNotifications() { public void unblockAllBlogPostNotifications() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
blockBlogs = false; blockBlogs = false;
@@ -683,7 +695,7 @@ class AndroidNotificationManagerImpl implements AndroidNotificationManager,
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
final String action = intent.getAction(); final String action = intent.getAction();
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
if (CLEAR_PRIVATE_MESSAGE_ACTION.equals(action)) { if (CLEAR_PRIVATE_MESSAGE_ACTION.equals(action)) {

View File

@@ -108,7 +108,8 @@ public class BriarService extends Service {
} }
private void showStartupFailureNotification(final StartResult result) { private void showStartupFailureNotification(final StartResult result) {
androidExecutor.execute(new Runnable() { androidExecutor.runOnUiThread(new Runnable() {
@Override
public void run() { public void run() {
NotificationCompat.Builder b = NotificationCompat.Builder b =
new NotificationCompat.Builder(BriarService.this); new NotificationCompat.Builder(BriarService.this);
@@ -197,11 +198,13 @@ public class BriarService extends Service {
private volatile IBinder binder = null; private volatile IBinder binder = null;
@Override
public void onServiceConnected(ComponentName name, IBinder binder) { public void onServiceConnected(ComponentName name, IBinder binder) {
this.binder = binder; this.binder = binder;
binderLatch.countDown(); binderLatch.countDown();
} }
@Override
public void onServiceDisconnected(ComponentName name) {} public void onServiceDisconnected(ComponentName name) {}
/** Waits for the service to connect and returns its binder. */ /** Waits for the service to connect and returns its binder. */

View File

@@ -87,7 +87,7 @@ public class SplashScreenActivity extends BaseActivity {
} }
private void setPreferencesDefaults() { private void setPreferencesDefaults() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnBackgroundThread(new Runnable() {
@Override @Override
public void run() { public void run() {
PreferenceManager.setDefaultValues(SplashScreenActivity.this, PreferenceManager.setDefaultValues(SplashScreenActivity.this,

View File

@@ -13,10 +13,21 @@ public interface AndroidExecutor {
* Runs the given task on a background thread with a message queue and * Runs the given task on a background thread with a message queue and
* returns a Future for getting the result. * returns a Future for getting the result.
*/ */
<V> Future<V> submit(Callable<V> c); <V> Future<V> runOnBackgroundThread(Callable<V> c);
/** /**
* Runs the given task on a background thread with a message queue. * Runs the given task on a background thread with a message queue.
*/ */
void execute(Runnable r); void runOnBackgroundThread(Runnable r);
/**
* Runs the given task on the main UI thread and returns a Future for
* getting the result.
*/
<V> Future<V> runOnUiThread(Callable<V> c);
/**
* Runs the given task on the main UI thread.
*/
void runOnUiThread(Runnable r);
} }

View File

@@ -173,6 +173,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
private void loadSettings() { private void loadSettings() {
listener.runOnDbThread(new Runnable() { listener.runOnDbThread(new Runnable() {
@Override
public void run() { public void run() {
try { try {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
@@ -195,6 +196,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
private void displaySettings() { private void displaySettings() {
listener.runOnUiThread(new Runnable() { listener.runOnUiThread(new Runnable() {
@Override
public void run() { public void run() {
enableBluetooth.setValue(Boolean.toString(bluetoothSetting)); enableBluetooth.setValue(Boolean.toString(bluetoothSetting));
torOverMobile.setValue(Boolean.toString(torSetting)); torOverMobile.setValue(Boolean.toString(torSetting));
@@ -228,7 +230,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
} }
private void triggerFeedback() { private void triggerFeedback() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnBackgroundThread(new Runnable() {
@Override
public void run() { public void run() {
ACRA.getErrorReporter().handleException(new UserFeedback(), ACRA.getErrorReporter().handleException(new UserFeedback(),
false); false);
@@ -268,7 +271,8 @@ public class SettingsFragment extends PreferenceFragmentCompat
private void enableOrDisableBluetooth(final boolean enable) { private void enableOrDisableBluetooth(final boolean enable) {
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null) { if (adapter != null) {
androidExecutor.execute(new Runnable() { androidExecutor.runOnBackgroundThread(new Runnable() {
@Override
public void run() { public void run() {
if (enable) adapter.enable(); if (enable) adapter.enable();
else adapter.disable(); else adapter.disable();
@@ -279,6 +283,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
private void storeTorSettings() { private void storeTorSettings() {
listener.runOnDbThread(new Runnable() { listener.runOnDbThread(new Runnable() {
@Override
public void run() { public void run() {
try { try {
Settings s = new Settings(); Settings s = new Settings();
@@ -298,6 +303,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
private void storeBluetoothSettings() { private void storeBluetoothSettings() {
listener.runOnDbThread(new Runnable() { listener.runOnDbThread(new Runnable() {
@Override
public void run() { public void run() {
try { try {
Settings s = new Settings(); Settings s = new Settings();
@@ -317,6 +323,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
private void storeSettings(final Settings settings) { private void storeSettings(final Settings settings) {
listener.runOnDbThread(new Runnable() { listener.runOnDbThread(new Runnable() {
@Override
public void run() { public void run() {
try { try {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();

View File

@@ -144,7 +144,7 @@ public class ShowQrCodeFragment extends BaseEventFragment
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null && !adapter.isEnabled()) { if (adapter != null && !adapter.isEnabled()) {
waitingForBluetooth = true; waitingForBluetooth = true;
androidExecutor.execute(new Runnable() { androidExecutor.runOnBackgroundThread(new Runnable() {
@Override @Override
public void run() { public void run() {
adapter.enable(); adapter.enable();

View File

@@ -107,7 +107,7 @@ public class PanicResponderActivity extends BriarActivity {
} }
private void deleteAllData() { private void deleteAllData() {
androidExecutor.execute(new Runnable() { androidExecutor.runOnBackgroundThread(new Runnable() {
@Override @Override
public void run() { public void run() {
configController.deleteAccount(PanicResponderActivity.this); configController.deleteAccount(PanicResponderActivity.this);

View File

@@ -125,12 +125,13 @@ class DroidtoothPlugin implements DuplexPlugin {
// BluetoothAdapter.getDefaultAdapter() must be called on a thread // BluetoothAdapter.getDefaultAdapter() must be called on a thread
// with a message queue, so submit it to the AndroidExecutor // with a message queue, so submit it to the AndroidExecutor
try { try {
adapter = androidExecutor.submit(new Callable<BluetoothAdapter>() { adapter = androidExecutor.runOnBackgroundThread(
@Override new Callable<BluetoothAdapter>() {
public BluetoothAdapter call() throws Exception { @Override
return BluetoothAdapter.getDefaultAdapter(); public BluetoothAdapter call() throws Exception {
} return BluetoothAdapter.getDefaultAdapter();
}).get(); }
}).get();
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
throw new IOException("Interrupted while getting BluetoothAdapter"); throw new IOException("Interrupted while getting BluetoothAdapter");

View File

@@ -1,5 +1,6 @@
package org.briarproject.system; package org.briarproject.system;
import android.app.Application;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
@@ -16,18 +17,21 @@ import javax.inject.Inject;
class AndroidExecutorImpl implements AndroidExecutor { class AndroidExecutorImpl implements AndroidExecutor {
private final Handler uiHandler;
private final Runnable loop; private final Runnable loop;
private final AtomicBoolean started = new AtomicBoolean(false); private final AtomicBoolean started = new AtomicBoolean(false);
private final CountDownLatch startLatch = new CountDownLatch(1); private final CountDownLatch startLatch = new CountDownLatch(1);
private volatile Handler handler = null; private volatile Handler backgroundHandler = null;
@Inject @Inject
AndroidExecutorImpl() { AndroidExecutorImpl(Application app) {
uiHandler = new Handler(app.getApplicationContext().getMainLooper());
loop = new Runnable() { loop = new Runnable() {
@Override
public void run() { public void run() {
Looper.prepare(); Looper.prepare();
handler = new Handler(); backgroundHandler = new Handler();
startLatch.countDown(); startLatch.countDown();
Looper.loop(); Looper.loop();
} }
@@ -46,14 +50,28 @@ class AndroidExecutorImpl implements AndroidExecutor {
} }
} }
public <V> Future<V> submit(Callable<V> c) { @Override
public <V> Future<V> runOnBackgroundThread(Callable<V> c) {
FutureTask<V> f = new FutureTask<>(c); FutureTask<V> f = new FutureTask<>(c);
execute(f); runOnBackgroundThread(f);
return f; return f;
} }
public void execute(Runnable r) { @Override
public void runOnBackgroundThread(Runnable r) {
startIfNecessary(); startIfNecessary();
handler.post(r); backgroundHandler.post(r);
}
@Override
public <V> Future<V> runOnUiThread(Callable<V> c) {
FutureTask<V> f = new FutureTask<>(c);
runOnUiThread(f);
return f;
}
@Override
public void runOnUiThread(Runnable r) {
uiHandler.post(r);
} }
} }

View File

@@ -27,7 +27,7 @@ public class AndroidSystemModule {
@Provides @Provides
@Singleton @Singleton
public AndroidExecutor provideAndroidExecutor() { public AndroidExecutor provideAndroidExecutor(Application app) {
return new AndroidExecutorImpl(); return new AndroidExecutorImpl(app);
} }
} }