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:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user