Refactored system app converter into classes.
The multiple occurances of "if (Build.SDK_INT < ... )" statements hint at the prospect that there are a couple of different implementations of this class which behave differently. The new classes start with InstallFDroidAsSystem, and then there are SDK specific subclasses which provide the customization relevant for those subclasses.
This commit is contained in:
parent
c27d8f6287
commit
4775c17653
@ -0,0 +1,167 @@
|
||||
package org.fdroid.fdroid.installer;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import eu.chainfire.libsuperuser.Shell;
|
||||
|
||||
abstract class InstallFDroidAsSystem {
|
||||
|
||||
protected final Context context;
|
||||
|
||||
public InstallFDroidAsSystem(final Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public static InstallFDroidAsSystem create(final Context context) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
return new LollipopImpl(context);
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
return new KitKatToLollipopImpl(context);
|
||||
} else {
|
||||
return new PreKitKatImpl(context);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String getSystemFolder();
|
||||
|
||||
protected void onPreInstall() {
|
||||
// To be overridden by relevant base class[es]
|
||||
}
|
||||
|
||||
public String getWarningInfo() {
|
||||
return context.getString(R.string.system_install_question);
|
||||
}
|
||||
|
||||
final void performUninstall() {
|
||||
final String[] commands = {
|
||||
"mount -o rw,remount /system",
|
||||
"pm uninstall " + context.getPackageName(),
|
||||
"rm -f " + installPath(),
|
||||
"sleep 5",
|
||||
"mount -o ro,remount /system"
|
||||
};
|
||||
Shell.SU.run(commands);
|
||||
}
|
||||
|
||||
final void performInstall() {
|
||||
onPreInstall();
|
||||
Shell.SU.run(getCommands());
|
||||
}
|
||||
|
||||
private String installPath() {
|
||||
return getSystemFolder() + "FDroid.apk";
|
||||
}
|
||||
|
||||
private List<String> getCommands() {
|
||||
final List<String> commands = new ArrayList<>();
|
||||
commands.add(makePartitionWriteable());
|
||||
commands.add(copyApkToPartition());
|
||||
commands.add(uninstallFDroid());
|
||||
commands.addAll(reinstallFDroidAsSystem());
|
||||
commands.addAll(makePartitionReadOnly());
|
||||
return commands;
|
||||
}
|
||||
|
||||
protected String makePartitionWriteable() {
|
||||
return "mount -o rw,remount /system";
|
||||
}
|
||||
|
||||
protected String copyApkToPartition() {
|
||||
return "cat " + context.getPackageCodePath() + " > " + installPath() + ".tmp";
|
||||
}
|
||||
|
||||
protected String uninstallFDroid() {
|
||||
return "pm uninstall -k " + context.getPackageName();
|
||||
}
|
||||
|
||||
protected List<String> reinstallFDroidAsSystem() {
|
||||
final List<String> commands = new ArrayList<>(3);
|
||||
commands.add("mv " + installPath() + ".tmp " + installPath());
|
||||
commands.add("pm install -r " + installPath());
|
||||
commands.add("sleep 5");
|
||||
return commands;
|
||||
}
|
||||
|
||||
protected List<String> makePartitionReadOnly() {
|
||||
final List<String> commands = new ArrayList<>(2);
|
||||
commands.add("mount -o ro,remount /system");
|
||||
commands.add("am start -n org.fdroid.fdroid/.installer.InstallIntoSystemDialogActivity --ez post_install true");
|
||||
return commands;
|
||||
}
|
||||
|
||||
private static class PreKitKatImpl extends InstallFDroidAsSystem {
|
||||
|
||||
public PreKitKatImpl(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSystemFolder() {
|
||||
return "/system/app";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class KitKatToLollipopImpl extends InstallFDroidAsSystem {
|
||||
|
||||
public KitKatToLollipopImpl(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* New folder introduced in
|
||||
* https://github.com/android/platform_frameworks_base/commit/ccbf84f44c9e6a5ed3c08673614826bb237afc54
|
||||
*/
|
||||
@Override
|
||||
protected String getSystemFolder() {
|
||||
return "/system/priv-app/";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class LollipopImpl extends InstallFDroidAsSystem {
|
||||
|
||||
public LollipopImpl(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* New cluster based installation and app dirs
|
||||
*/
|
||||
@Override
|
||||
protected String getSystemFolder() {
|
||||
return "/system/priv-app/FDroid/";
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Currently only works with reboot. Find a way how this could work without.
|
||||
* See http://stackoverflow.com/q/26487750
|
||||
*/
|
||||
@Override
|
||||
protected List<String> makePartitionReadOnly() {
|
||||
List<String> commands = new ArrayList<>(3);
|
||||
commands.add("am broadcast -a android.intent.action.ACTION_SHUTDOWN");
|
||||
commands.add("sleep 1");
|
||||
commands.add("reboot");
|
||||
return commands;
|
||||
}
|
||||
|
||||
protected void onPreInstall() {
|
||||
// Setup preference to execute postInstall after reboot
|
||||
Preferences.get().setPostSystemInstall(true);
|
||||
}
|
||||
|
||||
public String getWarningInfo() {
|
||||
return context.getString(R.string.system_install_question_lollipop);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -22,6 +22,7 @@ package org.fdroid.fdroid.installer;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
@ -37,6 +38,9 @@ import org.fdroid.fdroid.FDroidApp;
|
||||
import org.fdroid.fdroid.Preferences;
|
||||
import org.fdroid.fdroid.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import eu.chainfire.libsuperuser.Shell;
|
||||
|
||||
/**
|
||||
@ -63,55 +67,6 @@ public class InstallIntoSystemDialogActivity extends FragmentActivity {
|
||||
public static final String ACTION_POST_INSTALL = "post_install";
|
||||
public static final String ACTION_FIRST_TIME = "first_time";
|
||||
|
||||
private static String SYSTEM_FOLDER;
|
||||
|
||||
static {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
|
||||
SYSTEM_FOLDER = "/system/app/";
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
|
||||
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
// new folder introduced in
|
||||
// https://github.com/android/platform_frameworks_base/commit/ccbf84f44c9e6a5ed3c08673614826bb237afc54
|
||||
SYSTEM_FOLDER = "/system/priv-app/";
|
||||
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// new cluster based installation and app dirs
|
||||
SYSTEM_FOLDER = "/system/priv-app/FDroid/";
|
||||
}
|
||||
}
|
||||
|
||||
private static final String APK_NAME = "FDroid.apk";
|
||||
|
||||
private static final String CMD_SCRIPT_KITKAT = "mount -o rw,remount /system\n" +
|
||||
"cat %s > " + SYSTEM_FOLDER + APK_NAME + ".tmp\n" +
|
||||
"chmod 655 " + SYSTEM_FOLDER + APK_NAME + ".tmp\n" +
|
||||
"pm uninstall -k %s\n" + // -k to retain data
|
||||
"mv " + SYSTEM_FOLDER + APK_NAME + ".tmp " + SYSTEM_FOLDER + APK_NAME + "\n" +
|
||||
"pm install -r " + SYSTEM_FOLDER + APK_NAME + "\n" +
|
||||
"sleep 5\n" +
|
||||
"mount -o ro,remount /system\n" +
|
||||
"am start -n org.fdroid.fdroid/.installer.InstallIntoSystemDialogActivity --ez post_install true";
|
||||
|
||||
// TODO: Currently only works with reboot. Find a way how this could work without.
|
||||
// See http://stackoverflow.com/q/26487750
|
||||
private static final String CMD_SCRIPT_LOLLIPOP_REBOOT = "am broadcast -a android.intent.action.ACTION_SHUTDOWN\n" +
|
||||
"sleep 1\n" +
|
||||
"reboot";
|
||||
|
||||
private static final String CMD_SCRIPT_LOLLIPOP = "mount -o rw,remount /system\n" +
|
||||
"mkdir " + SYSTEM_FOLDER + "\n" + // cluster based app directories
|
||||
"cat %s > " + SYSTEM_FOLDER + APK_NAME + ".tmp\n" +
|
||||
"chmod 655 " + SYSTEM_FOLDER + APK_NAME + ".tmp\n" +
|
||||
"pm uninstall -k %s\n" + // -k to retain data
|
||||
"mv " + SYSTEM_FOLDER + APK_NAME + ".tmp " + SYSTEM_FOLDER + APK_NAME + "\n" +
|
||||
"pm install -r " + SYSTEM_FOLDER + APK_NAME + "\n" +
|
||||
"sleep 5\n" + CMD_SCRIPT_LOLLIPOP_REBOOT;
|
||||
|
||||
private static final String CMD_UNINSTALL = "mount -o rw,remount /system\n" +
|
||||
"pm uninstall %s\n" +
|
||||
"rm -f " + SYSTEM_FOLDER + APK_NAME + "\n" +
|
||||
"sleep 5\n" +
|
||||
"mount -o ro,remount /system";
|
||||
|
||||
String action;
|
||||
|
||||
@Override
|
||||
@ -147,13 +102,7 @@ public class InstallIntoSystemDialogActivity extends FragmentActivity {
|
||||
ContextThemeWrapper theme = new ContextThemeWrapper(this, FDroidApp.getCurThemeResId());
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(theme);
|
||||
String message = getString(R.string.system_install_first_time_message) +
|
||||
"<br/><br/>";
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
message += getString(R.string.system_install_question_lollipop);
|
||||
} else {
|
||||
message += getString(R.string.system_install_question);
|
||||
}
|
||||
String message = getString(R.string.system_install_first_time_message) + "<br/><br/>" + InstallFDroidAsSystem.create(getApplicationContext()).getWarningInfo();
|
||||
builder.setMessage(Html.fromHtml(message));
|
||||
builder.setPositiveButton(R.string.system_permission_install_via_root, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
@ -260,22 +209,7 @@ public class InstallIntoSystemDialogActivity extends FragmentActivity {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
// execute postInstall after reboot
|
||||
Preferences.get().setPostSystemInstall(true);
|
||||
|
||||
Shell.SU.run(String.format(CMD_SCRIPT_LOLLIPOP,
|
||||
new String[]{
|
||||
InstallIntoSystemDialogActivity.this.getPackageCodePath(),
|
||||
InstallIntoSystemDialogActivity.this.getPackageName()
|
||||
}));
|
||||
} else {
|
||||
Shell.SU.run(String.format(CMD_SCRIPT_KITKAT,
|
||||
new String[]{
|
||||
InstallIntoSystemDialogActivity.this.getPackageCodePath(),
|
||||
InstallIntoSystemDialogActivity.this.getPackageName()
|
||||
}));
|
||||
}
|
||||
InstallFDroidAsSystem.create(getApplicationContext()).performInstall();
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@ -365,10 +299,7 @@ public class InstallIntoSystemDialogActivity extends FragmentActivity {
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... voids) {
|
||||
Shell.SU.run(String.format(CMD_UNINSTALL,
|
||||
new String[]{
|
||||
InstallIntoSystemDialogActivity.this.getPackageName()
|
||||
}));
|
||||
InstallFDroidAsSystem.create(getApplicationContext()).performUninstall();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user