diff --git a/app/src/main/java/org/lineageos/updater/UpdatesCheckReceiver.java b/app/src/main/java/org/lineageos/updater/UpdatesCheckReceiver.java index 8db14e51c523fde9ad7d2f977b487f8f9ee8219a..8ad0f4de669f8e5d4618494bae21bf7445fb002d 100644 --- a/app/src/main/java/org/lineageos/updater/UpdatesCheckReceiver.java +++ b/app/src/main/java/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/app/src/main/java/org/lineageos/updater/controller/UpdaterService.java b/app/src/main/java/org/lineageos/updater/controller/UpdaterService.java index 6b69d282a065e6763cf5efa5b38f505d70c23356..8d26b35cfaefa6acef15889a189820ffaf3fffe8 100644 --- a/app/src/main/java/org/lineageos/updater/controller/UpdaterService.java +++ b/app/src/main/java/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; @@ -49,7 +53,6 @@ import org.lineageos.updater.model.Update; import org.lineageos.updater.model.UpdateInfo; import org.lineageos.updater.model.UpdateStatus; -import java.io.File; import java.io.IOException; import java.text.DateFormat; import java.text.NumberFormat; @@ -86,11 +89,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( @@ -277,6 +290,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); @@ -311,6 +326,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); @@ -330,6 +349,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); @@ -355,6 +378,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; } @@ -474,7 +501,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); boolean isLocal = Update.LOCAL_ID.equals(update.getDownloadId()); if (deleteUpdate || isLocal) { @@ -528,10 +554,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) { @@ -574,6 +596,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/app/src/main/java/org/lineageos/updater/misc/ConnectionStateMonitor.kt b/app/src/main/java/org/lineageos/updater/misc/ConnectionStateMonitor.kt index 583d770c55e1f6bb018f99165ad961c5215261be..edb1b51835791a21231055187856c8fe3693b8b9 100644 --- a/app/src/main/java/org/lineageos/updater/misc/ConnectionStateMonitor.kt +++ b/app/src/main/java/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/app/src/main/java/org/lineageos/updater/misc/Constants.java b/app/src/main/java/org/lineageos/updater/misc/Constants.java index e37725827b138682d90142dfbd1d757955a2462a..520b274dd513dcaa7a025235e5be59da4700d5a7 100644 --- a/app/src/main/java/org/lineageos/updater/misc/Constants.java +++ b/app/src/main/java/org/lineageos/updater/misc/Constants.java @@ -64,4 +64,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"; }