|
|
|
@ -45,6 +45,7 @@ import java.io.FileOutputStream;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
|
import java.io.OutputStream;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.zip.ZipEntry;
|
|
|
|
|
import java.util.zip.ZipFile;
|
|
|
|
|
import java.util.zip.ZipInputStream;
|
|
|
|
@ -83,6 +84,7 @@ public class InstallerActivity extends FoxActivity {
|
|
|
|
|
final String checksum;
|
|
|
|
|
final boolean noExtensions;
|
|
|
|
|
final boolean rootless;
|
|
|
|
|
final boolean mmtReborn;
|
|
|
|
|
// Should we allow 3rd part app to install modules?
|
|
|
|
|
if (Constants.INTENT_INSTALL_INTERNAL.equals(intent.getAction())) {
|
|
|
|
|
if (!MainApplication.checkSecret(intent)) {
|
|
|
|
@ -97,6 +99,8 @@ public class InstallerActivity extends FoxActivity {
|
|
|
|
|
Constants.EXTRA_INSTALL_NO_EXTENSIONS, false);
|
|
|
|
|
rootless = intent.getBooleanExtra(// For debug only
|
|
|
|
|
Constants.EXTRA_INSTALL_TEST_ROOTLESS, false);
|
|
|
|
|
mmtReborn = intent.getBooleanExtra(// For debug only
|
|
|
|
|
Constants.EXTRA_INSTALL_MMT_REBORN, false);
|
|
|
|
|
} else {
|
|
|
|
|
Toast.makeText(this, "Unknown intent!", Toast.LENGTH_SHORT).show();
|
|
|
|
|
this.forceBackPressed();
|
|
|
|
@ -136,9 +140,10 @@ public class InstallerActivity extends FoxActivity {
|
|
|
|
|
this.rebootFloatingButton = findViewById(R.id.install_terminal_reboot_fab);
|
|
|
|
|
this.installerTerminal = new InstallerTerminal(
|
|
|
|
|
installTerminal = findViewById(R.id.install_terminal),
|
|
|
|
|
this.isLightTheme(), foreground);
|
|
|
|
|
this.isLightTheme(), foreground, mmtReborn);
|
|
|
|
|
(horizontalScroller != null ? horizontalScroller : installTerminal)
|
|
|
|
|
.setBackground(new ColorDrawable(background));
|
|
|
|
|
installTerminal.setItemAnimator(null);
|
|
|
|
|
this.progressIndicator.setVisibility(View.GONE);
|
|
|
|
|
this.progressIndicator.setIndeterminate(true);
|
|
|
|
|
this.getWindow().setFlags( // Note: Doesn't require WAKELOCK permission
|
|
|
|
@ -305,6 +310,7 @@ public class InstallerActivity extends FoxActivity {
|
|
|
|
|
String moduleId = null;
|
|
|
|
|
boolean anyKernel3 = false;
|
|
|
|
|
boolean magiskModule = false;
|
|
|
|
|
boolean mmtReborn = false;
|
|
|
|
|
String MAGISK_PATH = InstallerInitializer.peekMagiskPath();
|
|
|
|
|
if (MAGISK_PATH == null) {
|
|
|
|
|
this.setInstallStateFinished(false, "! Unable to resolve magisk path", "");
|
|
|
|
@ -337,6 +343,11 @@ public class InstallerActivity extends FoxActivity {
|
|
|
|
|
}
|
|
|
|
|
ZipEntry moduleProp = zipFile.getEntry("module.prop");
|
|
|
|
|
magiskModule = moduleProp != null;
|
|
|
|
|
if (zipFile.getEntry("install.sh") == null &&
|
|
|
|
|
zipFile.getEntry("customize.sh") == null &&
|
|
|
|
|
zipFile.getEntry("setup.sh") != null && magiskModule) {
|
|
|
|
|
mmtReborn = true; // MMT-Reborn require a separate runtime
|
|
|
|
|
}
|
|
|
|
|
moduleId = PropUtils.readModuleId(zipFile
|
|
|
|
|
.getInputStream(zipFile.getEntry("module.prop")));
|
|
|
|
|
} catch (IOException ignored) {
|
|
|
|
@ -378,6 +389,7 @@ public class InstallerActivity extends FoxActivity {
|
|
|
|
|
}
|
|
|
|
|
String installCommand;
|
|
|
|
|
File installExecutable;
|
|
|
|
|
boolean magiskCmdLine = false;
|
|
|
|
|
if (anyKernel3 && moduleId == null) { // AnyKernel zip don't have a moduleId
|
|
|
|
|
this.warnReboot = true; // We should probably re-flash magisk...
|
|
|
|
|
installExecutable = this.extractInstallScript("anykernel3_installer.sh");
|
|
|
|
@ -398,6 +410,7 @@ public class InstallerActivity extends FoxActivity {
|
|
|
|
|
installCommand = "magisk --install-module \"" + file.getAbsolutePath() + "\"";
|
|
|
|
|
installExecutable = new File(MAGISK_PATH.equals("/sbin") ?
|
|
|
|
|
"/sbin/magisk" : "/system/bin/magisk");
|
|
|
|
|
magiskCmdLine = true;
|
|
|
|
|
} else if (moduleId != null) {
|
|
|
|
|
installExecutable = this.extractInstallScript("module_installer_compat.sh");
|
|
|
|
|
if (installExecutable == null) {
|
|
|
|
@ -435,6 +448,7 @@ public class InstallerActivity extends FoxActivity {
|
|
|
|
|
"export MMM_TEXT_WRAP=" + (this.textWrap ? "1" : "0"),
|
|
|
|
|
this.installerTerminal.isAnsiEnabled() ?
|
|
|
|
|
AnsiConstants.ANSI_CMD_SUPPORT : "true",
|
|
|
|
|
mmtReborn ? "export MMM_MMT_REBORN=1" : "true",
|
|
|
|
|
"export BOOTMODE=true", anyKernel3 ? "export AK3TMPFS=" +
|
|
|
|
|
InstallerInitializer.peekMagiskPath() + "/ak3tmpfs" :
|
|
|
|
|
"cd \"" + this.moduleCache.getAbsolutePath() + "\"",
|
|
|
|
@ -445,14 +459,19 @@ public class InstallerActivity extends FoxActivity {
|
|
|
|
|
Breadcrumb breadcrumb = new Breadcrumb();
|
|
|
|
|
breadcrumb.setType("install");
|
|
|
|
|
breadcrumb.setData("moduleId", moduleId == null ? "<null>" : moduleId);
|
|
|
|
|
breadcrumb.setData("mmtReborn", mmtReborn ? "true" : "false");
|
|
|
|
|
breadcrumb.setData("isAnyKernel3", anyKernel3 ? "true" : "false");
|
|
|
|
|
breadcrumb.setData("noExtensions", noExtensions ? "true" : "false");
|
|
|
|
|
breadcrumb.setData("magiskCmdLine", magiskCmdLine ? "true" : "false");
|
|
|
|
|
breadcrumb.setData("ansi", this.installerTerminal
|
|
|
|
|
.isAnsiEnabled() ? "enabled" : "disabled");
|
|
|
|
|
breadcrumb.setCategory("app.action.install");
|
|
|
|
|
breadcrumb.setLevel(SentryLevel.INFO);
|
|
|
|
|
Sentry.addBreadcrumb(breadcrumb);
|
|
|
|
|
}
|
|
|
|
|
if (mmtReborn && magiskCmdLine) {
|
|
|
|
|
Log.w(TAG, "mmtReborn and magiskCmdLine may not work well together");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
boolean success = installJob.exec().isSuccess();
|
|
|
|
|
// Wait one UI cycle before disabling controller or processing results
|
|
|
|
@ -678,14 +697,18 @@ public class InstallerActivity extends FoxActivity {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final HashSet<String> extracted = new HashSet<>();
|
|
|
|
|
private File extractInstallScript(String script) {
|
|
|
|
|
File compatInstallScript = new File(this.moduleCache, script);
|
|
|
|
|
if (!compatInstallScript.exists() || compatInstallScript.length() == 0) {
|
|
|
|
|
if (!compatInstallScript.exists() || compatInstallScript.length() == 0 ||
|
|
|
|
|
!extracted.contains(script)) {
|
|
|
|
|
try {
|
|
|
|
|
Files.write(compatInstallScript, Files.readAllBytes(
|
|
|
|
|
this.getAssets().open(script)));
|
|
|
|
|
extracted.add(script);
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
compatInstallScript.delete();
|
|
|
|
|
if (compatInstallScript.delete())
|
|
|
|
|
extracted.remove(script);
|
|
|
|
|
Log.e(TAG, "Failed to extract " + script, e);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|