Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65391c6b authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android (Google) Code Review
Browse files

Merge "Wait for IApplicationThread events via ping/pong." into udc-dev

parents bb98b14b 82a6a495
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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);
}
+76 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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);
@@ -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) {
+11 −1
Original line number Diff line number Diff line
@@ -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":
@@ -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;
    }

+18 −11
Original line number Diff line number Diff line
@@ -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);
            }
        });
    }
}