Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71a759a1 authored by Mohammed Althaf T's avatar Mohammed Althaf T 😊
Browse files

Updater: resume update on network failure

- Use same connection state monitor
parent 9c336445
Loading
Loading
Loading
Loading
+13 −40
Original line number Diff line number Diff line
@@ -24,9 +24,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;
@@ -37,7 +34,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;
@@ -57,17 +53,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(),
@@ -81,6 +72,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);
@@ -88,9 +83,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;
        }
@@ -100,17 +92,15 @@ public class UpdatesCheckReceiver extends BroadcastReceiver {
            scheduleRepeatingUpdatesCheck(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());
@@ -141,9 +131,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) {
@@ -166,21 +154,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);
+1 −1
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ public class UpdaterController {
    private int mActiveDownloads = 0;
    private final Set<String> mVerifyingUpdates = new HashSet<>();

    protected static synchronized UpdaterController getInstance(Context context) {
    public static synchronized UpdaterController getInstance(Context context) {
        if (sUpdaterController == null) {
            sUpdaterController = new UpdaterController(context);
        }
+47 −5
Original line number Diff line number Diff line
@@ -25,6 +25,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;
@@ -39,6 +42,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;
@@ -81,11 +85,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(
@@ -270,6 +284,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: {
                stopForeground(STOP_FOREGROUND_DETACH);
@@ -301,6 +317,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);
@@ -319,6 +339,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);
@@ -343,6 +367,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;
            }
@@ -457,7 +485,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());
@@ -507,10 +534,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) {
@@ -553,6 +576,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);
+24 −14
Original line number Diff line number Diff line
@@ -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 {
        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()
        }
    }
}
+2 −1
Original line number Diff line number Diff line
@@ -35,7 +35,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";

@@ -61,4 +60,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";
}