Relaunch process without second process

This commit is contained in:
topjohnwu 2022-02-13 02:58:55 -08:00
parent 936ad1aa20
commit 8f0ea5925a
6 changed files with 20 additions and 60 deletions

View File

@ -1,37 +0,0 @@
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);
}
}

View File

@ -2,7 +2,9 @@ package com.topjohnwu.magisk;
import static android.os.Build.VERSION.SDK_INT; import static android.os.Build.VERSION.SDK_INT;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.res.AssetManager; import android.content.res.AssetManager;
@ -56,6 +58,14 @@ public class StubApk {
} catch (Exception ignored) {} } catch (Exception ignored) {}
} }
public static void restartProcess(Activity activity) {
Intent intent = activity.getPackageManager()
.getLaunchIntentForPackage(activity.getPackageName());
activity.finishAffinity();
activity.startActivity(intent);
Runtime.getRuntime().exit(0);
}
public static class Data { public static class Data {
// Indices of the object array // Indices of the object array
private static final int STUB_VERSION = 0; private static final int STUB_VERSION = 0;

View File

@ -9,7 +9,6 @@ import android.net.Uri
import android.os.Build import android.os.Build
import androidx.core.net.toFile import androidx.core.net.toFile
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
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.ActivityTracker
@ -103,8 +102,13 @@ class DownloadService : NotificationService() {
apk.delete() apk.delete()
patched.renameTo(apk) patched.renameTo(apk)
} else { } else {
val clz = Info.stub!!.classToComponent["PHOENIX"]!! ActivityTracker.foreground?.let {
PhoenixActivity.rebirth(this, clz) // Relaunch the process if we are foreground
StubApk.restartProcess(it)
} ?: run {
// Or else simply kill the current process
Runtime.getRuntime().exit(0)
}
return return
} }
} catch (e: Exception) { } catch (e: Exception) {

View File

@ -104,17 +104,6 @@ fun genStubManifest(srcDir: File, outDir: File): String {
true 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(
"com.topjohnwu.magisk.core.Provider", "com.topjohnwu.magisk.core.Provider",
"dummy.DummyProvider", "dummy.DummyProvider",
@ -260,7 +249,7 @@ fun genStubManifest(srcDir: File, outDir: File): String {
} }
} }
if (gen.xml.isNotEmpty()) { if (gen.xml.isNotEmpty()) {
cmps.add(gen.xml.format(name, names.random(kRANDOM))) cmps.add(gen.xml.format(name))
} }
} }

View File

@ -8,19 +8,13 @@ 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 {
String n = Mapping.get(name); return super.loadClass(Mapping.get(name), resolve);
if (n.equals(PKEY))
return PhoenixActivity.class;
return super.loadClass(n, resolve);
} }
} }

View File

@ -109,7 +109,7 @@ 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();
PhoenixActivity.rebirth(this, InjectedClassLoader.PHOENIX); StubApk.restartProcess(this);
finish(); finish();
}; };
// Download and upgrade the app // Download and upgrade the app