Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -284,17 +285,30 @@ private ServiceKey bindInternal(Intent intent, Executor executor, ServiceConnect
public Shell.Task createBindTask(Intent intent, Executor executor, ServiceConnection conn) {
ServiceKey key = bindInternal(intent, executor, conn);
if (key != null) {
pendingTasks.add(() -> bindInternal(intent, executor, conn) == null);
PendingBindTask pending = new PendingBindTask(key, intent, executor, conn);
pendingTasks.add(pending);
int mask = key.isDaemon() ? DAEMON_EN_ROUTE : REMOTE_EN_ROUTE;
if ((flags & mask) == 0) {
flags |= mask;
String action = key.isDaemon() ? CMDLINE_START_DAEMON : CMDLINE_START_SERVICE;
return startRootProcess(key.getName(), action);
return new RootProcessStartTask(startRootProcess(key.getName(), action), key.isDaemon());
}
}
return null;
}

private void cancelPendingBinds(boolean daemon) {
UiThreadHandler.runAndWait(() -> {
int mask = daemon ? DAEMON_EN_ROUTE : REMOTE_EN_ROUTE;
flags &= ~mask;
for (int i = pendingTasks.size() - 1; i >= 0; --i) {
if (pendingTasks.get(i).isDaemon() == daemon) {
pendingTasks.remove(i);
}
}
});
}

public void unbind(@NonNull ServiceConnection conn) {
enforceMainThread();

Expand Down Expand Up @@ -463,7 +477,65 @@ public void onReceive(Context context, Intent intent) {
}
}

private class PendingBindTask implements BindTask {
private final ServiceKey key;
private final Intent intent;
private final Executor executor;
private final ServiceConnection conn;

PendingBindTask(
ServiceKey key,
Intent intent,
Executor executor,
ServiceConnection conn) {
this.key = key;
this.intent = intent;
this.executor = executor;
this.conn = conn;
}

@Override
public boolean isDaemon() {
return key.isDaemon();
}

@Override
public boolean run() {
return bindInternal(intent, executor, conn) == null;
}
}

private class RootProcessStartTask implements Shell.Task {
private final Shell.Task task;
private final boolean daemon;

RootProcessStartTask(Shell.Task task, boolean daemon) {
this.task = task;
this.daemon = daemon;
}

@Override
public void run(
@NonNull OutputStream stdin,
@NonNull InputStream stdout,
@NonNull InputStream stderr) throws IOException {
try {
task.run(stdin, stdout, stderr);
} catch (IOException e) {
cancelPendingBinds(daemon);
throw e;
}
}

@Override
public void shellDied() {
cancelPendingBinds(daemon);
task.shellDied();
}
}

private interface BindTask {
boolean isDaemon();
boolean run();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,11 @@ private static Runnable asRunnable(Shell.Task task) {
Shell shell = Shell.getShell();
if (shell.isRoot()) {
shell.execTask(task);
} else {
task.shellDied();
}
} catch (IOException e) {
task.shellDied();
Utils.err(e);
}
};
Expand Down