Allow service restarts while installing AB updates
The update engine service is independent and once started doesn't need our service to install updates. Therefore we can't assume that our service will stay up as long as the installation is being performed. If the service gets terminated while an update is being installed, we simply lose our connection to the update engine service and stop receiving notifications, the installation itself won't stop. Keep track of ongoing installations using a shared preference and use a sticky service when installing updates. The service will try to re-connect to the update engine service and determine if the installation is still ongoing. Change-Id: Id2fc11cab51610d04bf41a0927824bb8c0c94d71
This commit is contained in:
@@ -41,15 +41,26 @@ class ABUpdateInstaller {
|
||||
|
||||
private static final String TAG = "ABUpdateInstaller";
|
||||
|
||||
private static String sDownloadId;
|
||||
private static final String PREF_INSTALLING_AB_ID = "installing_ab_id";
|
||||
|
||||
private final UpdaterController mUpdaterController;
|
||||
private final String mDownloadId;
|
||||
private final Context mContext;
|
||||
private String mDownloadId;
|
||||
private boolean mReconnecting;
|
||||
|
||||
private UpdateEngine mUpdateEngine;
|
||||
|
||||
private final UpdateEngineCallback mUpdateEngineCallback = new UpdateEngineCallback() {
|
||||
|
||||
@Override
|
||||
public void onStatusUpdate(int status, float percent) {
|
||||
Update update = mUpdaterController.getActualUpdate(mDownloadId);
|
||||
if (update == null) {
|
||||
// We read the id from a preference, the update could no longer exist
|
||||
installationDone();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case UpdateEngine.UpdateStatusConstants.DOWNLOADING:
|
||||
case UpdateEngine.UpdateStatusConstants.FINALIZING: {
|
||||
@@ -60,8 +71,7 @@ class ABUpdateInstaller {
|
||||
break;
|
||||
|
||||
case UpdateEngine.UpdateStatusConstants.REPORTING_ERROR_EVENT: {
|
||||
sDownloadId = null;
|
||||
Update update = mUpdaterController.getActualUpdate(mDownloadId);
|
||||
installationDone();
|
||||
update.setInstallProgress(0);
|
||||
update.setStatus(UpdateStatus.INSTALLATION_FAILED);
|
||||
mUpdaterController.notifyUpdateChange(mDownloadId);
|
||||
@@ -69,8 +79,7 @@ class ABUpdateInstaller {
|
||||
break;
|
||||
|
||||
case UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT: {
|
||||
sDownloadId = null;
|
||||
Update update = mUpdaterController.getActualUpdate(mDownloadId);
|
||||
installationDone();
|
||||
update.setInstallProgress(0);
|
||||
update.setStatus(UpdateStatus.INSTALLED);
|
||||
mUpdaterController.notifyUpdateChange(mDownloadId);
|
||||
@@ -83,6 +92,16 @@ class ABUpdateInstaller {
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case UpdateEngine.UpdateStatusConstants.IDLE: {
|
||||
if (mReconnecting) {
|
||||
// The service was restarted because we thought we were installing an
|
||||
// update, but we aren't, so clear everything.
|
||||
installationDone();
|
||||
mReconnecting = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,35 +110,29 @@ class ABUpdateInstaller {
|
||||
}
|
||||
};
|
||||
|
||||
static synchronized boolean start(Context context, UpdaterController updaterController,
|
||||
String downloadId) {
|
||||
if (sDownloadId != null) {
|
||||
return false;
|
||||
}
|
||||
ABUpdateInstaller installer = new ABUpdateInstaller(context, updaterController, downloadId);
|
||||
if (installer.startUpdate()) {
|
||||
sDownloadId = downloadId;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
static synchronized boolean isInstallingUpdate(Context context) {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getString(ABUpdateInstaller.PREF_INSTALLING_AB_ID, null) != null;
|
||||
}
|
||||
|
||||
static synchronized boolean isInstallingUpdate() {
|
||||
return sDownloadId != null;
|
||||
static synchronized boolean isInstallingUpdate(Context context, String downloadId) {
|
||||
return downloadId.equals(PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getString(ABUpdateInstaller.PREF_INSTALLING_AB_ID, null));
|
||||
}
|
||||
|
||||
static synchronized boolean isInstallingUpdate(String downloadId) {
|
||||
return sDownloadId != null && sDownloadId.equals(downloadId);
|
||||
}
|
||||
|
||||
private ABUpdateInstaller(Context context, UpdaterController updaterController,
|
||||
String downloadId) {
|
||||
ABUpdateInstaller(Context context, UpdaterController updaterController) {
|
||||
mUpdaterController = updaterController;
|
||||
mDownloadId = downloadId;
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
private boolean startUpdate() {
|
||||
public boolean install(String downloadId) {
|
||||
if (isInstallingUpdate(mContext)) {
|
||||
Log.e(TAG, "Already installing an update");
|
||||
return false;
|
||||
}
|
||||
|
||||
mDownloadId = downloadId;
|
||||
|
||||
File file = mUpdaterController.getActualUpdate(mDownloadId).getFile();
|
||||
if (!file.exists()) {
|
||||
Log.e(TAG, "The given update doesn't exist");
|
||||
@@ -154,11 +167,42 @@ class ABUpdateInstaller {
|
||||
return false;
|
||||
}
|
||||
|
||||
UpdateEngine updateEngine = new UpdateEngine();
|
||||
updateEngine.bind(mUpdateEngineCallback);
|
||||
mUpdateEngine = new UpdateEngine();
|
||||
if (!mUpdateEngine.bind(mUpdateEngineCallback)) {
|
||||
Log.e(TAG, "Could not bind");
|
||||
return false;
|
||||
}
|
||||
String zipFileUri = "file://" + file.getAbsolutePath();
|
||||
updateEngine.applyPayload(zipFileUri, offset, 0, headerKeyValuePairs);
|
||||
mUpdateEngine.applyPayload(zipFileUri, offset, 0, headerKeyValuePairs);
|
||||
|
||||
mUpdaterController.getActualUpdate(mDownloadId).setStatus(UpdateStatus.INSTALLING);
|
||||
mUpdaterController.notifyUpdateChange(mDownloadId);
|
||||
|
||||
PreferenceManager.getDefaultSharedPreferences(mContext).edit()
|
||||
.putString(PREF_INSTALLING_AB_ID, mDownloadId)
|
||||
.apply();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean reconnect() {
|
||||
if (!isInstallingUpdate(mContext)) {
|
||||
Log.e(TAG, "reconnect: Not installing any update");
|
||||
return false;
|
||||
}
|
||||
|
||||
mReconnecting = true;
|
||||
mDownloadId = PreferenceManager.getDefaultSharedPreferences(mContext)
|
||||
.getString(PREF_INSTALLING_AB_ID, null);
|
||||
|
||||
mUpdateEngine = new UpdateEngine();
|
||||
// We will get a status notification as soon as we are connected
|
||||
return mUpdateEngine.bind(mUpdateEngineCallback);
|
||||
}
|
||||
|
||||
private void installationDone() {
|
||||
PreferenceManager.getDefaultSharedPreferences(mContext).edit()
|
||||
.remove(PREF_INSTALLING_AB_ID)
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user