diff --git a/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java b/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java deleted file mode 100644 index 6c288f465..000000000 --- a/src/org/thoughtcrime/securesms/jobs/UpdateApkJob.java +++ /dev/null @@ -1,254 +0,0 @@ -package org.thoughtcrime.securesms.jobs; - - -import android.app.DownloadManager; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import android.support.annotation.Nullable; -import android.util.Log; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import org.thoughtcrime.securesms.BuildConfig; -import org.thoughtcrime.securesms.jobmanager.JobParameters; -import org.thoughtcrime.securesms.jobmanager.requirements.NetworkRequirement; -import org.thoughtcrime.securesms.service.UpdateApkReadyListener; -import org.thoughtcrime.securesms.util.FileUtils; -import org.thoughtcrime.securesms.util.Hex; -import org.thoughtcrime.securesms.util.JsonUtils; -import org.thoughtcrime.securesms.util.Prefs; - -import java.io.FileInputStream; -import java.io.IOException; -import java.security.MessageDigest; -import java.util.concurrent.TimeUnit; - -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; - -public class UpdateApkJob extends ContextJob { - - private static final String TAG = UpdateApkJob.class.getSimpleName(); - - public UpdateApkJob(Context context) { - super(context, JobParameters.newBuilder() - .withGroupId(UpdateApkJob.class.getSimpleName()) - .withRequirement(new NetworkRequirement(context)) - .withWakeLock(true, 30, TimeUnit.SECONDS) - .withRetryCount(2) - .create()); - } - - @Override - public void onAdded() {} - - @Override - public void onRun() throws IOException, PackageManager.NameNotFoundException { - if (!BuildConfig.PLAY_STORE_DISABLED) return; - - Log.w(TAG, "Checking for APK update..."); - - OkHttpClient client = new OkHttpClient(); - Request request = new Request.Builder().url(String.format("%s/latest.json", BuildConfig.NOPLAY_UPDATE_URL)).build(); - - Response response = client.newCall(request).execute(); - - if (!response.isSuccessful()) { - throw new IOException("Bad response: " + response.message()); - } - - UpdateDescriptor updateDescriptor = JsonUtils.fromJson(response.body().string(), UpdateDescriptor.class); - byte[] digest = Hex.fromStringCondensed(updateDescriptor.getDigest()); - - Log.w(TAG, "Got descriptor: " + updateDescriptor); - - if (updateDescriptor.getVersionCode() > getVersionCode()) { - DownloadStatus downloadStatus = getDownloadStatus(updateDescriptor.getUrl(), digest); - - Log.w(TAG, "Download status: " + downloadStatus.getStatus()); - - if (downloadStatus.getStatus() == DownloadStatus.Status.COMPLETE) { - Log.w(TAG, "Download status complete, notifying..."); - handleDownloadNotify(downloadStatus.getDownloadId()); - } else if (downloadStatus.getStatus() == DownloadStatus.Status.MISSING) { - Log.w(TAG, "Download status missing, starting download..."); - handleDownloadStart(updateDescriptor.getUrl(), updateDescriptor.getVersionName(), digest); - } - } - } - - @Override - public boolean onShouldRetry(Exception e) { - return e instanceof IOException; - } - - @Override - public void onCanceled() { - Log.w(TAG, "Update check failed"); - } - - private int getVersionCode() throws PackageManager.NameNotFoundException { - PackageManager packageManager = context.getPackageManager(); - PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0); - - return packageInfo.versionCode; - } - - private DownloadStatus getDownloadStatus(String uri, byte[] theirDigest) { - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - DownloadManager.Query query = new DownloadManager.Query(); - - query.setFilterByStatus(DownloadManager.STATUS_PAUSED | DownloadManager.STATUS_PENDING | DownloadManager.STATUS_RUNNING | DownloadManager.STATUS_SUCCESSFUL); - - long pendingDownloadId = Prefs.getUpdateApkDownloadId(context); - byte[] pendingDigest = getPendingDigest(context); - Cursor cursor = downloadManager.query(query); - - try { - DownloadStatus status = new DownloadStatus(DownloadStatus.Status.MISSING, -1); - - while (cursor != null && cursor.moveToNext()) { - int jobStatus = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS)); - String jobRemoteUri = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_URI)); - long downloadId = cursor.getLong(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID)); - byte[] digest = getDigestForDownloadId(downloadId); - - if (jobRemoteUri != null && jobRemoteUri.equals(uri) && downloadId == pendingDownloadId) { - - if (jobStatus == DownloadManager.STATUS_SUCCESSFUL && - digest != null && pendingDigest != null && - MessageDigest.isEqual(pendingDigest, theirDigest) && - MessageDigest.isEqual(digest, theirDigest)) - { - return new DownloadStatus(DownloadStatus.Status.COMPLETE, downloadId); - } else if (jobStatus != DownloadManager.STATUS_SUCCESSFUL) { - status = new DownloadStatus(DownloadStatus.Status.PENDING, downloadId); - } - } - } - - return status; - } finally { - if (cursor != null) cursor.close(); - } - } - - private void handleDownloadStart(String uri, String versionName, byte[] digest) { - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(uri)); - - downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI); - downloadRequest.setTitle("Downloading Signal update"); - downloadRequest.setDescription("Downloading Signal " + versionName); - downloadRequest.setVisibleInDownloadsUi(false); - downloadRequest.setDestinationInExternalFilesDir(context, null, "signal-update.apk"); - - if (Build.VERSION.SDK_INT >= 11) { - downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); - } - - long downloadId = downloadManager.enqueue(downloadRequest); - Prefs.setUpdateApkDownloadId(context, downloadId); - Prefs.setUpdateApkDigest(context, Hex.toStringCondensed(digest)); - } - - private void handleDownloadNotify(long downloadId) { - Intent intent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE); - intent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, downloadId); - - new UpdateApkReadyListener().onReceive(context, intent); - } - - private @Nullable byte[] getDigestForDownloadId(long downloadId) { - try { - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - FileInputStream fin = new FileInputStream(downloadManager.openDownloadedFile(downloadId).getFileDescriptor()); - byte[] digest = FileUtils.getFileDigest(fin); - - fin.close(); - - return digest; - } catch (IOException e) { - Log.w(TAG, e); - return null; - } - } - - private @Nullable byte[] getPendingDigest(Context context) { - try { - String encodedDigest = Prefs.getUpdateApkDigest(context); - - if (encodedDigest == null) return null; - - return Hex.fromStringCondensed(encodedDigest); - } catch (IOException e) { - Log.w(TAG, e); - return null; - } - } - - private static class UpdateDescriptor { - @JsonProperty - private int versionCode; - - @JsonProperty - private String versionName; - - @JsonProperty - private String url; - - @JsonProperty - private String sha256sum; - - - public int getVersionCode() { - return versionCode; - } - - public String getVersionName() { - return versionName; - } - - public String getUrl() { - return url; - } - - public String toString() { - return "[" + versionCode + ", " + versionName + ", " + url + "]"; - } - - public String getDigest() { - return sha256sum; - } - } - - private static class DownloadStatus { - enum Status { - PENDING, - COMPLETE, - MISSING - } - - private final Status status; - private final long downloadId; - - DownloadStatus(Status status, long downloadId) { - this.status = status; - this.downloadId = downloadId; - } - - public Status getStatus() { - return status; - } - - public long getDownloadId() { - return downloadId; - } - } -} diff --git a/src/org/thoughtcrime/securesms/service/UpdateApkReadyListener.java b/src/org/thoughtcrime/securesms/service/UpdateApkReadyListener.java deleted file mode 100644 index 2b3881a21..000000000 --- a/src/org/thoughtcrime/securesms/service/UpdateApkReadyListener.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.thoughtcrime.securesms.service; - - -import android.app.DownloadManager; -import android.app.Notification; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.database.Cursor; -import android.net.Uri; -import android.support.annotation.Nullable; -import android.support.v4.app.NotificationCompat; -import android.util.Log; - -import org.thoughtcrime.securesms.R; -import org.thoughtcrime.securesms.util.FileProviderUtil; -import org.thoughtcrime.securesms.util.FileUtils; -import org.thoughtcrime.securesms.util.Hex; -import org.thoughtcrime.securesms.util.ServiceUtil; -import org.thoughtcrime.securesms.util.Prefs; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.MessageDigest; - -public class UpdateApkReadyListener extends BroadcastReceiver { - - private static final String TAG = UpdateApkReadyListener.class.getSimpleName(); - - @Override - public void onReceive(Context context, Intent intent) { - Log.w(TAG, "onReceive()"); - - if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) { - long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -2); - - if (downloadId == Prefs.getUpdateApkDownloadId(context)) { - Uri uri = getLocalUriForDownloadId(context, downloadId); - String encodedDigest = Prefs.getUpdateApkDigest(context); - - if (uri == null) { - Log.w(TAG, "Downloaded local URI is null?"); - return; - } - - if (isMatchingDigest(context, downloadId, encodedDigest)) { - displayInstallNotification(context, uri); - } else { - Log.w(TAG, "Downloaded APK doesn't match digest..."); - } - } - } - } - - private void displayInstallNotification(Context context, Uri uri) { - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.setDataAndType(uri, "application/vnd.android.package-archive"); - - PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); - - Notification notification = new NotificationCompat.Builder(context) - .setOngoing(true) - .setContentTitle(context.getString(R.string.UpdateApkReadyListener_Signal_update)) - .setContentText(context.getString(R.string.UpdateApkReadyListener_a_new_version_of_signal_is_available_tap_to_update)) - .setSmallIcon(R.drawable.icon_notification) - .setColor(context.getResources().getColor(R.color.textsecure_primary)) - .setPriority(NotificationCompat.PRIORITY_HIGH) - .setCategory(NotificationCompat.CATEGORY_REMINDER) - .setContentIntent(pendingIntent) - .build(); - - ServiceUtil.getNotificationManager(context).notify(666, notification); - } - - private @Nullable Uri getLocalUriForDownloadId(Context context, long downloadId) { - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - DownloadManager.Query query = new DownloadManager.Query(); - query.setFilterById(downloadId); - - Cursor cursor = downloadManager.query(query); - - try { - if (cursor != null && cursor.moveToFirst()) { - String localUri = cursor.getString(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI)); - - if (localUri != null) { - File localFile = new File(Uri.parse(localUri).getPath()); - return FileProviderUtil.getUriFor(context, localFile); - } - } - } finally { - if (cursor != null) cursor.close(); - } - - return null; - } - - private boolean isMatchingDigest(Context context, long downloadId, String theirEncodedDigest) { - try { - if (theirEncodedDigest == null) return false; - - byte[] theirDigest = Hex.fromStringCondensed(theirEncodedDigest); - DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); - FileInputStream fin = new FileInputStream(downloadManager.openDownloadedFile(downloadId).getFileDescriptor()); - byte[] ourDigest = FileUtils.getFileDigest(fin); - - fin.close(); - - return MessageDigest.isEqual(ourDigest, theirDigest); - } catch (IOException e) { - Log.w(TAG, e); - return false; - } - } -} diff --git a/src/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java b/src/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java deleted file mode 100644 index 2fbb9f317..000000000 --- a/src/org/thoughtcrime/securesms/service/UpdateApkRefreshListener.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.thoughtcrime.securesms.service; - - -import android.content.Context; -import android.content.Intent; -import android.util.Log; - -import org.thoughtcrime.securesms.ApplicationContext; -import org.thoughtcrime.securesms.BuildConfig; -import org.thoughtcrime.securesms.jobs.UpdateApkJob; -import org.thoughtcrime.securesms.util.Prefs; - -import java.util.concurrent.TimeUnit; - -public class UpdateApkRefreshListener extends PersistentAlarmManagerListener { - - private static final String TAG = UpdateApkRefreshListener.class.getSimpleName(); - - private static final long INTERVAL = TimeUnit.HOURS.toMillis(6); - - @Override - protected long getNextScheduledExecutionTime(Context context) { - return Prefs.getUpdateApkRefreshTime(context); - } - - @Override - protected long onAlarm(Context context, long scheduledTime) { - Log.w(TAG, "onAlarm..."); - - if (scheduledTime != 0 && BuildConfig.PLAY_STORE_DISABLED) { - Log.w(TAG, "Queueing APK update job..."); - ApplicationContext.getInstance(context) - .getJobManager() - .add(new UpdateApkJob(context)); - } - - long newTime = System.currentTimeMillis() + INTERVAL; - Prefs.setUpdateApkRefreshTime(context, newTime); - - return newTime; - } - - public static void schedule(Context context) { - new UpdateApkRefreshListener().onReceive(context, new Intent()); - } - -} diff --git a/src/org/thoughtcrime/securesms/util/Prefs.java b/src/org/thoughtcrime/securesms/util/Prefs.java index 9db926cfe..eccc516e1 100644 --- a/src/org/thoughtcrime/securesms/util/Prefs.java +++ b/src/org/thoughtcrime/securesms/util/Prefs.java @@ -48,9 +48,6 @@ public class Prefs { private static final String ENTER_SENDS_PREF = "pref_enter_sends"; private static final String LOCAL_NUMBER_PREF = "pref_local_number"; private static final String PROMPTED_OPTIMIZE_DOZE_PREF = "pref_prompted_optimize_doze"; - private static final String UPDATE_APK_REFRESH_TIME_PREF = "pref_update_apk_refresh_time"; - private static final String UPDATE_APK_DOWNLOAD_ID = "pref_update_apk_download_id"; - private static final String UPDATE_APK_DIGEST = "pref_update_apk_digest"; private static final String IN_THREAD_NOTIFICATION_PREF = "pref_key_inthread_notifications"; public static final String MESSAGE_BODY_TEXT_SIZE_PREF = "pref_message_body_text_size"; @@ -60,7 +57,6 @@ public class Prefs { public static final String SYSTEM_EMOJI_PREF = "pref_system_emoji"; public static final String DIRECT_CAPTURE_CAMERA_ID = "pref_direct_capture_camera_id"; - private static final String PROFILE_KEY_PREF = "pref_profile_key"; private static final String PROFILE_NAME_PREF = "pref_profile_name"; private static final String PROFILE_AVATAR_ID_PREF = "pref_profile_avatar_id"; public static final String INCOGNITO_KEYBORAD_PREF = "pref_incognito_keyboard"; @@ -176,30 +172,6 @@ public class Prefs { return getBooleanPreference(context, IN_THREAD_NOTIFICATION_PREF, true); } - public static long getUpdateApkRefreshTime(Context context) { - return getLongPreference(context, UPDATE_APK_REFRESH_TIME_PREF, 0L); - } - - public static void setUpdateApkRefreshTime(Context context, long value) { - setLongPreference(context, UPDATE_APK_REFRESH_TIME_PREF, value); - } - - public static void setUpdateApkDownloadId(Context context, long value) { - setLongPreference(context, UPDATE_APK_DOWNLOAD_ID, value); - } - - public static long getUpdateApkDownloadId(Context context) { - return getLongPreference(context, UPDATE_APK_DOWNLOAD_ID, -1); - } - - public static void setUpdateApkDigest(Context context, String value) { - setStringPreference(context, UPDATE_APK_DIGEST, value); - } - - public static String getUpdateApkDigest(Context context) { - return getStringPreference(context, UPDATE_APK_DIGEST, null); - } - public static String getLocalNumber(Context context) { return getStringPreference(context, LOCAL_NUMBER_PREF, null); }