From 8866aa63e3f2dcc5d82b746bbecfcaa3ec2384e3 Mon Sep 17 00:00:00 2001 From: althafvly Date: Mon, 8 Jan 2024 12:30:05 +0530 Subject: [PATCH] Updater: resume update on network failure - Use same connection state monitor --- .../updater/UpdatesCheckReceiver.java | 53 +++++-------------- .../updater/controller/UpdaterController.java | 2 +- .../updater/controller/UpdaterService.java | 52 ++++++++++++++++-- .../updater/misc/ConnectionStateMonitor.kt | 38 ++++++++----- src/org/lineageos/updater/misc/Constants.java | 3 +- 5 files changed, 87 insertions(+), 61 deletions(-) diff --git a/src/org/lineageos/updater/UpdatesCheckReceiver.java b/src/org/lineageos/updater/UpdatesCheckReceiver.java index 8db14e51..8ad0f4de 100644 --- a/src/org/lineageos/updater/UpdatesCheckReceiver.java +++ b/src/org/lineageos/updater/UpdatesCheckReceiver.java @@ -23,9 +23,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; -import android.net.ConnectivityManager; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; import android.os.SystemClock; import android.provider.Settings; import android.util.Log; @@ -36,7 +33,6 @@ import androidx.preference.PreferenceManager; import org.json.JSONException; import org.lineageos.updater.controller.UpdaterService; import org.lineageos.updater.download.DownloadClient; -import org.lineageos.updater.misc.ConnectionStateMonitor; import org.lineageos.updater.misc.Constants; import org.lineageos.updater.misc.JsonValidator; import org.lineageos.updater.misc.Utils; @@ -56,17 +52,12 @@ public class UpdatesCheckReceiver extends BroadcastReceiver { private static final String NEW_UPDATES_NOTIFICATION_CHANNEL = "new_updates_notification_channel"; - private final NetworkRequest networkRequest = new NetworkRequest.Builder() - .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) - .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .build(); - - private ConnectivityManager.NetworkCallback cnState; - private ConnectivityManager connectivityManager; - @Override public void onReceive(final Context context, Intent intent) { + final SharedPreferences preferences = + PreferenceManager.getDefaultSharedPreferences(context); + SharedPreferences.Editor editor = preferences.edit(); + if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { // Check if the current value is empty or null and set anon hash. String eLicenseID = Settings.Secure.getString(context.getContentResolver(), @@ -80,6 +71,10 @@ public class UpdatesCheckReceiver extends BroadcastReceiver { } Utils.cleanupDownloadsDir(context); + + // Reset resume or update check failed on reboot + editor.putBoolean(Constants.AUTO_UPDATE_CHECK_FAILED, false).apply(); + editor.putString(Constants.RESUME_DOWNLOAD_ID, "").apply(); } final File json = Utils.getCachedUpdateList(context); @@ -87,9 +82,6 @@ public class UpdatesCheckReceiver extends BroadcastReceiver { Log.i(TAG, "Removing cached json file due validation failure"); } - final SharedPreferences preferences = - PreferenceManager.getDefaultSharedPreferences(context); - if (!Utils.isUpdateCheckEnabled(context)) { return; } @@ -98,17 +90,15 @@ public class UpdatesCheckReceiver extends BroadcastReceiver { // work like repeating alarms. To check for update at the exact time. updateRepeatingUpdatesCheck(context); - cnState = new ConnectionStateMonitor().getInstance(context); - connectivityManager = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); - if (!Utils.isNetworkAvailable(context)) { if (!UpdaterService.isNetworkCallBackActive()) { - setupNetworkCallback(true); + editor.putBoolean(Constants.AUTO_UPDATE_CHECK_FAILED, true).apply(); + UpdaterService.setupNetworkCallback(true); } return; } else if (UpdaterService.isNetworkCallBackActive()) { - setupNetworkCallback(false); + editor.putBoolean(Constants.AUTO_UPDATE_CHECK_FAILED, false).apply(); + UpdaterService.setupNetworkCallback(false); } final File jsonNew = new File(json.getAbsolutePath() + UUID.randomUUID()); @@ -139,9 +129,7 @@ public class UpdatesCheckReceiver extends BroadcastReceiver { //noinspection ResultOfMethodCallIgnored jsonNew.renameTo(json); long currentMillis = System.currentTimeMillis(); - preferences.edit() - .putLong(Constants.PREF_LAST_UPDATE_CHECK, currentMillis) - .apply(); + editor.putLong(Constants.PREF_LAST_UPDATE_CHECK, currentMillis).apply(); // In case we set a one-shot check because of a previous failure cancelUpdatesCheck(context); } catch (IOException | JSONException e) { @@ -164,21 +152,6 @@ public class UpdatesCheckReceiver extends BroadcastReceiver { } } - public void setupNetworkCallback(boolean shouldEnable) { - if (shouldEnable) { - connectivityManager.registerNetworkCallback(networkRequest, cnState); - } else { - try { - connectivityManager.unregisterNetworkCallback(cnState); - } catch (IllegalArgumentException e) { - Log.e(TAG, "Network callback was not registered"); - } - } - - UpdaterService.setNetworkCallBackActive(shouldEnable); - Log.d(TAG, "Network callback enabled: " + shouldEnable); - } - private static void showNotification(Context context) { NotificationManager notificationManager = context.getSystemService( NotificationManager.class); diff --git a/src/org/lineageos/updater/controller/UpdaterController.java b/src/org/lineageos/updater/controller/UpdaterController.java index 5d7d51a7..307f6ffa 100644 --- a/src/org/lineageos/updater/controller/UpdaterController.java +++ b/src/org/lineageos/updater/controller/UpdaterController.java @@ -66,7 +66,7 @@ public class UpdaterController { private int mActiveDownloads = 0; private final Set mVerifyingUpdates = new HashSet<>(); - protected static synchronized UpdaterController getInstance(Context context) { + public static synchronized UpdaterController getInstance(Context context) { if (sUpdaterController == null) { sUpdaterController = new UpdaterController(context); } diff --git a/src/org/lineageos/updater/controller/UpdaterService.java b/src/org/lineageos/updater/controller/UpdaterService.java index 52dc2cad..d2ac3fdd 100644 --- a/src/org/lineageos/updater/controller/UpdaterService.java +++ b/src/org/lineageos/updater/controller/UpdaterService.java @@ -28,6 +28,9 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; +import android.net.ConnectivityManager; +import android.net.NetworkCapabilities; +import android.net.NetworkRequest; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -42,6 +45,7 @@ import androidx.preference.PreferenceManager; import org.lineageos.updater.R; import org.lineageos.updater.UpdaterReceiver; import org.lineageos.updater.UpdatesActivity; +import org.lineageos.updater.misc.ConnectionStateMonitor; import org.lineageos.updater.misc.Constants; import org.lineageos.updater.misc.StringGenerator; import org.lineageos.updater.misc.Utils; @@ -84,11 +88,21 @@ public class UpdaterService extends Service { private UpdaterController mUpdaterController; + private static final NetworkRequest networkRequest = new NetworkRequest.Builder() + .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) + .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) + .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + .build(); + private static ConnectivityManager.NetworkCallback mConnectionStateMonitor; + private static ConnectivityManager mConnectivityManager; + @Override public void onCreate() { super.onCreate(); mUpdaterController = UpdaterController.getInstance(this); + mConnectionStateMonitor = new ConnectionStateMonitor().getInstance(this); + mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); mNotificationManager = getSystemService(NotificationManager.class); NotificationChannel notificationChannel = new NotificationChannel( @@ -273,6 +287,8 @@ public class UpdaterService extends Service { } private void handleUpdateStatusChange(UpdateInfo update) { + SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences.Editor editor = pref.edit(); switch (update.getStatus()) { case DELETED: { notifySystemUpdaterService(STATUS_WAITING_DOWNLOAD, update); @@ -307,6 +323,10 @@ public class UpdaterService extends Service { mNotificationBuilder.addAction(android.R.drawable.ic_media_pause, getString(R.string.pause_button), getPausePendingIntent(update.getDownloadId())); + if (isNetworkCallBackActive) { + editor.putString(Constants.RESUME_DOWNLOAD_ID, "").apply(); + setupNetworkCallback(false); + } mNotificationBuilder.setTicker(text); mNotificationBuilder.setOngoing(true); mNotificationBuilder.setAutoCancel(false); @@ -326,6 +346,10 @@ public class UpdaterService extends Service { mNotificationBuilder.addAction(android.R.drawable.ic_media_play, getString(R.string.resume_button), getResumePendingIntent(update.getDownloadId())); + if (isNetworkCallBackActive) { + editor.putString(Constants.RESUME_DOWNLOAD_ID, "").apply(); + setupNetworkCallback(false); + } mNotificationBuilder.setTicker(text); mNotificationBuilder.setOngoing(false); mNotificationBuilder.setAutoCancel(false); @@ -351,6 +375,10 @@ public class UpdaterService extends Service { mNotificationBuilder.setOngoing(false); mNotificationBuilder.setAutoCancel(false); mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build()); + if (!Utils.isNetworkAvailable(this)) { + editor.putString(Constants.RESUME_DOWNLOAD_ID, update.getDownloadId()).apply(); + setupNetworkCallback(true); + } tryStopSelf(); break; } @@ -470,7 +498,6 @@ public class UpdaterService extends Service { mNotificationBuilder.setAutoCancel(true); mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build()); - SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); boolean deleteUpdate = pref.getBoolean(Constants.PREF_AUTO_DELETE_UPDATES, true); if (deleteUpdate) { mUpdaterController.deleteUpdate(update.getDownloadId()); @@ -523,10 +550,6 @@ public class UpdaterService extends Service { } } - public static void setNetworkCallBackActive(boolean isActive) { - isNetworkCallBackActive = isActive; - } - public static boolean isNetworkCallBackActive() { return isNetworkCallBackActive; } private void handleDownloadProgressChange(UpdateInfo update) { @@ -569,6 +592,25 @@ public class UpdaterService extends Service { mNotificationBuilder.setContentTitle(buildInfo); } + public static void setupNetworkCallback(boolean shouldEnable) { + if (mConnectivityManager == null || mConnectionStateMonitor == null) { + Log.e(TAG, "Unable to set network callback"); + return; + } + if (shouldEnable) { + mConnectivityManager.registerNetworkCallback(networkRequest, mConnectionStateMonitor); + } else { + try { + mConnectivityManager.unregisterNetworkCallback(mConnectionStateMonitor); + } catch (IllegalArgumentException | NullPointerException e) { + Log.e(TAG, "Network callback was not registered"); + } + } + + isNetworkCallBackActive = shouldEnable; + Log.d(TAG, "Network callback enabled: " + shouldEnable); + } + private PendingIntent getResumePendingIntent(String downloadId) { final Intent intent = new Intent(this, UpdaterService.class); intent.setAction(ACTION_DOWNLOAD_CONTROL); diff --git a/src/org/lineageos/updater/misc/ConnectionStateMonitor.kt b/src/org/lineageos/updater/misc/ConnectionStateMonitor.kt index 583d770c..edb1b518 100644 --- a/src/org/lineageos/updater/misc/ConnectionStateMonitor.kt +++ b/src/org/lineageos/updater/misc/ConnectionStateMonitor.kt @@ -17,12 +17,15 @@ package org.lineageos.updater.misc import android.content.Context import android.content.Intent +import android.content.SharedPreferences import android.net.ConnectivityManager import android.net.Network import android.os.Handler import android.os.Looper import android.util.Log +import androidx.preference.PreferenceManager import org.lineageos.updater.UpdatesCheckReceiver +import org.lineageos.updater.controller.UpdaterController class ConnectionStateMonitor { companion object { @@ -43,31 +46,38 @@ class ConnectionStateMonitor { * - onAvailable: device connected to a network of course * - onLost: when the connection completely lost */ - fun networkCallback(context: Context) = object: ConnectivityManager.NetworkCallback() { + private fun networkCallback(context: Context) = object: ConnectivityManager.NetworkCallback() { private val tag = "ConnectionStateMonitor" - private val delayExecute = 10000L // 10 seconds + private val pref: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + private val updaterController: UpdaterController = UpdaterController.getInstance(context) - private fun startUpdatesCheckReceiver(): Runnable = Runnable { - val broadcastIntent = Intent() - broadcastIntent.setClassName(context, UpdatesCheckReceiver::class.java.name) - context.sendBroadcast(broadcastIntent) - } + private fun checkForUpdatesOrResume() { + val downloadId: String = pref.getString(Constants.RESUME_DOWNLOAD_ID, "")!! + if (downloadId.isNotEmpty()) { + Handler(Looper.getMainLooper()).postDelayed({ + updaterController.resumeDownload( + downloadId + ) + }, 2000L) // 2 seconds + } + if (pref.getBoolean(Constants.AUTO_UPDATE_CHECK_FAILED, false)) { + Handler(Looper.getMainLooper()).postDelayed({ + val broadcastIntent = Intent() + broadcastIntent.setClassName(context, UpdatesCheckReceiver::class.java.name) + context.sendBroadcast(broadcastIntent) + }, 10000L) // 10 seconds + } - private fun checkForUpdates() { - // Delay because some phones takes time go online - Handler(Looper.getMainLooper()).postDelayed( - startUpdatesCheckReceiver(), delayExecute - ) } override fun onAvailable(network: Network) { Log.d(tag, "Network available") - checkForUpdates() + checkForUpdatesOrResume() } override fun onLost(network: Network) { Log.d(tag, "Network not available") - checkForUpdates() + checkForUpdatesOrResume() } } } diff --git a/src/org/lineageos/updater/misc/Constants.java b/src/org/lineageos/updater/misc/Constants.java index 6a0f02c3..a083dce8 100644 --- a/src/org/lineageos/updater/misc/Constants.java +++ b/src/org/lineageos/updater/misc/Constants.java @@ -37,7 +37,6 @@ public final class Constants { public static final String PREF_AB_PERF_MODE = "ab_perf_mode"; public static final String PREF_MOBILE_DATA_WARNING = "pref_mobile_data_warning"; public static final String PREF_NEEDS_REBOOT_ID = "needs_reboot_id"; - public static final String PREF_NETWORK_CALLBACK_ACTIVE = "pref_network_callback_active"; public static final String UNCRYPT_FILE_EXT = ".uncrypt"; @@ -63,4 +62,6 @@ public final class Constants { public static final String UPDATE_RECOVERY_PROPERTY = "persist.vendor.recovery_update"; public static final String HAS_SEEN_INFO_DIALOG = "has_seen_info_dialog"; + public static final String RESUME_DOWNLOAD_ID = "resume_download_id"; + public static final String AUTO_UPDATE_CHECK_FAILED = "auto_update_check_failed"; } -- GitLab