diff --git a/res/values/strings.xml b/res/values/strings.xml index fc92d52486081e9a374573e6a0b22fa67257137b..d6b241cc293dec3b79004ce15e0b994982c68699 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -41,7 +41,7 @@ Downloading Download paused Download error - Download completed + Update is ready to be installed Starting download Update failed Installation suspended @@ -53,6 +53,7 @@ Pause Resume Suspend + Reboot and install Installing update package Install error @@ -108,6 +109,7 @@ You are running the latest /e/OS version. To manually check for updates, use the Refresh button. Download + Apply update Pause Resume Install diff --git a/src/org/lineageos/updater/UpdatesListAdapter.java b/src/org/lineageos/updater/UpdatesListAdapter.java index 7ee4b3dc2d2f6ec808afdbfdfedd1d969e230827..ab025ffbd4a25786ee25e89ebc7c072d52d51014 100644 --- a/src/org/lineageos/updater/UpdatesListAdapter.java +++ b/src/org/lineageos/updater/UpdatesListAdapter.java @@ -18,11 +18,9 @@ package org.lineageos.updater; import android.app.Activity; import android.content.Intent; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources; import android.net.Uri; -import android.os.BatteryManager; import android.os.Build; import android.os.PowerManager; import android.text.SpannableString; @@ -74,10 +72,6 @@ public class UpdatesListAdapter extends RecyclerView.Adapter mDownloadIds; @@ -256,7 +250,8 @@ public class UpdatesListAdapter extends RecyclerView.Adapter { if (checkbox.isChecked()) { preferences.edit() @@ -383,7 +379,8 @@ public class UpdatesListAdapter extends RecyclerView.Adapter { AlertDialog.Builder freeSpaceDialog = getSpaceDialog( @@ -507,7 +504,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter= required; - } } diff --git a/src/org/lineageos/updater/controller/UpdaterService.java b/src/org/lineageos/updater/controller/UpdaterService.java index f5ee697b846b689807c18b7443e5a26f606f3da6..ba4baafdadd0529fdf43635fd657d9ecc9f182a1 100644 --- a/src/org/lineageos/updater/controller/UpdaterService.java +++ b/src/org/lineageos/updater/controller/UpdaterService.java @@ -28,6 +28,7 @@ import android.content.SharedPreferences; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; +import android.service.notification.StatusBarNotification; import android.text.format.Formatter; import android.util.Log; @@ -245,12 +246,27 @@ public class UpdaterService extends Service { private void tryStopSelf() { if (!mHasClients && !mUpdaterController.hasActiveDownloads() && - !mUpdaterController.isInstallingUpdate()) { + !mUpdaterController.isInstallingUpdate() && !areNotificationsActive()) { Log.d(TAG, "Service no longer needed, stopping"); stopSelf(); } } + private boolean areNotificationsActive() { + NotificationManager notificationManager = + (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + StatusBarNotification[] notifications = notificationManager.getActiveNotifications(); + if (notifications != null && notifications.length > 0) { + for (StatusBarNotification notification : notifications) { + if (notification.getId() == NOTIFICATION_ID && + notification.getPackageName().equals(getPackageName())) { + return true; + } + } + } + return false; + } + private void handleUpdateStatusChange(UpdateInfo update) { switch (update.getStatus()) { case DELETED: { @@ -346,12 +362,45 @@ public class UpdaterService extends Service { mNotificationBuilder.setSmallIcon(R.drawable.ic_system_update); mNotificationBuilder.setProgress(0, 0, false); String text = getString(R.string.download_completed_notification); + boolean hasRequiredSpace = Utils.availableFreeSpace() > (update.getFileSize() * 2); + + if (!Utils.canInstall(update) || !Utils.isBatteryLevelOk(this) + || !hasRequiredSpace) { + /* Show notification if any of the below condition didn't met. */ + text = getString(R.string.blocked_update_dialog_title) + ". "; + if (!Utils.isBatteryLevelOk(this)) { + text = text + getString(R.string.dialog_battery_low_title); + } else if (!hasRequiredSpace) { + text = text + getString(R.string.dialog_free_space_low_title); + } else if (!Utils.canInstall(update)) { + text = text + getString(R.string.verification_failed_notification); + } + } else if (!Utils.isABDevice()) { + /* Add action to reboot and install for Non-A/B devices. */ + mNotificationBuilder.mActions.clear(); + mNotificationBuilder.addAction(R.drawable.ic_system_update, + getString(R.string.reboot_install), + getInstallationPendingIntent(update.getDownloadId())); + } + mNotificationBuilder.setContentText(text); mNotificationBuilder.setTicker(text); mNotificationBuilder.setOngoing(false); mNotificationBuilder.setAutoCancel(true); mNotificationManager.notify(NOTIFICATION_ID, mNotificationBuilder.build()); - tryStopSelf(); + + /* Make sure these conditions are met before auto install + - Can install package (Is a newer build or downgrade allowed) + - Battery level (Above 30% if discharging or 20% if charging) + - Free space to install (Double the size of the ota zip) + */ + if (Utils.isABDevice() && Utils.canInstall(update) + && Utils.isBatteryLevelOk(this) && hasRequiredSpace) { + Utils.triggerUpdate(this, update.getDownloadId()); + } else { + tryStopSelf(); + } + break; } case VERIFICATION_FAILED: { @@ -528,6 +577,14 @@ public class UpdaterService extends Service { PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } + private PendingIntent getInstallationPendingIntent(String downloadId) { + final Intent intent = new Intent(this, UpdaterService.class); + intent.setAction(ACTION_INSTALL_UPDATE); + intent.putExtra(UpdaterService.EXTRA_DOWNLOAD_ID, downloadId); + return PendingIntent.getService(this, 0, intent, + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); + } + private PendingIntent getResumeInstallationPendingIntent() { final Intent intent = new Intent(this, UpdaterService.class); intent.setAction(ACTION_INSTALL_RESUME); diff --git a/src/org/lineageos/updater/misc/Utils.java b/src/org/lineageos/updater/misc/Utils.java index 497b635fa0584a9e1b06e82a28548a79d45c0097..4e7b20f209fd84ac9b9bbe83c38070c0ffe4b366 100644 --- a/src/org/lineageos/updater/misc/Utils.java +++ b/src/org/lineageos/updater/misc/Utils.java @@ -22,6 +22,7 @@ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.database.Cursor; @@ -29,6 +30,7 @@ import android.net.ConnectivityManager; import android.net.Network; import android.net.NetworkCapabilities; import android.net.Uri; +import android.os.BatteryManager; import android.os.Build; import android.os.Environment; import android.os.StatFs; @@ -66,6 +68,10 @@ import java.util.zip.ZipFile; public class Utils { + private static final int BATTERY_PLUGGED_ANY = BatteryManager.BATTERY_PLUGGED_AC + | BatteryManager.BATTERY_PLUGGED_USB + | BatteryManager.BATTERY_PLUGGED_WIRELESS; + private static final String TAG = "Utils"; private static final String CONTENT_URI_PATH = "content://custom.setting.Provider.OTA_SERVER/cte"; @@ -507,4 +513,19 @@ public class Utils { public static boolean isRecoveryUpdateExecPresent() { return new File(Constants.UPDATE_RECOVERY_EXEC).exists(); } + + public static boolean isBatteryLevelOk(Context context) { + Intent intent = context.registerReceiver(null, + new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); + if (!intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false)) { + return true; + } + int percent = Math.round(100.f * intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100) / + intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)); + int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0); + int required = (plugged & BATTERY_PLUGGED_ANY) != 0 ? + context.getResources().getInteger(R.integer.battery_ok_percentage_charging) : + context.getResources().getInteger(R.integer.battery_ok_percentage_discharging); + return percent >= required; + } }