Simplify subclass changes, fix mkdir missing on lollipop
This commit is contained in:
parent
4775c17653
commit
709bd9d699
@ -1,5 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 3
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
|
* MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
package org.fdroid.fdroid.installer;
|
package org.fdroid.fdroid.installer;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
|
||||||
@ -11,6 +31,12 @@ import java.util.List;
|
|||||||
|
|
||||||
import eu.chainfire.libsuperuser.Shell;
|
import eu.chainfire.libsuperuser.Shell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partly based on
|
||||||
|
* http://omerjerk.in/2014/08/how-to-install-an-app-to-system-partition/
|
||||||
|
* https://github.com/omerjerk/RemoteDroid/blob/master/app/src/main/java/in/omerjerk/remotedroid/app/MainActivity.java
|
||||||
|
*/
|
||||||
|
@TargetApi(Build.VERSION_CODES.FROYO)
|
||||||
abstract class InstallFDroidAsSystem {
|
abstract class InstallFDroidAsSystem {
|
||||||
|
|
||||||
protected final Context context;
|
protected final Context context;
|
||||||
@ -39,59 +65,47 @@ abstract class InstallFDroidAsSystem {
|
|||||||
return context.getString(R.string.system_install_question);
|
return context.getString(R.string.system_install_question);
|
||||||
}
|
}
|
||||||
|
|
||||||
final void performUninstall() {
|
final void runUninstall() {
|
||||||
final String[] commands = {
|
final String[] commands = {
|
||||||
"mount -o rw,remount /system",
|
"mount -o rw,remount /system",
|
||||||
"pm uninstall " + context.getPackageName(),
|
"pm uninstall " + context.getPackageName(),
|
||||||
"rm -f " + installPath(),
|
"rm -f " + getInstallPath(),
|
||||||
"sleep 5",
|
"sleep 5",
|
||||||
"mount -o ro,remount /system"
|
"mount -o ro,remount /system"
|
||||||
};
|
};
|
||||||
Shell.SU.run(commands);
|
Shell.SU.run(commands);
|
||||||
}
|
}
|
||||||
|
|
||||||
final void performInstall() {
|
final void runInstall() {
|
||||||
onPreInstall();
|
onPreInstall();
|
||||||
Shell.SU.run(getCommands());
|
Shell.SU.run(getInstallCommands());
|
||||||
}
|
}
|
||||||
|
|
||||||
private String installPath() {
|
protected String getInstallPath() {
|
||||||
return getSystemFolder() + "FDroid.apk";
|
return getSystemFolder() + "FDroid.apk";
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<String> getCommands() {
|
private List<String> getInstallCommands() {
|
||||||
final List<String> commands = new ArrayList<>();
|
final List<String> commands = new ArrayList<>();
|
||||||
commands.add(makePartitionWriteable());
|
commands.add("mount -o rw,remount /system");
|
||||||
commands.add(copyApkToPartition());
|
commands.addAll(getCopyToSystemCommands());
|
||||||
commands.add(uninstallFDroid());
|
commands.add("pm uninstall -k " + context.getPackageName()); // -k to retain data
|
||||||
commands.addAll(reinstallFDroidAsSystem());
|
commands.add("mv " + getInstallPath() + ".tmp " + getInstallPath());
|
||||||
commands.addAll(makePartitionReadOnly());
|
commands.add("pm install -r " + getInstallPath());
|
||||||
return commands;
|
commands.add("sleep 5"); // wait until the app is really installed
|
||||||
}
|
|
||||||
|
|
||||||
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("mount -o ro,remount /system");
|
||||||
|
commands.addAll(getPostInstallCommands());
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> getCopyToSystemCommands() {
|
||||||
|
final List<String> commands = new ArrayList<>(1);
|
||||||
|
commands.add("cat " + context.getPackageCodePath() + " > " + getInstallPath() + ".tmp");
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> getPostInstallCommands() {
|
||||||
|
final List<String> commands = new ArrayList<>(1);
|
||||||
commands.add("am start -n org.fdroid.fdroid/.installer.InstallIntoSystemDialogActivity --ez post_install true");
|
commands.add("am start -n org.fdroid.fdroid/.installer.InstallIntoSystemDialogActivity --ez post_install true");
|
||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
@ -116,7 +130,7 @@ abstract class InstallFDroidAsSystem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* New folder introduced in
|
* On KitKat, "Some system apps are more system than others"
|
||||||
* https://github.com/android/platform_frameworks_base/commit/ccbf84f44c9e6a5ed3c08673614826bb237afc54
|
* https://github.com/android/platform_frameworks_base/commit/ccbf84f44c9e6a5ed3c08673614826bb237afc54
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@ -126,33 +140,17 @@ abstract class InstallFDroidAsSystem {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* History of PackageManagerService in Lollipop:
|
||||||
|
* https://github.com/android/platform_frameworks_base/commits/lollipop-release/services/core/java/com/android/server/pm/PackageManagerService.java
|
||||||
|
*/
|
||||||
private static class LollipopImpl extends InstallFDroidAsSystem {
|
private static class LollipopImpl extends InstallFDroidAsSystem {
|
||||||
|
|
||||||
public LollipopImpl(Context context) {
|
public LollipopImpl(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* New cluster based installation and app dirs
|
|
||||||
*/
|
|
||||||
@Override
|
@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() {
|
protected void onPreInstall() {
|
||||||
// Setup preference to execute postInstall after reboot
|
// Setup preference to execute postInstall after reboot
|
||||||
Preferences.get().setPostSystemInstall(true);
|
Preferences.get().setPostSystemInstall(true);
|
||||||
@ -162,6 +160,43 @@ abstract class InstallFDroidAsSystem {
|
|||||||
return context.getString(R.string.system_install_question_lollipop);
|
return context.getString(R.string.system_install_question_lollipop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cluster-style layout where each app is placed in a unique directory
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getSystemFolder() {
|
||||||
|
return "/system/priv-app/FDroid/";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create app directory
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected List<String> getCopyToSystemCommands() {
|
||||||
|
List<String> commands = new ArrayList<>(2);
|
||||||
|
commands.add("mkdir " + getSystemFolder()); // create app directory if not existing
|
||||||
|
commands.add("cat " + context.getPackageCodePath() + " > " + getInstallPath() + ".tmp");
|
||||||
|
return commands;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Currently only works with reboot
|
||||||
|
* <p/>
|
||||||
|
* File observers on /system/priv-app/ have been removed because they don't work with the new
|
||||||
|
* cluser-style layout. See
|
||||||
|
* https://github.com/android/platform_frameworks_base/commit/84e71d1d61c53cd947becc7879e05947be681103
|
||||||
|
* <p/>
|
||||||
|
* Related stack overflow post: http://stackoverflow.com/q/26487750
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected List<String> getPostInstallCommands() {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,11 +22,9 @@ package org.fdroid.fdroid.installer;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.FragmentActivity;
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
@ -38,25 +36,10 @@ import org.fdroid.fdroid.FDroidApp;
|
|||||||
import org.fdroid.fdroid.Preferences;
|
import org.fdroid.fdroid.Preferences;
|
||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import eu.chainfire.libsuperuser.Shell;
|
import eu.chainfire.libsuperuser.Shell;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: This activity has no view on its own, it displays consecutive dialogs.
|
* Note: This activity has no view on its own, it displays consecutive dialogs.
|
||||||
* <p/>
|
|
||||||
* Partly based on https://github.com/omerjerk/RemoteDroid/blob/master/app/src/main/java/in/omerjerk/remotedroid/app/MainActivity.java
|
|
||||||
* http://omerjerk.in/2014/08/how-to-install-an-app-to-system-partition/
|
|
||||||
* <p/>
|
|
||||||
* Info for lollipop:
|
|
||||||
* http://stackoverflow.com/q/26487750
|
|
||||||
* <p/>
|
|
||||||
* Removed apk observers in
|
|
||||||
* https://github.com/android/platform_frameworks_base/commit/84e71d1d61c53cd947becc7879e05947be681103
|
|
||||||
* <p/>
|
|
||||||
* History of PackageManagerService:
|
|
||||||
* https://github.com/android/platform_frameworks_base/commits/lollipop-release/services/core/java/com/android/server/pm/PackageManagerService.java
|
|
||||||
*/
|
*/
|
||||||
public class InstallIntoSystemDialogActivity extends FragmentActivity {
|
public class InstallIntoSystemDialogActivity extends FragmentActivity {
|
||||||
|
|
||||||
@ -209,7 +192,7 @@ public class InstallIntoSystemDialogActivity extends FragmentActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... voids) {
|
protected Void doInBackground(Void... voids) {
|
||||||
InstallFDroidAsSystem.create(getApplicationContext()).performInstall();
|
InstallFDroidAsSystem.create(getApplicationContext()).runInstall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -299,7 +282,7 @@ public class InstallIntoSystemDialogActivity extends FragmentActivity {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(Void... voids) {
|
protected Void doInBackground(Void... voids) {
|
||||||
InstallFDroidAsSystem.create(getApplicationContext()).performUninstall();
|
InstallFDroidAsSystem.create(getApplicationContext()).runUninstall();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user