Commit c1fc3f37 authored by topjohnwu's avatar topjohnwu

Proper app relaunch for stub

parent f4cf5dc0
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);
}
}
package com.topjohnwu.magisk.core.download 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 androidx.core.net.toFile
import com.topjohnwu.magisk.PhoenixActivity
import com.topjohnwu.magisk.R import com.topjohnwu.magisk.R
import com.topjohnwu.magisk.StubApk import com.topjohnwu.magisk.StubApk
import com.topjohnwu.magisk.core.ActivityTracker
import com.topjohnwu.magisk.core.Info import com.topjohnwu.magisk.core.Info
import com.topjohnwu.magisk.core.isRunningAsStub import com.topjohnwu.magisk.core.isRunningAsStub
import com.topjohnwu.magisk.core.tasks.HideAPK import com.topjohnwu.magisk.core.tasks.HideAPK
...@@ -59,17 +55,8 @@ suspend fun DownloadService.handleAPK(subject: Subject.Manager, stream: InputStr ...@@ -59,17 +55,8 @@ suspend fun DownloadService.handleAPK(subject: Subject.Manager, stream: InputStr
apk.delete() apk.delete()
patched.renameTo(apk) patched.renameTo(apk)
} else { } else {
val intent = packageManager.getLaunchIntentForPackage(packageName) val clz = Info.stub!!.classToComponent["PHOENIX"]!!
intent!!.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) PhoenixActivity.rebirth(this, clz)
//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<AlarmManager>()
alarm!!.set(AlarmManager.RTC, System.currentTimeMillis() + 1000, pending)
}
stopSelf()
Runtime.getRuntime().exit(0)
} }
} else { } else {
write(subject.file.outputStream()) write(subject.file.outputStream())
......
...@@ -77,7 +77,8 @@ fun genStubManifest(srcDir: File, outDir: File): String { ...@@ -77,7 +77,8 @@ fun genStubManifest(srcDir: File, outDir: File): String {
class Component( class Component(
val real: String, val real: String,
val stub: String, val stub: String,
val xml: String val xml: String,
val genClass: Boolean = false
) )
outDir.deleteRecursively() outDir.deleteRecursively()
...@@ -92,13 +93,26 @@ fun genStubManifest(srcDir: File, outDir: File): String { ...@@ -92,13 +93,26 @@ fun genStubManifest(srcDir: File, outDir: File): String {
cmpList.add(Component( cmpList.add(Component(
"androidx.core.app.CoreComponentFactory", "androidx.core.app.CoreComponentFactory",
"DelegateComponentFactory", "DelegateComponentFactory",
"" "",
true
)) ))
cmpList.add(Component( cmpList.add(Component(
"com.topjohnwu.magisk.core.App", "com.topjohnwu.magisk.core.App",
"DelegateApplication", "DelegateApplication",
"" "",
true
))
cmpList.add(Component(
"PHOENIX",
"PhoenixActivity",
"""
|<activity
| android:name="%s"
| android:process=":%s"
| android:exported="false" />""".ind(2),
true
)) ))
cmpList.add(Component( cmpList.add(Component(
...@@ -236,12 +250,12 @@ fun genStubManifest(srcDir: File, outDir: File): String { ...@@ -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("|internalMap.put(\"$name\", com.topjohnwu.magisk.${gen.stub}.class);".ind(2))
maps.append('\n') maps.append('\n')
} }
if (gen.stub.startsWith("Delegate")) { if (gen.genClass) {
genClass(name, gen.stub) genClass(name, gen.stub)
} }
} }
if (gen.xml.isNotEmpty()) { if (gen.xml.isNotEmpty()) {
cmps.add(gen.xml.format(name)) cmps.add(gen.xml.format(name, names.random(kRANDOM)))
} }
} }
......
...@@ -8,13 +8,19 @@ import java.io.File; ...@@ -8,13 +8,19 @@ import java.io.File;
// mapping when loading from platform (via LoadedApk.mClassLoader) // mapping when loading from platform (via LoadedApk.mClassLoader)
class InjectedClassLoader extends ClassLoader { class InjectedClassLoader extends ClassLoader {
private static final String PKEY = "PHOENIX";
static final String PHOENIX = Mapping.inverseMap.get(PKEY);
InjectedClassLoader(File apk) { InjectedClassLoader(File apk) {
super(new DynamicClassLoader(apk)); super(new DynamicClassLoader(apk));
} }
@Override @Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 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);
} }
} }
......
...@@ -5,7 +5,6 @@ import static android.R.string.ok; ...@@ -5,7 +5,6 @@ import static android.R.string.ok;
import static android.R.string.yes; import static android.R.string.yes;
import static com.topjohnwu.magisk.R.string.dling; 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.no_internet_msg;
import static com.topjohnwu.magisk.R.string.relaunch_app;
import static com.topjohnwu.magisk.R.string.upgrade_msg; import static com.topjohnwu.magisk.R.string.upgrade_msg;
import android.app.Activity; import android.app.Activity;
...@@ -17,7 +16,6 @@ import android.os.AsyncTask; ...@@ -17,7 +16,6 @@ import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper;
import android.widget.Toast;
import com.topjohnwu.magisk.net.Networking; import com.topjohnwu.magisk.net.Networking;
import com.topjohnwu.magisk.net.Request; import com.topjohnwu.magisk.net.Request;
...@@ -111,14 +109,14 @@ public class DownloadActivity extends Activity { ...@@ -111,14 +109,14 @@ public class DownloadActivity extends Activity {
dialog = ProgressDialog.show(themed, getString(dling), getString(dling) + " " + APP_NAME, true); dialog = ProgressDialog.show(themed, getString(dling), getString(dling) + " " + APP_NAME, true);
Runnable onSuccess = () -> { Runnable onSuccess = () -> {
dialog.dismiss(); dialog.dismiss();
Toast.makeText(themed, relaunch_app, Toast.LENGTH_LONG).show(); PhoenixActivity.rebirth(this, InjectedClassLoader.PHOENIX);
finish(); finish();
}; };
// Download and upgrade the app // Download and upgrade the app
File apk = dynLoad ? StubApk.current(this) : new File(getCacheDir(), "manager.apk"); File apk = dynLoad ? StubApk.current(this) : new File(getCacheDir(), "manager.apk");
request(apkLink).setExecutor(AsyncTask.THREAD_POOL_EXECUTOR).getAsFile(apk, file -> { request(apkLink).setExecutor(AsyncTask.THREAD_POOL_EXECUTOR).getAsFile(apk, file -> {
if (dynLoad) { if (dynLoad) {
// TODO runOnUiThread(onSuccess);
} else { } else {
var receiver = APKInstall.register(this, BuildConfig.APPLICATION_ID, onSuccess); var receiver = APKInstall.register(this, BuildConfig.APPLICATION_ID, onSuccess);
APKInstall.installapk(this, file); APKInstall.installapk(this, file);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment