Loading core/java/android/app/ActivityThread.java +10 −0 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading core/java/android/app/IApplicationThread.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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); } services/core/java/com/android/server/am/ActivityManagerService.java +76 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -18865,10 +18868,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); Loading @@ -18876,6 +18880,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) { services/core/java/com/android/server/am/ActivityManagerShellCommand.java +11 −1 Original line number Diff line number Diff line Loading @@ -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": Loading Loading @@ -3332,16 +3334,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; } Loading services/core/java/com/android/server/am/SameProcessApplicationThread.java +18 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } }); } } Loading
core/java/android/app/ActivityThread.java +10 −0 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading
core/java/android/app/IApplicationThread.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -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); }
services/core/java/com/android/server/am/ActivityManagerService.java +76 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -18865,10 +18868,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); Loading @@ -18876,6 +18880,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) {
services/core/java/com/android/server/am/ActivityManagerShellCommand.java +11 −1 Original line number Diff line number Diff line Loading @@ -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": Loading Loading @@ -3332,16 +3334,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; } Loading
services/core/java/com/android/server/am/SameProcessApplicationThread.java +18 −11 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } }); } }