2012-08-03 03:23:41 +00:00
|
|
|
package org.thoughtcrime.securesms.service;
|
|
|
|
|
|
|
|
import android.app.Notification;
|
|
|
|
import android.app.NotificationManager;
|
|
|
|
import android.app.PendingIntent;
|
|
|
|
import android.app.Service;
|
2013-02-17 19:42:30 +00:00
|
|
|
import android.content.BroadcastReceiver;
|
2012-08-03 03:23:41 +00:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
2013-02-17 19:42:30 +00:00
|
|
|
import android.content.IntentFilter;
|
|
|
|
import android.graphics.BitmapFactory;
|
2012-08-03 03:23:41 +00:00
|
|
|
import android.os.Binder;
|
|
|
|
import android.os.Handler;
|
|
|
|
import android.os.IBinder;
|
|
|
|
import android.os.PowerManager;
|
|
|
|
import android.os.PowerManager.WakeLock;
|
2013-02-17 19:42:30 +00:00
|
|
|
import android.support.v4.app.NotificationCompat;
|
|
|
|
import android.util.Log;
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2014-12-15 20:25:55 +00:00
|
|
|
import org.thoughtcrime.securesms.ConversationListActivity;
|
2012-08-03 03:23:41 +00:00
|
|
|
import org.thoughtcrime.securesms.R;
|
2014-11-03 23:16:04 +00:00
|
|
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
2012-08-03 03:23:41 +00:00
|
|
|
import org.thoughtcrime.securesms.database.SmsMigrator;
|
2013-02-17 19:42:30 +00:00
|
|
|
import org.thoughtcrime.securesms.database.SmsMigrator.ProgressDescription;
|
|
|
|
|
2015-06-12 20:54:47 +00:00
|
|
|
import java.lang.ref.WeakReference;
|
2013-02-17 19:42:30 +00:00
|
|
|
import java.util.concurrent.Executor;
|
|
|
|
import java.util.concurrent.Executors;
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2015-06-12 20:54:47 +00:00
|
|
|
// FIXME: This class is nuts.
|
2012-08-03 03:23:41 +00:00
|
|
|
public class ApplicationMigrationService extends Service
|
|
|
|
implements SmsMigrator.SmsMigrationProgressListener
|
2014-12-15 20:25:55 +00:00
|
|
|
{
|
|
|
|
private static final String TAG = ApplicationMigrationService.class.getSimpleName();
|
2013-02-17 19:42:30 +00:00
|
|
|
public static final String MIGRATE_DATABASE = "org.thoughtcrime.securesms.ApplicationMigration.MIGRATE_DATABSE";
|
|
|
|
public static final String COMPLETED_ACTION = "org.thoughtcrime.securesms.ApplicationMigrationService.COMPLETED";
|
|
|
|
private static final String PREFERENCES_NAME = "SecureSMS";
|
|
|
|
private static final String DATABASE_MIGRATED = "migrated";
|
|
|
|
|
|
|
|
private final BroadcastReceiver completedReceiver = new CompletedReceiver();
|
|
|
|
private final Binder binder = new ApplicationMigrationBinder();
|
|
|
|
private final Executor executor = Executors.newSingleThreadExecutor();
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2015-06-12 20:54:47 +00:00
|
|
|
private WeakReference<Handler> handler = null;
|
2013-02-17 19:42:30 +00:00
|
|
|
private NotificationCompat.Builder notification = null;
|
2015-06-12 20:54:47 +00:00
|
|
|
private ImportState state = new ImportState(ImportState.STATE_IDLE, null);
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
@Override
|
|
|
|
public void onCreate() {
|
|
|
|
registerCompletedReceiver();
|
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
|
|
|
|
@Override
|
2013-02-17 19:42:30 +00:00
|
|
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
|
|
|
if (intent == null) return START_NOT_STICKY;
|
2012-08-05 19:41:31 +00:00
|
|
|
|
2012-08-03 03:23:41 +00:00
|
|
|
if (intent.getAction() != null && intent.getAction().equals(MIGRATE_DATABASE)) {
|
2013-02-17 19:42:30 +00:00
|
|
|
executor.execute(new ImportRunnable(intent));
|
2012-08-03 03:23:41 +00:00
|
|
|
}
|
2013-02-17 19:42:30 +00:00
|
|
|
|
|
|
|
return START_NOT_STICKY;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroy() {
|
|
|
|
unregisterCompletedReceiver();
|
2012-08-03 03:23:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public IBinder onBind(Intent intent) {
|
|
|
|
return binder;
|
|
|
|
}
|
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
public void setImportStateHandler(Handler handler) {
|
2015-06-12 20:54:47 +00:00
|
|
|
this.handler = new WeakReference<>(handler);
|
2013-02-17 19:42:30 +00:00
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
private void registerCompletedReceiver() {
|
|
|
|
IntentFilter filter = new IntentFilter();
|
|
|
|
filter.addAction(COMPLETED_ACTION);
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
registerReceiver(completedReceiver, filter);
|
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
private void unregisterCompletedReceiver() {
|
|
|
|
unregisterReceiver(completedReceiver);
|
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
private void notifyImportComplete() {
|
|
|
|
Intent intent = new Intent();
|
|
|
|
intent.setAction(COMPLETED_ACTION);
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
sendOrderedBroadcast(intent, null);
|
2012-08-03 03:23:41 +00:00
|
|
|
}
|
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
@Override
|
|
|
|
public void progressUpdate(ProgressDescription progress) {
|
|
|
|
setState(new ImportState(ImportState.STATE_MIGRATING_IN_PROGRESS, progress));
|
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
public ImportState getState() {
|
|
|
|
return state;
|
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
private void setState(ImportState state) {
|
|
|
|
this.state = state;
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2015-06-23 01:03:58 +00:00
|
|
|
if (this.handler != null) {
|
|
|
|
Handler handler = this.handler.get();
|
2015-06-12 20:54:47 +00:00
|
|
|
|
2015-06-23 01:03:58 +00:00
|
|
|
if (handler != null) {
|
|
|
|
handler.obtainMessage(state.state, state.progress).sendToTarget();
|
|
|
|
}
|
2013-02-17 19:42:30 +00:00
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
if (state.progress != null && state.progress.secondaryComplete == 0) {
|
|
|
|
updateBackgroundNotification(state.progress.primaryTotal, state.progress.primaryComplete);
|
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
}
|
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
private void updateBackgroundNotification(int total, int complete) {
|
|
|
|
notification.setProgress(total, complete, false);
|
|
|
|
|
|
|
|
((NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE))
|
|
|
|
.notify(4242, notification.build());
|
2012-08-03 03:23:41 +00:00
|
|
|
}
|
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
private NotificationCompat.Builder initializeBackgroundNotification() {
|
|
|
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
|
|
|
|
|
|
|
|
builder.setSmallIcon(R.drawable.icon_notification);
|
|
|
|
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_notification));
|
|
|
|
builder.setContentTitle(getString(R.string.ApplicationMigrationService_importing_text_messages));
|
|
|
|
builder.setContentText(getString(R.string.ApplicationMigrationService_import_in_progress));
|
|
|
|
builder.setOngoing(true);
|
|
|
|
builder.setProgress(100, 0, false);
|
2014-12-15 20:25:55 +00:00
|
|
|
builder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, ConversationListActivity.class), 0));
|
2013-02-17 19:42:30 +00:00
|
|
|
|
|
|
|
stopForeground(true);
|
|
|
|
startForeground(4242, builder.build());
|
|
|
|
|
|
|
|
return builder;
|
2012-08-03 03:23:41 +00:00
|
|
|
}
|
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
private class ImportRunnable implements Runnable {
|
|
|
|
private final MasterSecret masterSecret;
|
|
|
|
|
|
|
|
public ImportRunnable(Intent intent) {
|
|
|
|
this.masterSecret = intent.getParcelableExtra("master_secret");
|
2014-12-15 20:25:55 +00:00
|
|
|
Log.w(TAG, "Service got mastersecret: " + masterSecret);
|
2013-02-17 19:42:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void run() {
|
|
|
|
notification = initializeBackgroundNotification();
|
|
|
|
PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
|
|
|
|
WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Migration");
|
|
|
|
|
|
|
|
try {
|
|
|
|
wakeLock.acquire();
|
|
|
|
|
|
|
|
setState(new ImportState(ImportState.STATE_MIGRATING_BEGIN, null));
|
|
|
|
|
|
|
|
SmsMigrator.migrateDatabase(ApplicationMigrationService.this,
|
|
|
|
masterSecret,
|
|
|
|
ApplicationMigrationService.this);
|
|
|
|
|
|
|
|
setState(new ImportState(ImportState.STATE_MIGRATING_COMPLETE, null));
|
|
|
|
|
|
|
|
setDatabaseImported(ApplicationMigrationService.this);
|
|
|
|
stopForeground(true);
|
|
|
|
notifyImportComplete();
|
|
|
|
stopSelf();
|
|
|
|
} finally {
|
|
|
|
wakeLock.release();
|
|
|
|
}
|
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public class ApplicationMigrationBinder extends Binder {
|
|
|
|
public ApplicationMigrationService getService() {
|
|
|
|
return ApplicationMigrationService.this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-12 23:22:08 +00:00
|
|
|
private static class CompletedReceiver extends BroadcastReceiver {
|
2013-02-17 19:42:30 +00:00
|
|
|
@Override
|
|
|
|
public void onReceive(Context context, Intent intent) {
|
|
|
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
|
|
|
|
builder.setSmallIcon(R.drawable.icon_notification);
|
|
|
|
builder.setContentTitle("Import Complete");
|
|
|
|
builder.setContentText("TextSecure system database import is complete.");
|
2014-12-15 20:25:55 +00:00
|
|
|
builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, ConversationListActivity.class), 0));
|
2013-02-17 19:42:30 +00:00
|
|
|
builder.setWhen(System.currentTimeMillis());
|
|
|
|
builder.setDefaults(Notification.DEFAULT_VIBRATE);
|
|
|
|
builder.setAutoCancel(true);
|
|
|
|
|
|
|
|
Notification notification = builder.build();
|
|
|
|
((NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE)).notify(31337, notification);
|
2012-08-03 03:23:41 +00:00
|
|
|
}
|
2013-02-17 19:42:30 +00:00
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
public static class ImportState {
|
|
|
|
public static final int STATE_IDLE = 0;
|
|
|
|
public static final int STATE_MIGRATING_BEGIN = 1;
|
|
|
|
public static final int STATE_MIGRATING_IN_PROGRESS = 2;
|
|
|
|
public static final int STATE_MIGRATING_COMPLETE = 3;
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
public int state;
|
|
|
|
public ProgressDescription progress;
|
2012-08-03 03:23:41 +00:00
|
|
|
|
2013-02-17 19:42:30 +00:00
|
|
|
public ImportState(int state, ProgressDescription progress) {
|
|
|
|
this.state = state;
|
|
|
|
this.progress = progress;
|
2012-08-03 03:23:41 +00:00
|
|
|
}
|
|
|
|
}
|
2013-02-17 19:42:30 +00:00
|
|
|
|
|
|
|
public static boolean isDatabaseImported(Context context) {
|
|
|
|
return context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_PRIVATE)
|
|
|
|
.getBoolean(DATABASE_MIGRATED, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void setDatabaseImported(Context context) {
|
2014-05-05 18:48:26 +00:00
|
|
|
context.getSharedPreferences(PREFERENCES_NAME, 0).edit().putBoolean(DATABASE_MIGRATED, true).apply();
|
2013-02-17 19:42:30 +00:00
|
|
|
}
|
2012-08-03 03:23:41 +00:00
|
|
|
}
|