Merge "Wait for IApplicationThread events via ping/pong." into udc-dev am: 65391c6b44 am: 6c4dedd2be

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21655453

Change-Id: I47219b7f2b98187f1bdfbaed725afb37760c3b79
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Jeff Sharkey
2023-03-04 14:49:18 +00:00
committed by Automerger Merge Worker
5 changed files with 116 additions and 14 deletions

View File

@@ -1153,6 +1153,11 @@ public final class ActivityThread extends ClientTransactionHandler
sendMessage(H.TIMEOUT_SERVICE, token, startId);
}
@Override
public final void schedulePing(RemoteCallback pong) {
sendMessage(H.PING, pong);
}
@Override
public final void bindApplication(String processName, ApplicationInfo appInfo,
String sdkSandboxClientAppVolumeUuid, String sdkSandboxClientAppPackage,
@@ -2154,6 +2159,7 @@ public final class ActivityThread extends ClientTransactionHandler
public static final int DUMP_GFXINFO = 165;
public static final int DUMP_RESOURCES = 166;
public static final int TIMEOUT_SERVICE = 167;
public static final int PING = 168;
public static final int INSTRUMENT_WITHOUT_RESTART = 170;
public static final int FINISH_INSTRUMENTATION_WITHOUT_RESTART = 171;
@@ -2209,6 +2215,7 @@ public final class ActivityThread extends ClientTransactionHandler
return "FINISH_INSTRUMENTATION_WITHOUT_RESTART";
case DUMP_RESOURCES: return "DUMP_RESOURCES";
case TIMEOUT_SERVICE: return "TIMEOUT_SERVICE";
case PING: return "PING";
}
}
return Integer.toString(code);
@@ -2292,6 +2299,9 @@ public final class ActivityThread extends ClientTransactionHandler
handleTimeoutService((IBinder) msg.obj, msg.arg1);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PING:
((RemoteCallback) msg.obj).sendResult(null);
break;
case CONFIGURATION_CHANGED:
mConfigurationController.handleConfigurationChanged((Configuration) msg.obj);
break;

View File

@@ -172,4 +172,5 @@ oneway interface IApplicationThread {
in TranslationSpec targetSpec, in List<AutofillId> viewIds,
in UiTranslationSpec uiTranslationSpec);
void scheduleTimeoutService(IBinder token, int startId);
void schedulePing(in RemoteCallback pong);
}

View File

