Detect update failures
This allows to delete the update only if the installation succeeded and to notify the user in case the installation failed. Since we now need the file in case of failure, create a copy for uncrypt even if the user chose to delete installed updates. Change-Id: I80b0f499663bbf50bcbca5f643c01ffdb4cd3957
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
<string name="download_paused_error_notification">Download error</string>
|
||||
<string name="download_completed_notification">Download completed</string>
|
||||
<string name="download_starting_notification">Starting download</string>
|
||||
<string name="update_failed_notification">Update failed</string>
|
||||
|
||||
<string name="new_updates_found_title">New updates</string>
|
||||
|
||||
@@ -139,4 +140,5 @@
|
||||
<string name="export_channel_title">Export completion</string>
|
||||
<string name="new_updates_channel_title">New updates</string>
|
||||
<string name="ongoing_channel_title">Ongoing downloads</string>
|
||||
<string name="update_failed_channel_title">Update failed</string>
|
||||
</resources>
|
||||
|
@@ -15,20 +15,75 @@
|
||||
*/
|
||||
package org.lineageos.updater;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.PowerManager;
|
||||
import android.os.SystemProperties;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
|
||||
import org.lineageos.updater.misc.BuildInfoUtils;
|
||||
import org.lineageos.updater.misc.Constants;
|
||||
import org.lineageos.updater.misc.StringGenerator;
|
||||
|
||||
import java.text.DateFormat;
|
||||
|
||||
public class UpdaterReceiver extends BroadcastReceiver {
|
||||
|
||||
public static final String ACTION_INSTALL_REBOOT =
|
||||
"org.lineageos.updater.action.INSTALL_REBOOT";
|
||||
|
||||
private static final String INSTALL_ERROR_NOTIFICATION_CHANNEL =
|
||||
"install_error_notification_channel";
|
||||
|
||||
private static boolean shouldShowUpdateFailedNotification(Context context) {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
// We can't easily detect failed re-installations
|
||||
if (preferences.getBoolean(Constants.PREF_INSTALL_AGAIN, false) ||
|
||||
preferences.getBoolean(Constants.PREF_INSTALL_NOTIFIED, false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
long buildTimestamp = SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0);
|
||||
long lastBuildTimestamp = preferences.getLong(Constants.PREF_INSTALL_OLD_TIMESTAMP, -1);
|
||||
return buildTimestamp == lastBuildTimestamp;
|
||||
}
|
||||
|
||||
private static void showUpdateFailedNotification(Context context) {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
String buildDate = StringGenerator.getDateLocalizedUTC(context,
|
||||
DateFormat.MEDIUM, preferences.getLong(Constants.PREF_INSTALL_NEW_TIMESTAMP, 0));
|
||||
String buildInfo = context.getString(R.string.list_build_version_date,
|
||||
BuildInfoUtils.getBuildVersion(), buildDate);
|
||||
|
||||
Intent notificationIntent = new Intent(context, UpdatesActivity.class);
|
||||
PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
|
||||
NotificationChannel notificationChannel = new NotificationChannel(
|
||||
INSTALL_ERROR_NOTIFICATION_CHANNEL,
|
||||
context.getString(R.string.update_failed_channel_title),
|
||||
NotificationManager.IMPORTANCE_LOW);
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context,
|
||||
INSTALL_ERROR_NOTIFICATION_CHANNEL)
|
||||
.setContentIntent(intent)
|
||||
.setSmallIcon(R.drawable.ic_system_update)
|
||||
.setContentTitle(context.getString(R.string.update_failed_notification))
|
||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(buildInfo))
|
||||
.setContentText(buildInfo);
|
||||
|
||||
NotificationManager nm = (NotificationManager) context.getSystemService(
|
||||
Context.NOTIFICATION_SERVICE);
|
||||
nm.createNotificationChannel(notificationChannel);
|
||||
nm.notify(0, builder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (ACTION_INSTALL_REBOOT.equals(intent.getAction())) {
|
||||
@@ -37,6 +92,11 @@ public class UpdaterReceiver extends BroadcastReceiver {
|
||||
} else if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
|
||||
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
pref.edit().remove(Constants.PREF_NEEDS_REBOOT).apply();
|
||||
|
||||
if (shouldShowUpdateFailedNotification(context)) {
|
||||
pref.edit().putBoolean(Constants.PREF_INSTALL_NOTIFIED, true).apply();
|
||||
showUpdateFailedNotification(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,9 @@
|
||||
package org.lineageos.updater.controller;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -55,15 +57,20 @@ class UpdateInstaller {
|
||||
|
||||
void install(String downloadId) {
|
||||
UpdateInfo update = mUpdaterController.getUpdate(downloadId);
|
||||
boolean deleteUpdate = PreferenceManager.getDefaultSharedPreferences(mContext)
|
||||
.getBoolean(Constants.PREF_AUTO_DELETE_UPDATES, false);
|
||||
if (deleteUpdate) {
|
||||
// Renaming the file is enough to have it deleted automatically
|
||||
File uncrytpFile = new File(
|
||||
update.getFile().getAbsolutePath() + Constants.UNCRYPT_FILE_EXT);
|
||||
update.getFile().renameTo(uncrytpFile);
|
||||
installPackage(uncrytpFile, downloadId);
|
||||
} else if (Utils.isEncrypted(mContext, update.getFile())) {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(mContext);
|
||||
long buildTimestamp = SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0);
|
||||
long lastBuildTimestamp = preferences.getLong(Constants.PREF_INSTALL_OLD_TIMESTAMP,
|
||||
buildTimestamp);
|
||||
boolean isReinstalling = buildTimestamp == lastBuildTimestamp;
|
||||
preferences.edit()
|
||||
.putLong(Constants.PREF_INSTALL_OLD_TIMESTAMP, buildTimestamp)
|
||||
.putLong(Constants.PREF_INSTALL_NEW_TIMESTAMP, update.getTimestamp())
|
||||
.putString(Constants.PREF_INSTALL_PACKAGE_PATH, update.getFile().getAbsolutePath())
|
||||
.putBoolean(Constants.PREF_INSTALL_AGAIN, isReinstalling)
|
||||
.putBoolean(Constants.PREF_INSTALL_NOTIFIED, false)
|
||||
.apply();
|
||||
|
||||
if (Utils.isEncrypted(mContext, update.getFile())) {
|
||||
// uncrypt rewrites the file so that it can be read without mounting
|
||||
// the filesystem, so create a copy of it.
|
||||
prepareForUncryptAndInstall(update);
|
||||
|
@@ -39,4 +39,9 @@ public final class Constants {
|
||||
public static final String PROP_RELEASE_TYPE = "ro.lineage.releasetype";
|
||||
public static final String PROP_UPDATER_URI = "lineage.updater.uri";
|
||||
|
||||
public static final String PREF_INSTALL_OLD_TIMESTAMP = "install_old_timestamp";
|
||||
public static final String PREF_INSTALL_NEW_TIMESTAMP = "install_new_timestamp";
|
||||
public static final String PREF_INSTALL_PACKAGE_PATH = "install_package_path";
|
||||
public static final String PREF_INSTALL_AGAIN = "install_again";
|
||||
public static final String PREF_INSTALL_NOTIFIED = "install_notified";
|
||||
}
|
||||
|
@@ -264,11 +264,26 @@ public class Utils {
|
||||
*/
|
||||
public static void cleanupDownloadsDir(Context context) {
|
||||
File downloadPath = getDownloadPath(context);
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
removeUncryptFiles(downloadPath);
|
||||
|
||||
long buildTimestamp = SystemProperties.getLong(Constants.PROP_BUILD_DATE, 0);
|
||||
long prevTimestamp = preferences.getLong(Constants.PREF_INSTALL_OLD_TIMESTAMP, 0);
|
||||
String lastUpdatePath = preferences.getString(Constants.PREF_INSTALL_PACKAGE_PATH, null);
|
||||
boolean reinstalling = preferences.getBoolean(Constants.PREF_INSTALL_AGAIN, false);
|
||||
boolean deleteUpdates = preferences.getBoolean(Constants.PREF_AUTO_DELETE_UPDATES, false);
|
||||
if ((buildTimestamp != prevTimestamp || reinstalling) && deleteUpdates &&
|
||||
lastUpdatePath != null) {
|
||||
File lastUpdate = new File(lastUpdatePath);
|
||||
if (lastUpdate.exists()) {
|
||||
lastUpdate.delete();
|
||||
// Remove the pref not to delete the file if re-downloaded
|
||||
preferences.edit().remove(Constants.PREF_INSTALL_PACKAGE_PATH).apply();
|
||||
}
|
||||
}
|
||||
|
||||
final String DOWNLOADS_CLEANUP_DONE = "cleanup_done";
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
if (preferences.getBoolean(DOWNLOADS_CLEANUP_DONE, false)) {
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user