diff --git a/app/shared/src/main/java/com/topjohnwu/magisk/PhoenixActivity.java b/app/shared/src/main/java/com/topjohnwu/magisk/PhoenixActivity.java new file mode 100644 index 000000000..68c6f8ff6 --- /dev/null +++ b/app/shared/src/main/java/com/topjohnwu/magisk/PhoenixActivity.java @@ -0,0 +1,37 @@ +package com.topjohnwu.magisk; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Process; + +import io.michaelrocks.paranoid.Obfuscate; + +// Inspired by https://github.com/JakeWharton/ProcessPhoenix + +@Obfuscate +public class PhoenixActivity extends Activity { + + private static final String PID_KEY = "pid"; + + public static void rebirth(Context context, String clzName) { + var intent = new Intent(); + intent.setComponent(new ComponentName(context, clzName)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(PID_KEY, Process.myPid()); + context.startActivity(intent); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Process.killProcess(getIntent().getIntExtra(PID_KEY, -1)); + var intent = getPackageManager().getLaunchIntentForPackage(getPackageName()); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + finish(); + Runtime.getRuntime().exit(0); + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/core/download/ManagerHandler.kt b/app/src/main/java/com/topjohnwu/magisk/core/download/ManagerHandler.kt index 831c3fc86..d1fdde339 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/download/ManagerHandler.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/download/ManagerHandler.kt @@ -1,13 +1,9 @@ package com.topjohnwu.magisk.core.download -import android.app.AlarmManager -import android.app.PendingIntent -import android.content.Intent -import androidx.core.content.getSystemService import androidx.core.net.toFile +import com.topjohnwu.magisk.PhoenixActivity import com.topjohnwu.magisk.R import com.topjohnwu.magisk.StubApk -import com.topjohnwu.magisk.core.ActivityTracker import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.isRunningAsStub import com.topjohnwu.magisk.core.tasks.HideAPK @@ -59,17 +55,8 @@ suspend fun DownloadService.handleAPK(subject: Subject.Manager, stream: InputStr apk.delete() patched.renameTo(apk) } else { - val intent = packageManager.getLaunchIntentForPackage(packageName) - intent!!.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - //noinspection InlinedApi - val flag = PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT - val pending = PendingIntent.getActivity(this, id, intent, flag) - if (ActivityTracker.hasForeground) { - val alarm = getSystemService() - alarm!!.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pending) - } - stopSelf() - Runtime.getRuntime().exit(0) + val clz = Info.stub!!.classToComponent["PHOENIX"]!! + PhoenixActivity.rebirth(this, clz) } } else { write(subject.file.outputStream()) diff --git a/buildSrc/src/main/java/Codegen.kt b/buildSrc/src/main/java/Codegen.kt index d0116b502..8c29685b6 100644 --- a/buildSrc/src/main/java/Codegen.kt +++ b/buildSrc/src/main/java/Codegen.kt @@ -77,7 +77,8 @@ fun genStubManifest(srcDir: File, outDir: File): String { class Component( val real: String, val stub: String, - val xml: String + val xml: String, + val genClass: Boolean = false ) outDir.deleteRecursively() @@ -92,13 +93,26 @@ fun genStubManifest(srcDir: File, outDir: File): String { cmpList.add(Component( "androidx.core.app.CoreComponentFactory", "DelegateComponentFactory", - "" + "", + true )) cmpList.add(Component( "com.topjohnwu.magisk.core.App", "DelegateApplication", - "" + "", + true + )) + + cmpList.add(Component( + "PHOENIX", + "PhoenixActivity", + """ + |""".ind(2), + true )) cmpList.add(Component( @@ -236,12 +250,12 @@ fun genStubManifest(srcDir: File, outDir: File): String { maps.append("|internalMap.put(\"$name\", com.topjohnwu.magisk.${gen.stub}.class);".ind(2)) maps.append('\n') } - if (gen.stub.startsWith("Delegate")) { + if (gen.genClass) { genClass(name, gen.stub) } } if (gen.xml.isNotEmpty()) { - cmps.add(gen.xml.format(name)) + cmps.add(gen.xml.format(name, names.random(kRANDOM))) } } diff --git a/stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java b/stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java index e92e3680b..ab7f7c824 100644 --- a/stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java +++ b/stub/src/main/java/com/topjohnwu/magisk/ClassLoaders.java @@ -8,13 +8,19 @@ import java.io.File; // mapping when loading from platform (via LoadedApk.mClassLoader) class InjectedClassLoader extends ClassLoader { + private static final String PKEY = "PHOENIX"; + static final String PHOENIX = Mapping.inverseMap.get(PKEY); + InjectedClassLoader(File apk) { super(new DynamicClassLoader(apk)); } @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - return super.loadClass(Mapping.get(name), resolve); + String n = Mapping.get(name); + if (n.equals(PKEY)) + return PhoenixActivity.class; + return super.loadClass(n, resolve); } } diff --git a/stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java b/stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java index 4a64737de..10aa06de9 100644 --- a/stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java +++ b/stub/src/main/java/com/topjohnwu/magisk/DownloadActivity.java @@ -5,7 +5,6 @@ import static android.R.string.ok; import static android.R.string.yes; import static com.topjohnwu.magisk.R.string.dling; import static com.topjohnwu.magisk.R.string.no_internet_msg; -import static com.topjohnwu.magisk.R.string.relaunch_app; import static com.topjohnwu.magisk.R.string.upgrade_msg; import android.app.Activity; @@ -17,7 +16,6 @@ import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.ContextThemeWrapper; -import android.widget.Toast; import com.topjohnwu.magisk.net.Networking; import com.topjohnwu.magisk.net.Request; @@ -111,14 +109,14 @@ public class DownloadActivity extends Activity { dialog = ProgressDialog.show(themed, getString(dling), getString(dling) + " " + APP_NAME, true); Runnable onSuccess = () -> { dialog.dismiss(); - Toast.makeText(themed, relaunch_app, Toast.LENGTH_LONG).show(); + PhoenixActivity.rebirth(this, InjectedClassLoader.PHOENIX); finish(); }; // Download and upgrade the app File apk = dynLoad ? StubApk.current(this) : new File(getCacheDir(), "manager.apk"); request(apkLink).setExecutor(AsyncTask.THREAD_POOL_EXECUTOR).getAsFile(apk, file -> { if (dynLoad) { - // TODO + runOnUiThread(onSuccess); } else { var receiver = APKInstall.register(this, BuildConfig.APPLICATION_ID, onSuccess); APKInstall.installapk(this, file);