@@ -344,6 +344,7 @@ import android.util.FeatureFlagUtils;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.Log;
import android.util.LogWriter;
import android.util.Pair;
import android.util.PrintWriterPrinter;
import android.util.Slog;
@@ -484,9 +485,11 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
@@ -18863,10 +18866,11 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void waitForBroadcastBarrier() {
waitForBroadcastBarrier(/* printWriter= */ null, false);
waitForBroadcastBarrier(/* printWriter= */ null, false, false);
}
public void waitForBroadcastBarrier(@Nullable PrintWriter pw, boolean flushBroadcastLoopers) {
public void waitForBroadcastBarrier(@Nullable PrintWriter pw,
boolean flushBroadcastLoopers, boolean flushApplicationThreads) {
enforceCallingPermission(permission.DUMP, "waitForBroadcastBarrier()");
if (flushBroadcastLoopers) {
BroadcastLoopers.waitForBarrier(pw);
@@ -18874,6 +18878,76 @@ public class ActivityManagerService extends IActivityManager.Stub
for (BroadcastQueue queue : mBroadcastQueues) {
queue.waitForBarrier(pw);
}
if (flushApplicationThreads) {
waitForApplicationBarrier(pw);
}
}
/**
* Wait for all pending {@link IApplicationThread} events to be processed in
* all currently running apps.
*/
public void waitForApplicationBarrier(@Nullable PrintWriter pw) {
if (pw == null) {
pw = new PrintWriter(new LogWriter(Log.VERBOSE, TAG));
}
final CountDownLatch finishedLatch = new CountDownLatch(1);
final AtomicInteger pingCount = new AtomicInteger(0);
final AtomicInteger pongCount = new AtomicInteger(0);
final RemoteCallback pongCallback = new RemoteCallback((result) -> {
if (pongCount.incrementAndGet() == pingCount.get()) {
finishedLatch.countDown();
}
});
// Insert an extra "ping" as a sentinel value to guard us from finishing
// too quickly in parallel below
pingCount.incrementAndGet();
synchronized (mProcLock) {
final ArrayMap<String, SparseArray<ProcessRecord>> pmap =
mProcessList.getProcessNamesLOSP().getMap();
final int numProc = pmap.size();
for (int iProc = 0; iProc < numProc; iProc++) {
final SparseArray<ProcessRecord> apps = pmap.valueAt(iProc);
for (int iApp = 0, numApps = apps.size(); iApp < numApps; iApp++) {
final ProcessRecord app = apps.valueAt(iApp);
final IApplicationThread thread = app.getOnewayThread();
if (thread != null) {
mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(app,
OomAdjuster.OOM_ADJ_REASON_NONE);
pingCount.incrementAndGet();
try {
thread.schedulePing(pongCallback);
} catch (RemoteException ignored) {
// When we failed to ping remote process, pretend as
// if we received the expected pong
pongCallback.sendResult(null);
}
}
}
}
}
// Now that we've dispatched all "ping" events above, we can send our
// "pong" sentinel value
pongCallback.sendResult(null);
// Wait for any remaining "pong" events to trickle in
for (int i = 0; i < 30; i++) {
try {
if (finishedLatch.await(1, TimeUnit.SECONDS)) {
pw.println("Finished application barriers!");
return;
} else {
pw.println("Waiting for application barriers, at " + pongCount.get() + " of "
+ pingCount.get() + "...");
}
} catch (InterruptedException ignored) {
}
}
pw.println("Gave up waiting for application barriers!");
}
void setIgnoreDeliveryGroupPolicy(@NonNull String broadcastAction) {

View File

@@ -359,6 +359,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
return runWaitForBroadcastIdle(pw);
case "wait-for-broadcast-barrier":
return runWaitForBroadcastBarrier(pw);
case "wait-for-application-barrier":
return runWaitForApplicationBarrier(pw);
case "set-ignore-delivery-group-policy":
return runSetIgnoreDeliveryGroupPolicy(pw);
case "clear-ignore-delivery-group-policy":
@@ -3364,16 +3366,24 @@ final class ActivityManagerShellCommand extends ShellCommand {
int runWaitForBroadcastBarrier(PrintWriter pw) throws RemoteException {
boolean flushBroadcastLoopers = false;
boolean flushApplicationThreads = false;
String opt;
while ((opt = getNextOption()) != null) {
if (opt.equals("--flush-broadcast-loopers")) {
flushBroadcastLoopers = true;
} else if (opt.equals("--flush-application-threads")) {
flushApplicationThreads = true;
} else {
getErrPrintWriter().println("Error: Unknown option: " + opt);
return -1;
}
}
mInternal.waitForBroadcastBarrier(pw, flushBroadcastLoopers);
mInternal.waitForBroadcastBarrier(pw, flushBroadcastLoopers, flushApplicationThreads);
return 0;
}
int runWaitForApplicationBarrier(PrintWriter pw) throws RemoteException {
mInternal.waitForApplicationBarrier(pw);
return 0;
}

View File

@@ -25,6 +25,7 @@ import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteCallback;
import android.os.RemoteException;
import java.util.List;
@@ -77,17 +78,23 @@ public class SameProcessApplicationThread extends IApplicationThread.Default {
@Override
public void scheduleReceiverList(List<ReceiverInfo> info) {
for (int i = 0; i < info.size(); i++) {
ReceiverInfo r = info.get(i);
if (r.registered) {
scheduleRegisteredReceiver(r.receiver, r.intent,
r.resultCode, r.data, r.extras, r.ordered, r.sticky, r.assumeDelivered,
r.sendingUser, r.processState, r.sendingUid, r.sendingPackage);
} else {
scheduleReceiver(r.intent, r.activityInfo, r.compatInfo,
r.resultCode, r.data, r.extras, r.sync, r.assumeDelivered,
r.sendingUser, r.processState, r.sendingUid, r.sendingPackage);
mHandler.post(() -> {
try {
mWrapped.scheduleReceiverList(info);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
});
}
@Override
public void schedulePing(RemoteCallback pong) {
mHandler.post(() -> {
try {
mWrapped.schedulePing(pong);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
});
}
}