aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGabriele M <moto.falcon.git@gmail.com>2017-07-21 01:17:19 +0200
committerGabriele M <moto.falcon.git@gmail.com>2017-07-21 17:05:53 +0200
commit20ea5136845ae4c108167bb98d5621d76df124eb (patch)
tree049aa786879fd835918402095fb45d7adba394f4
parent09968f1b25b91fc292491cfa62020733a6fee6c5 (diff)
downloadandroid_packages_apps_Updater-20ea5136845ae4c108167bb98d5621d76df124eb.tar.gz
android_packages_apps_Updater-20ea5136845ae4c108167bb98d5621d76df124eb.tar.bz2
android_packages_apps_Updater-20ea5136845ae4c108167bb98d5621d76df124eb.zip
Create a copy of the zips on encrypted devices
On encrypted devices, uncrypt modifies the zip so that it can be read without mounting the filesystem. Instead of installing the zip downloaded, create a copy of it which will be deleted. This will allow to re-install the zip multiple times or export it after installing it.
-rw-r--r--res/values/strings.xml2
-rw-r--r--src/org/lineageos/updater/controller/UpdaterService.java29
-rw-r--r--src/org/lineageos/updater/misc/Constants.java2
-rw-r--r--src/org/lineageos/updater/misc/FileUtils.java76
-rw-r--r--src/org/lineageos/updater/misc/Utils.java30
5 files changed, 136 insertions, 3 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 94e844f..0b6ae93 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -48,6 +48,8 @@
<string name="installing_update_finished">Update installed</string>
<string name="finalizing_package">Finalizing package installation</string>
<string name="preparing_ota_first_boot">Preparing for first boot</string>
+ <string name="dialog_prepare_zip_message">Preliminary update preparation</string>
+ <string name="notification_prepare_zip_error_title">Could not prepare update</string>
<string name="reboot">Reboot</string>
diff --git a/src/org/lineageos/updater/controller/UpdaterService.java b/src/org/lineageos/updater/controller/UpdaterService.java
index 57e2371..c360032 100644
--- a/src/org/lineageos/updater/controller/UpdaterService.java
+++ b/src/org/lineageos/updater/controller/UpdaterService.java
@@ -34,11 +34,14 @@ import org.lineageos.updater.R;
import org.lineageos.updater.UpdaterReceiver;
import org.lineageos.updater.UpdatesActivity;
import org.lineageos.updater.misc.BuildInfoUtils;
+import org.lineageos.updater.misc.Constants;
+import org.lineageos.updater.misc.FileUtils;
import org.lineageos.updater.misc.StringGenerator;
import org.lineageos.updater.misc.Utils;
import org.lineageos.updater.model.UpdateInfo;
import org.lineageos.updater.model.UpdateStatus;
+import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.NumberFormat;
@@ -169,7 +172,22 @@ public class UpdaterService extends Service {
if (Utils.isABUpdate(update.getFile())) {
ABUpdateInstaller.start(mUpdaterController, downloadId);
} else {
- android.os.RecoverySystem.installPackage(this, update.getFile());
+ if (update.getFile().getAbsolutePath().startsWith("/data/") &&
+ Utils.isDeviceEncrypted(this)) {
+ // uncrypt rewrites the file so that it can be read without mounting
+ // the filesystem, so create a copy of it.
+ File uncrytpFile = new File(
+ update.getFile().getAbsolutePath() + Constants.UNCRYPT_FILE_EXT);
+ FileUtils.prepareForUncrypt(this, update.getFile(), uncrytpFile,
+ new Runnable() {
+ @Override
+ public void run() {
+ installPackage(uncrytpFile);
+ }
+ });
+ } else {
+ installPackage(update.getFile());
+ }
}
} catch (IOException e) {
Log.e(TAG, "Could not install update", e);
@@ -180,6 +198,15 @@ public class UpdaterService extends Service {
return START_NOT_STICKY;
}
+ private void installPackage(File update) {
+ try {
+ android.os.RecoverySystem.installPackage(this, update);
+ } catch (IOException e) {
+ // TODO: show error message
+ Log.e(TAG, "Could not install update", e);
+ }
+ }
+
public Controller getUpdaterController() {
return mUpdaterController;
}
diff --git a/src/org/lineageos/updater/misc/Constants.java b/src/org/lineageos/updater/misc/Constants.java
index 570fd4b..5b27bb2 100644
--- a/src/org/lineageos/updater/misc/Constants.java
+++ b/src/org/lineageos/updater/misc/Constants.java
@@ -26,6 +26,8 @@ public final class Constants {
public static final String PREF_LAST_UPDATE_CHECK = "last_update_check";
public static final String PREF_AUTO_UPDATES_CHECK = "auto_updates_check";
+ public static final String UNCRYPT_FILE_EXT = ".uncrypt";
+
public static final String PROP_BUILD_DATE = "ro.build.date.utc";
public static final String PROP_BUILD_VERSION = "ro.cm.build.version";
public static final String PROP_BUILD_VERSION_INCREMENTAL = "ro.build.version.incremental";
diff --git a/src/org/lineageos/updater/misc/FileUtils.java b/src/org/lineageos/updater/misc/FileUtils.java
index c6f7f44..0cfbf93 100644
--- a/src/org/lineageos/updater/misc/FileUtils.java
+++ b/src/org/lineageos/updater/misc/FileUtils.java
@@ -22,6 +22,7 @@ import android.content.DialogInterface;
import android.os.AsyncTask;
import android.support.v7.app.NotificationCompat;
import android.util.Log;
+import android.view.WindowManager;
import org.lineageos.updater.R;
@@ -177,4 +178,79 @@ public class FileUtils {
}
}.execute();
}
+
+ public static void prepareForUncrypt(Context context, File updateFile, File uncryptFile,
+ Runnable callback) {
+
+ final int NOTIFICATION_ID = 12;
+
+ new AsyncTask<Void, String, Boolean>() {
+
+ private ProgressDialog mProgressDialog;
+ private boolean mCancelled;
+ private ProgressCallBack mProgressCallBack;
+
+ @Override
+ protected void onPreExecute() {
+ super.onPreExecute();
+ Log.d(TAG, "Preparing update");
+ mProgressDialog = new ProgressDialog(context);
+ mProgressDialog.setTitle(R.string.app_name);
+ mProgressDialog.setMessage(context.getString(R.string.dialog_prepare_zip_message));
+ mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
+ mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
+ mProgressDialog.setCancelable(true);
+ mProgressDialog.setProgressNumberFormat(null);
+ mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ cancel(true);
+ }
+ });
+ mProgressDialog.setCanceledOnTouchOutside(false);
+ mProgressCallBack = new ProgressCallBack() {
+ @Override
+ public void update(int progress) {
+ mProgressDialog.setProgress(progress);
+ }
+ };
+ mProgressDialog.show();
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... voids) {
+ try {
+ copyFile(updateFile, uncryptFile, mProgressCallBack);
+ } catch (IOException e) {
+ Log.e(TAG, "Error while copying the file", e);
+ }
+ return !mCancelled;
+ }
+
+ @Override
+ protected void onCancelled() {
+ mCancelled = true;
+ uncryptFile.delete();
+ }
+
+ @Override
+ protected void onPostExecute(Boolean success) {
+ if (!success || mCancelled) {
+ Log.e(TAG, "Could not prepare the update, cancelled=" + mCancelled);
+ uncryptFile.delete();
+ NotificationManager nm = (NotificationManager) context.getSystemService(
+ Context.NOTIFICATION_SERVICE);
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
+ builder.setSmallIcon(R.drawable.ic_system_update);
+ builder.setContentTitle(
+ context.getString(R.string.notification_prepare_zip_error_title));
+ final String notificationTag = updateFile.getAbsolutePath();
+ nm.notify(notificationTag, NOTIFICATION_ID, builder.build());
+ } else {
+ callback.run();
+ }
+ mProgressDialog.dismiss();
+ }
+ }.execute();
+ }
}
diff --git a/src/org/lineageos/updater/misc/Utils.java b/src/org/lineageos/updater/misc/Utils.java
index 74b55ce..0426f11 100644
--- a/src/org/lineageos/updater/misc/Utils.java
+++ b/src/org/lineageos/updater/misc/Utils.java
@@ -15,6 +15,7 @@
*/
package org.lineageos.updater.misc;
+import android.app.admin.DevicePolicyManager;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
@@ -42,6 +43,7 @@ import org.lineageos.updater.model.UpdateInfo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
+import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
@@ -222,6 +224,21 @@ public class Utils {
throw new IllegalArgumentException("The given entry was not found");
}
+ public static void removeUncryptFiles(File downloadPath) {
+ File[] uncryptFiles = downloadPath.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith(Constants.UNCRYPT_FILE_EXT);
+ }
+ });
+ if (uncryptFiles == null) {
+ return;
+ }
+ for (File file : uncryptFiles) {
+ file.delete();
+ }
+ }
+
/**
* Cleanup the download directory, which is assumed to be a privileged location
* the user can't access and that might have stale files. This can happen if
@@ -230,14 +247,16 @@ public class Utils {
* @param context
*/
public static void cleanupDownloadsDir(Context context) {
- final String DOWNLOADS_CLEANUP_DONE = "cleanup_done";
+ File downloadPath = getDownloadPath(context);
+
+ removeUncryptFiles(downloadPath);
+ final String DOWNLOADS_CLEANUP_DONE = "cleanup_done";
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if (preferences.getBoolean(DOWNLOADS_CLEANUP_DONE, false)) {
return;
}
- File downloadPath = getDownloadPath(context);
Log.d(TAG, "Cleaning " + downloadPath);
if (!downloadPath.isDirectory()) {
return;
@@ -307,4 +326,11 @@ public class Utils {
clipboard.setPrimaryClip(clip);
Toast.makeText(context, toastMessage, Toast.LENGTH_SHORT).show();
}
+
+ public static boolean isDeviceEncrypted(Context context) {
+ DevicePolicyManager dpm =
+ (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
+ int status = dpm.getStorageEncryptionStatus();
+ return status == DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
+ }
}