Minor IPC changes

This commit is contained in:
topjohnwu 2020-07-28 02:46:12 -07:00
parent ee21b566c1
commit 6f888049d8
6 changed files with 49 additions and 36 deletions

View File

@ -50,9 +50,12 @@ public final class Utils {
Log.d(TAG, "", t);
}
// Unexpected errors, log regardless of
public static void err(Throwable t) {
Log.d(TAG, "", t);
err(TAG, t);
}
public static void err(String tag, Throwable t) {
Log.d(tag, "", t);
}
public static boolean vLog() {

View File

@ -5,7 +5,7 @@ package com.topjohnwu.superuser.internal;
interface IRootIPC {
void broadcast();
IBinder bind(in Intent intent, IBinder client);
IBinder bind(in Intent intent);
void unbind();
void stop();
}

View File

@ -27,6 +27,8 @@ import com.topjohnwu.superuser.internal.Utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import static com.topjohnwu.superuser.ipc.RootService.TAG;
/**
* All hidden Android framework APIs used here are very stable.
* <p>
@ -71,7 +73,7 @@ class HiddenAPIs {
try {
return (IBinder) IPCMain.getService.invoke(null, name);
} catch (Exception e) {
Utils.err(e);
Utils.err(TAG, e);
return null;
}
}
@ -80,7 +82,7 @@ class HiddenAPIs {
try {
IPCMain.addService.invoke(null, name, service);
} catch (Exception e) {
Utils.err(e);
Utils.err(TAG, e);
}
}
}

View File

@ -49,12 +49,13 @@ import static com.topjohnwu.superuser.internal.IPCMain.CMDLINE_STOP_SERVER;
import static com.topjohnwu.superuser.ipc.RootService.serialExecutor;
class IPCClient implements IBinder.DeathRecipient, Closeable {
static final String INTENT_LOGGING_KEY = "logging";
static final String INTENT_DEBUG_KEY = "debug";
static final String INTENT_EXTRA_KEY = "binder_bundle";
static final String BUNDLE_BINDER_KEY = "binder";
static final String LOGGING_ENV = "LIBSU_VERBOSE_LOGGING";
private static final String BROADCAST_ACTION = "com.topjohnwu.superuser.BROADCAST_IPC";
private static final String INTENT_EXTRA_KEY = "binder_bundle";
private static final String BUNDLE_BINDER_KEY = "binder";
private static final String IPCSERVER_CLASSNAME = "com.topjohnwu.superuser.internal.IPCMain";
private final ComponentName name;
private final Map<ServiceConnection, Executor> connections = new HashMap<>();
@ -84,8 +85,7 @@ class IPCClient implements IBinder.DeathRecipient, Closeable {
// Execute main.jar through root shell
String cmd = String.format(Locale.US,
"(CLASSPATH=%s /proc/%d/exe /system/bin %s %s %s)&",
mainJar, Process.myPid(),
"com.topjohnwu.superuser.internal.IPCMain", /* main class */
mainJar, Process.myPid(), IPCSERVER_CLASSNAME,
name.flattenToString(), CMDLINE_STOP_SERVER /* command args */);
// Make sure cmd is properly formatted in shell
cmd = cmd.replace("$", "\\$");
@ -102,11 +102,8 @@ class IPCClient implements IBinder.DeathRecipient, Closeable {
IntentFilter filter = new IntentFilter(getBroadcastAction(name));
context.registerReceiver(new BinderReceiver(), filter);
// Copy intent and add client info into intent extra
intent = new Intent(intent);
if (Utils.vLog()) {
intent.putExtra(INTENT_LOGGING_KEY, true);
}
// Strip extra and add our own data
intent = intent.cloneFilter();
String debugParams = "";
if (Debug.isDebuggerConnected()) {
// Also debug the remote root server
@ -121,25 +118,31 @@ class IPCClient implements IBinder.DeathRecipient, Closeable {
debugParams = "-XjdwpProvider:adbconnection";
}
}
Bundle bundle = new Bundle();
bundle.putBinder(BUNDLE_BINDER_KEY, new Binder());
intent.putExtra(INTENT_EXTRA_KEY, bundle);
// Dump main.jar as trampoline
File mainJar = dumpMainJar(context);
// Execute main.jar through root shell
String cmd = String.format(Locale.US,
"(CLASSPATH=%s /proc/%d/exe %s /system/bin --nice-name=%s:root %s %s %s)&",
"CLASSPATH=%s /proc/%d/exe %s /system/bin --nice-name=%s:root %s %s %s",
mainJar, Process.myPid(), debugParams, context.getPackageName(),
"com.topjohnwu.superuser.internal.IPCMain", /* main class */
IPCSERVER_CLASSNAME, /* main class */
name.flattenToString(), IPCServer.class.getName() /* command args */);
// Make sure cmd is properly formatted in shell
cmd = cmd.replace("$", "\\$");
if (Utils.vLog())
cmd = LOGGING_ENV + "=1 " + cmd;
synchronized (this) {
Shell.su(cmd).exec();
Shell.su("(" + cmd + ")&").exec();
// Wait for broadcast receiver
wait();
}
server.asBinder().linkToDeath(this, 0);
binder = server.bind(intent, new Binder());
binder = server.bind(intent);
}
boolean isSameService(Intent intent) {

View File

@ -19,6 +19,7 @@ package com.topjohnwu.superuser.ipc;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Debug;
import android.os.FileObserver;
import android.os.IBinder;
@ -43,8 +44,10 @@ import static android.os.FileObserver.MODIFY;
import static android.os.FileObserver.MOVED_FROM;
import static android.os.FileObserver.MOVED_TO;
import static com.topjohnwu.superuser.internal.IPCMain.getServiceName;
import static com.topjohnwu.superuser.ipc.IPCClient.BUNDLE_BINDER_KEY;
import static com.topjohnwu.superuser.ipc.IPCClient.INTENT_DEBUG_KEY;
import static com.topjohnwu.superuser.ipc.IPCClient.INTENT_LOGGING_KEY;
import static com.topjohnwu.superuser.ipc.IPCClient.INTENT_EXTRA_KEY;
import static com.topjohnwu.superuser.ipc.IPCClient.LOGGING_ENV;
import static com.topjohnwu.superuser.ipc.RootService.TAG;
class IPCServer extends IRootIPC.Stub implements IBinder.DeathRecipient {
@ -75,6 +78,8 @@ class IPCServer extends IRootIPC.Stub implements IBinder.DeathRecipient {
}
}
Shell.Config.verboseLogging(System.getenv(LOGGING_ENV) != null);
mName = name;
Class<RootService> clz = (Class<RootService>) Class.forName(name.getClassName());
Constructor<RootService> constructor = clz.getDeclaredConstructor();
@ -137,15 +142,11 @@ class IPCServer extends IRootIPC.Stub implements IBinder.DeathRecipient {
}
@Override
public synchronized IBinder bind(Intent intent, IBinder client) {
public synchronized IBinder bind(Intent intent) {
// ComponentName doesn't match, abort
if (!mName.equals(intent.getComponent()))
System.exit(1);
Shell.Config.verboseLogging(intent.getBooleanExtra(INTENT_LOGGING_KEY, false));
Utils.log(TAG, mName + " bind");
if (intent.getBooleanExtra(INTENT_DEBUG_KEY, false)) {
// ActivityThread.attach(true, 0) will set this to system_process
HiddenAPIs.setAppName(service.getPackageName() + ":root");
@ -157,21 +158,25 @@ class IPCServer extends IRootIPC.Stub implements IBinder.DeathRecipient {
}
try {
mClient = client;
client.linkToDeath(this, 0);
Bundle bundle = intent.getBundleExtra(INTENT_EXTRA_KEY);
mClient = bundle.getBinder(BUNDLE_BINDER_KEY);
mClient.linkToDeath(this, 0);
class Container { IBinder obj; }
Container binderContainer = new Container();
Container c = new Container();
UiThreadHandler.runAndWait(() -> {
if (mIntent != null)
if (mIntent != null) {
Utils.log(TAG, mName + " rebind");
service.onRebind(intent);
else
} else {
Utils.log(TAG, mName + " bind");
mIntent = intent.cloneFilter();
binderContainer.obj = service.onBind(intent);
}
c.obj = service.onBind(intent);
});
return binderContainer.obj;
return c.obj;
} catch (Exception e) {
Utils.err(e);
Utils.err(TAG, e);
return null;
}
}
@ -207,7 +212,7 @@ class IPCServer extends IRootIPC.Stub implements IBinder.DeathRecipient {
@Override
public void binderDied() {
Utils.log(TAG, mName + " binderDied");
Utils.log(TAG, "client binderDied");
unbind();
}
}

View File

@ -107,7 +107,7 @@ public abstract class RootService extends ContextWrapper {
client.newConnection(conn, executor);
bound.add(client);
} catch (Exception e) {
Utils.err(e);
Utils.err(TAG, e);
}
});
}
@ -168,7 +168,7 @@ public abstract class RootService extends ContextWrapper {
try {
IPCClient.stopRootServer(intent.getComponent());
} catch (IOException e) {
Utils.err(e);
Utils.err(TAG, e);
}
});
}