From 049ba6a7060cec7e13f09909e2b3fa2e92b8a7ba Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 4 Nov 2021 09:58:13 -0400 Subject: [PATCH] Remove WorkManager migration that is no longer necessary. We migrated away from WorkManager over 2 years ago. We needed it at the time because we wanted to migrate jobs that were scheduled on WorkManager into the new system. However, at this point, the user's client would have been expired for 2 years at the point of upgrade, and there wouldn't be any jobs that need migrating. --- .../securesms/jobmanager/JobManager.java | 6 - .../jobmanager/workmanager/DataMigrator.java | 169 ------------------ .../workmanager/WorkManagerDatabase.java | 102 ----------- .../WorkManagerFactoryMappings.java | 107 ----------- .../workmanager/WorkManagerMigrator.java | 46 ----- 5 files changed, 430 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/DataMigrator.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerDatabase.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerFactoryMappings.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerMigrator.java diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java index 14c090d7b..a4950c0d1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/JobManager.java @@ -14,7 +14,6 @@ import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.jobmanager.impl.DefaultExecutorFactory; import org.thoughtcrime.securesms.jobmanager.impl.JsonDataSerializer; import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage; -import org.thoughtcrime.securesms.jobmanager.workmanager.WorkManagerMigrator; import org.thoughtcrime.securesms.util.Debouncer; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; @@ -73,11 +72,6 @@ public class JobManager implements ConstraintObserver.Notifier { executor.execute(() -> { synchronized (this) { - if (WorkManagerMigrator.needsMigration(application)) { - Log.i(TAG, "Detected an old WorkManager database. Migrating."); - WorkManagerMigrator.migrate(application, configuration.getJobStorage(), configuration.getDataSerializer()); - } - JobStorage jobStorage = configuration.getJobStorage(); jobStorage.init(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/DataMigrator.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/DataMigrator.java deleted file mode 100644 index 0aa913e05..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/DataMigrator.java +++ /dev/null @@ -1,169 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.workmanager; - -import androidx.annotation.NonNull; - -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.jobmanager.Data; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.util.HashMap; -import java.util.Map; - -/** - * Takes a persisted data blob stored by WorkManager and converts it to our {@link Data} class. - */ -final class DataMigrator { - - private static final String TAG = Log.tag(DataMigrator.class); - - static final Data convert(@NonNull byte[] workManagerData) { - Map values = parseWorkManagerDataMap(workManagerData); - - Data.Builder builder = new Data.Builder(); - - for (Map.Entry entry : values.entrySet()) { - Object value = entry.getValue(); - - if (value == null) { - builder.putString(entry.getKey(), null); - } else { - Class type = value.getClass(); - - if (type == String.class) { - builder.putString(entry.getKey(), (String) value); - } else if (type == String[].class) { - builder.putStringArray(entry.getKey(), (String[]) value); - } else if (type == Integer.class || type == int.class) { - builder.putInt(entry.getKey(), (int) value); - } else if (type == Integer[].class || type == int[].class) { - builder.putIntArray(entry.getKey(), convertToIntArray(value, type)); - } else if (type == Long.class || type == long.class) { - builder.putLong(entry.getKey(), (long) value); - } else if (type == Long[].class || type == long[].class) { - builder.putLongArray(entry.getKey(), convertToLongArray(value, type)); - } else if (type == Float.class || type == float.class) { - builder.putFloat(entry.getKey(), (float) value); - } else if (type == Float[].class || type == float[].class) { - builder.putFloatArray(entry.getKey(), convertToFloatArray(value, type)); - } else if (type == Double.class || type == double.class) { - builder.putDouble(entry.getKey(), (double) value); - } else if (type == Double[].class || type == double[].class) { - builder.putDoubleArray(entry.getKey(), convertToDoubleArray(value, type)); - } else if (type == Boolean.class || type == boolean.class) { - builder.putBoolean(entry.getKey(), (boolean) value); - } else if (type == Boolean[].class || type == boolean[].class) { - builder.putBooleanArray(entry.getKey(), convertToBooleanArray(value, type)); - } else { - Log.w(TAG, "Encountered unexpected type '" + type + "'. Skipping."); - } - } - } - - return builder.build(); - } - - private static @NonNull Map parseWorkManagerDataMap(@NonNull byte[] bytes) throws IllegalStateException { - Map map = new HashMap<>(); - ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); - ObjectInputStream objectInputStream = null; - - try { - objectInputStream = new ObjectInputStream(inputStream); - - for (int i = objectInputStream.readInt(); i > 0; i--) { - map.put(objectInputStream.readUTF(), objectInputStream.readObject()); - } - } catch (IOException | ClassNotFoundException e) { - Log.w(TAG, "Failed to read WorkManager data.", e); - } finally { - try { - inputStream.close(); - - if (objectInputStream != null) { - objectInputStream.close(); - } - } catch (IOException e) { - Log.e(TAG, "Failed to close streams after reading WorkManager data.", e); - } - } - return map; - } - - private static int[] convertToIntArray(Object value, Class type) { - if (type == int[].class) { - return (int[]) value; - } - - Integer[] casted = (Integer[]) value; - int[] output = new int[casted.length]; - - for (int i = 0; i < casted.length; i++) { - output[i] = casted[i]; - } - - return output; - } - - private static long[] convertToLongArray(Object value, Class type) { - if (type == long[].class) { - return (long[]) value; - } - - Long[] casted = (Long[]) value; - long[] output = new long[casted.length]; - - for (int i = 0; i < casted.length; i++) { - output[i] = casted[i]; - } - - return output; - } - - private static float[] convertToFloatArray(Object value, Class type) { - if (type == float[].class) { - return (float[]) value; - } - - Float[] casted = (Float[]) value; - float[] output = new float[casted.length]; - - for (int i = 0; i < casted.length; i++) { - output[i] = casted[i]; - } - - return output; - } - - private static double[] convertToDoubleArray(Object value, Class type) { - if (type == double[].class) { - return (double[]) value; - } - - Double[] casted = (Double[]) value; - double[] output = new double[casted.length]; - - for (int i = 0; i < casted.length; i++) { - output[i] = casted[i]; - } - - return output; - } - - private static boolean[] convertToBooleanArray(Object value, Class type) { - if (type == boolean[].class) { - return (boolean[]) value; - } - - Boolean[] casted = (Boolean[]) value; - boolean[] output = new boolean[casted.length]; - - for (int i = 0; i < casted.length; i++) { - output[i] = casted[i]; - } - - return output; - } -} - diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerDatabase.java deleted file mode 100644 index 70d8d8725..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerDatabase.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.workmanager; - -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.jobmanager.Data; -import org.thoughtcrime.securesms.jobmanager.Job; -import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; -import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -final class WorkManagerDatabase extends SQLiteOpenHelper { - - private static final String TAG = Log.tag(WorkManagerDatabase.class); - - static final String DB_NAME = "androidx.work.workdb"; - - WorkManagerDatabase(@NonNull Context context) { - super(context, DB_NAME, null, 5); - } - - @Override - public void onCreate(SQLiteDatabase db) { - throw new UnsupportedOperationException("We should never be creating this database, only migrating an existing one!"); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - // There's a chance that a user who hasn't upgraded in > 6 months could hit this onUpgrade path, - // but we don't use any of the columns that were added in any migrations they could hit, so we - // can ignore this. - Log.w(TAG, "Hit onUpgrade path from " + oldVersion + " to " + newVersion); - } - - @NonNull List getAllJobs(@NonNull Data.Serializer dataSerializer) { - SQLiteDatabase db = getReadableDatabase(); - String[] columns = new String[] { "id", "worker_class_name", "input", "required_network_type"}; - List fullSpecs = new LinkedList<>(); - - try (Cursor cursor = db.query("WorkSpec", columns, null, null, null, null, null)) { - while (cursor != null && cursor.moveToNext()) { - String factoryName = WorkManagerFactoryMappings.getFactoryKey(cursor.getString(cursor.getColumnIndexOrThrow("worker_class_name"))); - - if (factoryName != null) { - String id = cursor.getString(cursor.getColumnIndexOrThrow("id")); - byte[] data = cursor.getBlob(cursor.getColumnIndexOrThrow("input")); - - List constraints = new LinkedList<>(); - JobSpec jobSpec = new JobSpec(id, - factoryName, - getQueueKey(id), - System.currentTimeMillis(), - 0, - 0, - Job.Parameters.UNLIMITED, - TimeUnit.DAYS.toMillis(1), - dataSerializer.serialize(DataMigrator.convert(data)), - null, - false, - false); - - - - if (cursor.getInt(cursor.getColumnIndexOrThrow("required_network_type")) != 0) { - constraints.add(new ConstraintSpec(id, NetworkConstraint.KEY, false)); - } - - fullSpecs.add(new FullSpec(jobSpec, constraints, Collections.emptyList())); - } else { - Log.w(TAG, "Failed to find a matching factory for worker class: " + factoryName); - } - } - } - - return fullSpecs; - } - - private @Nullable String getQueueKey(@NonNull String jobId) { - String query = "work_spec_id = ?"; - String[] args = new String[] { jobId }; - - try (Cursor cursor = getReadableDatabase().query("WorkName", null, query, args, null, null, null)) { - if (cursor != null && cursor.moveToFirst()) { - return cursor.getString(cursor.getColumnIndexOrThrow("name")); - } - } - - return null; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerFactoryMappings.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerFactoryMappings.java deleted file mode 100644 index 5ed84820a..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerFactoryMappings.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.workmanager; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob; -import org.thoughtcrime.securesms.jobs.AttachmentUploadJob; -import org.thoughtcrime.securesms.jobs.AvatarGroupsV1DownloadJob; -import org.thoughtcrime.securesms.jobs.CleanPreKeysJob; -import org.thoughtcrime.securesms.jobs.CreateSignedPreKeyJob; -import org.thoughtcrime.securesms.jobs.DirectoryRefreshJob; -import org.thoughtcrime.securesms.jobs.FailingJob; -import org.thoughtcrime.securesms.jobs.FcmRefreshJob; -import org.thoughtcrime.securesms.jobs.LocalBackupJob; -import org.thoughtcrime.securesms.jobs.LocalBackupJobApi29; -import org.thoughtcrime.securesms.jobs.MmsDownloadJob; -import org.thoughtcrime.securesms.jobs.MmsReceiveJob; -import org.thoughtcrime.securesms.jobs.MmsSendJob; -import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob; -import org.thoughtcrime.securesms.jobs.MultiDeviceConfigurationUpdateJob; -import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob; -import org.thoughtcrime.securesms.jobs.MultiDeviceGroupUpdateJob; -import org.thoughtcrime.securesms.jobs.MultiDeviceProfileKeyUpdateJob; -import org.thoughtcrime.securesms.jobs.MultiDeviceReadUpdateJob; -import org.thoughtcrime.securesms.jobs.MultiDeviceVerifiedUpdateJob; -import org.thoughtcrime.securesms.jobs.PushDecryptMessageJob; -import org.thoughtcrime.securesms.jobs.PushGroupSendJob; -import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob; -import org.thoughtcrime.securesms.jobs.PushMediaSendJob; -import org.thoughtcrime.securesms.jobs.PushNotificationReceiveJob; -import org.thoughtcrime.securesms.jobs.PushTextSendJob; -import org.thoughtcrime.securesms.jobs.RefreshAttributesJob; -import org.thoughtcrime.securesms.jobs.RefreshPreKeysJob; -import org.thoughtcrime.securesms.jobs.RequestGroupInfoJob; -import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob; -import org.thoughtcrime.securesms.jobs.RetrieveProfileJob; -import org.thoughtcrime.securesms.jobs.RotateCertificateJob; -import org.thoughtcrime.securesms.jobs.RotateProfileKeyJob; -import org.thoughtcrime.securesms.jobs.RotateSignedPreKeyJob; -import org.thoughtcrime.securesms.jobs.SendDeliveryReceiptJob; -import org.thoughtcrime.securesms.jobs.SendReadReceiptJob; -import org.thoughtcrime.securesms.jobs.SendViewedReceiptJob; -import org.thoughtcrime.securesms.jobs.ServiceOutageDetectionJob; -import org.thoughtcrime.securesms.jobs.SmsReceiveJob; -import org.thoughtcrime.securesms.jobs.SmsSendJob; -import org.thoughtcrime.securesms.jobs.SmsSentJob; -import org.thoughtcrime.securesms.jobs.TrimThreadJob; -import org.thoughtcrime.securesms.jobs.TypingSendJob; -import org.thoughtcrime.securesms.jobs.UpdateApkJob; - -import java.util.HashMap; -import java.util.Map; - -public class WorkManagerFactoryMappings { - - private static final Map FACTORY_MAP = new HashMap() {{ - put("AttachmentDownloadJob", AttachmentDownloadJob.KEY); - put("AttachmentUploadJob", AttachmentUploadJob.KEY); - put("AvatarDownloadJob", AvatarGroupsV1DownloadJob.KEY); - put("CleanPreKeysJob", CleanPreKeysJob.KEY); - put("CreateSignedPreKeyJob", CreateSignedPreKeyJob.KEY); - put("DirectoryRefreshJob", DirectoryRefreshJob.KEY); - put("FcmRefreshJob", FcmRefreshJob.KEY); - put("LocalBackupJob", LocalBackupJob.KEY); - put("LocalBackupJobApi29", LocalBackupJobApi29.KEY); - put("MmsDownloadJob", MmsDownloadJob.KEY); - put("MmsReceiveJob", MmsReceiveJob.KEY); - put("MmsSendJob", MmsSendJob.KEY); - put("MultiDeviceBlockedUpdateJob", MultiDeviceBlockedUpdateJob.KEY); - put("MultiDeviceConfigurationUpdateJob", MultiDeviceConfigurationUpdateJob.KEY); - put("MultiDeviceContactUpdateJob", MultiDeviceContactUpdateJob.KEY); - put("MultiDeviceGroupUpdateJob", MultiDeviceGroupUpdateJob.KEY); - put("MultiDeviceProfileKeyUpdateJob", MultiDeviceProfileKeyUpdateJob.KEY); - put("MultiDeviceReadUpdateJob", MultiDeviceReadUpdateJob.KEY); - put("MultiDeviceVerifiedUpdateJob", MultiDeviceVerifiedUpdateJob.KEY); - put("PushContentReceiveJob", FailingJob.KEY); - put("PushDecryptJob", PushDecryptMessageJob.KEY); - put("PushGroupSendJob", PushGroupSendJob.KEY); - put("PushGroupUpdateJob", PushGroupUpdateJob.KEY); - put("PushMediaSendJob", PushMediaSendJob.KEY); - put("PushNotificationReceiveJob", PushNotificationReceiveJob.KEY); - put("PushTextSendJob", PushTextSendJob.KEY); - put("RefreshAttributesJob", RefreshAttributesJob.KEY); - put("RefreshPreKeysJob", RefreshPreKeysJob.KEY); - put("RefreshUnidentifiedDeliveryAbilityJob", FailingJob.KEY); - put("RequestGroupInfoJob", RequestGroupInfoJob.KEY); - put("RetrieveProfileAvatarJob", RetrieveProfileAvatarJob.KEY); - put("RetrieveProfileJob", RetrieveProfileJob.KEY); - put("RotateCertificateJob", RotateCertificateJob.KEY); - put("RotateProfileKeyJob", RotateProfileKeyJob.KEY); - put("RotateSignedPreKeyJob", RotateSignedPreKeyJob.KEY); - put("SendDeliveryReceiptJob", SendDeliveryReceiptJob.KEY); - put("SendReadReceiptJob", SendReadReceiptJob.KEY); - put("SendViewedReceiptJob", SendViewedReceiptJob.KEY); - put("ServiceOutageDetectionJob", ServiceOutageDetectionJob.KEY); - put("SmsReceiveJob", SmsReceiveJob.KEY); - put("SmsSendJob", SmsSendJob.KEY); - put("SmsSentJob", SmsSentJob.KEY); - put("TrimThreadJob", TrimThreadJob.KEY); - put("TypingSendJob", TypingSendJob.KEY); - put("UpdateApkJob", UpdateApkJob.KEY); - }}; - - public static @Nullable String getFactoryKey(@NonNull String workManagerClass) { - return FACTORY_MAP.get(workManagerClass); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerMigrator.java b/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerMigrator.java deleted file mode 100644 index 8a3ff14cb..000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/jobmanager/workmanager/WorkManagerMigrator.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.thoughtcrime.securesms.jobmanager.workmanager; - -import android.annotation.SuppressLint; -import android.content.Context; - -import androidx.annotation.NonNull; -import androidx.annotation.WorkerThread; - -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.jobmanager.Data; -import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec; -import org.thoughtcrime.securesms.jobmanager.persistence.JobStorage; - -import java.util.List; - -public class WorkManagerMigrator { - - private static final String TAG = Log.tag(WorkManagerMigrator.class); - - @SuppressLint("DefaultLocale") - @WorkerThread - public static synchronized void migrate(@NonNull Context context, - @NonNull JobStorage jobStorage, - @NonNull Data.Serializer dataSerializer) - { - long startTime = System.currentTimeMillis(); - Log.i(TAG, "Beginning WorkManager migration."); - - WorkManagerDatabase database = new WorkManagerDatabase(context); - List fullSpecs = database.getAllJobs(dataSerializer); - - for (FullSpec fullSpec : fullSpecs) { - Log.i(TAG, String.format("Migrating job with key '%s' and %d constraint(s).", fullSpec.getJobSpec().getFactoryKey(), fullSpec.getConstraintSpecs().size())); - } - - jobStorage.insertJobs(fullSpecs); - - context.deleteDatabase(WorkManagerDatabase.DB_NAME); - Log.i(TAG, String.format("WorkManager migration finished. Migrated %d job(s) in %d ms.", fullSpecs.size(), System.currentTimeMillis() - startTime)); - } - - @WorkerThread - public static synchronized boolean needsMigration(@NonNull Context context) { - return context.getDatabasePath(WorkManagerDatabase.DB_NAME).exists(); - } -}