diff --git a/res/values/strings.xml b/res/values/strings.xml index 2239482e8f87f0702a6e5743fdd419e9580bb8a5..0efe456818ddf8b015f665eda8850f7799f1be6b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -40,7 +40,7 @@ Downloading Download paused Download error - Download completed + Update is ready to be installed Starting download Update failed Installation suspended @@ -52,6 +52,7 @@ Pause Resume Suspend + Reboot and install Installing update package Install error @@ -103,6 +104,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 3e5f7c657a53ceaae62918c78b4dad8d7ac67243..e0a7d30b4529e871a9fb95f94eda17cb62ff083e 100644 --- a/src/org/lineageos/updater/UpdatesListAdapter.java +++ b/src/org/lineageos/updater/UpdatesListAdapter.java @@ -17,10 +17,8 @@ package org.lineageos.updater; import android.content.Context; import android.content.Intent; -import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources; -import android.os.BatteryManager; import android.os.Build; import android.os.PowerManager; import android.text.SpannableString; @@ -68,10 +66,6 @@ public class UpdatesListAdapter extends RecyclerView.Adapter mDownloadIds; @@ -245,7 +239,8 @@ public class UpdatesListAdapter extends RecyclerView.Adapter { if (checkbox.isChecked()) { preferences.edit() @@ -372,7 +368,8 @@ public class UpdatesListAdapter extends RecyclerView.Adapter { AlertDialog.Builder freeSpaceDialog = getSpaceDialog( @@ -500,7 +497,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 21da556f75fc9090fb57a82a9ce56225e7f87c9d..632c11b8982779c7066f5ce90e979bc74165e16a 100644 --- a/src/org/lineageos/updater/controller/UpdaterService.java +++ b/src/org/lineageos/updater/controller/UpdaterService.java @@ -27,6 +27,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: { @@ -525,6 +574,14 @@ public class UpdaterService extends Service { PendingIntent.FLAG_UPDATE_CURRENT); } + 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 65369fc6ccacbef3e631eb7b94c40d06a17aa1bc..d795a7c9bf9639e69880dad3647f5cd62ee4b9a3 100644 --- a/src/org/lineageos/updater/misc/Utils.java +++ b/src/org/lineageos/updater/misc/Utils.java @@ -21,12 +21,14 @@ 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; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; +import android.os.BatteryManager; import android.os.Environment; import android.os.StatFs; import android.os.SystemProperties; @@ -63,6 +65,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"; @@ -486,4 +492,19 @@ public class Utils { return AlarmManager.INTERVAL_DAY * 30; } } + + 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; + } }