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

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

Merge changes from topic "oct26"

* changes:
  Enable "modern" BroadcastQueue by default; take two.
  BroadcastQueue: make "oneway" calls non-blocking.
  BroadcastQueue: only OOM adjust for manifest.
parents e861d161 719d3aaa
Loading
Loading
Loading
Loading
+44 −20
Original line number Diff line number Diff line
@@ -85,9 +85,16 @@ class BroadcastProcessQueue {
    @Nullable ProcessRecord app;

    /**
     * Track name to use for {@link Trace} events.
     * Track name to use for {@link Trace} events, defined as part of upgrading
     * into a running slot.
     */
    @Nullable String traceTrackName;
    @Nullable String runningTraceTrackName;

    /**
     * Flag indicating if this process should be OOM adjusted, defined as part
     * of upgrading into a running slot.
     */
    boolean runningOomAdjusted;

    /**
     * Snapshotted value of {@link ProcessRecord#getCpuDelayTime()}, typically
@@ -141,7 +148,8 @@ class BroadcastProcessQueue {
    private boolean mActiveViaColdStart;

    /**
     * Count of {@link #mPending} broadcasts of these various flavors.
     * Count of {@link #mPending} and {@link #mPendingUrgent} broadcasts of
     * these various flavors.
     */
    private int mCountForeground;
    private int mCountOrdered;
@@ -150,6 +158,7 @@ class BroadcastProcessQueue {
    private int mCountInteractive;
    private int mCountResultTo;
    private int mCountInstrumented;
    private int mCountManifest;

    private @UptimeMillisLong long mRunnableAt = Long.MAX_VALUE;
    private @Reason int mRunnableAtReason = REASON_EMPTY;
@@ -206,7 +215,7 @@ class BroadcastProcessQueue {
        // with implicit responsiveness expectations.
        final ArrayDeque<SomeArgs> queue = record.isUrgent() ? mPendingUrgent : mPending;
        queue.addLast(newBroadcastArgs);
        onBroadcastEnqueued(record);
        onBroadcastEnqueued(record, recordIndex);
    }

    /**
@@ -224,7 +233,8 @@ class BroadcastProcessQueue {
        while (it.hasNext()) {
            final SomeArgs args = it.next();
            final BroadcastRecord testRecord = (BroadcastRecord) args.arg1;
            final Object testReceiver = testRecord.receivers.get(args.argi1);
            final int testRecordIndex = args.argi1;
            final Object testReceiver = testRecord.receivers.get(testRecordIndex);
            if ((record.callingUid == testRecord.callingUid)
                    && (record.userId == testRecord.userId)
                    && record.intent.filterEquals(testRecord.intent)
@@ -233,8 +243,8 @@ class BroadcastProcessQueue {
                args.arg1 = record;
                args.argi1 = recordIndex;
                args.argi2 = blockedUntilTerminalCount;
                onBroadcastDequeued(testRecord);
                onBroadcastEnqueued(record);
                onBroadcastDequeued(testRecord, testRecordIndex);
                onBroadcastEnqueued(record, recordIndex);
                return true;
            }
        }
@@ -284,13 +294,13 @@ class BroadcastProcessQueue {
        while (it.hasNext()) {
            final SomeArgs args = it.next();
            final BroadcastRecord record = (BroadcastRecord) args.arg1;
            final int index = args.argi1;
            if (predicate.test(record, index)) {
                consumer.accept(record, index);
            final int recordIndex = args.argi1;
            if (predicate.test(record, recordIndex)) {
                consumer.accept(record, recordIndex);
                if (andRemove) {
                    args.recycle();
                    it.remove();
                    onBroadcastDequeued(record);
                    onBroadcastDequeued(record, recordIndex);
                }
                didSomething = true;
            }
@@ -339,7 +349,7 @@ class BroadcastProcessQueue {
     * Return if we know of an actively running "warm" process for this queue.
     */
    public boolean isProcessWarm() {
        return (app != null) && (app.getThread() != null) && !app.isKilled();
        return (app != null) && (app.getOnewayThread() != null) && !app.isKilled();
    }

    public int getPreferredSchedulingGroupLocked() {
@@ -385,7 +395,7 @@ class BroadcastProcessQueue {
        mActiveCountSinceIdle++;
        mActiveViaColdStart = false;
        next.recycle();
        onBroadcastDequeued(mActive);
        onBroadcastDequeued(mActive, mActiveIndex);
    }

    /**
@@ -403,7 +413,7 @@ class BroadcastProcessQueue {
    /**
     * Update summary statistics when the given record has been enqueued.
     */
    private void onBroadcastEnqueued(@NonNull BroadcastRecord record) {
    private void onBroadcastEnqueued(@NonNull BroadcastRecord record, int recordIndex) {
        if (record.isForeground()) {
            mCountForeground++;
        }
@@ -425,13 +435,16 @@ class BroadcastProcessQueue {
        if (record.callerInstrumented) {
            mCountInstrumented++;
        }
        if (record.receivers.get(recordIndex) instanceof ResolveInfo) {
            mCountManifest++;
        }
        invalidateRunnableAt();
    }

    /**
     * Update summary statistics when the given record has been dequeued.
     */
    private void onBroadcastDequeued(@NonNull BroadcastRecord record) {
    private void onBroadcastDequeued(@NonNull BroadcastRecord record, int recordIndex) {
        if (record.isForeground()) {
            mCountForeground--;
        }
@@ -453,34 +466,37 @@ class BroadcastProcessQueue {
        if (record.callerInstrumented) {
            mCountInstrumented--;
        }
        if (record.receivers.get(recordIndex) instanceof ResolveInfo) {
            mCountManifest--;
        }
        invalidateRunnableAt();
    }

    public void traceProcessStartingBegin() {
        Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                traceTrackName, toShortString() + " starting", hashCode());
                runningTraceTrackName, toShortString() + " starting", hashCode());
    }

    public void traceProcessRunningBegin() {
        Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                traceTrackName, toShortString() + " running", hashCode());
                runningTraceTrackName, toShortString() + " running", hashCode());
    }

    public void traceProcessEnd() {
        Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                traceTrackName, hashCode());
                runningTraceTrackName, hashCode());
    }

    public void traceActiveBegin() {
        final int cookie = mActive.receivers.get(mActiveIndex).hashCode();
        Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                traceTrackName, mActive.toShortString() + " scheduled", cookie);
                runningTraceTrackName, mActive.toShortString() + " scheduled", cookie);
    }

    public void traceActiveEnd() {
        final int cookie = mActive.receivers.get(mActiveIndex).hashCode();
        Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                traceTrackName, cookie);
                runningTraceTrackName, cookie);
    }

    /**
@@ -539,6 +555,14 @@ class BroadcastProcessQueue {
        return (queue != null) ? (BroadcastRecord) queue.peekFirst().arg1 : null;
    }

    /**
     * Quickly determine if this queue has broadcasts waiting to be delivered to
     * manifest receivers, which indicates we should request an OOM adjust.
     */
    public boolean isPendingManifest() {
        return mCountManifest > 0;
    }

    /**
     * Quickly determine if this queue has broadcasts that are still waiting to
     * be delivered at some point in the future.
+14 −12
Original line number Diff line number Diff line
@@ -401,7 +401,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
            mRunnableHead = removeFromRunnableList(mRunnableHead, queue);

            // Emit all trace events for this process into a consistent track
            queue.traceTrackName = TAG + ".mRunning[" + queueIndex + "]";
            queue.runningTraceTrackName = TAG + ".mRunning[" + queueIndex + "]";
            queue.runningOomAdjusted = queue.isPendingManifest();

            // If we're already warm, schedule next pending broadcast now;
            // otherwise we'll wait for the cold start to circle back around
@@ -415,9 +416,8 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
                scheduleReceiverColdLocked(queue);
            }

            // We've moved at least one process into running state above, so we
            // need to kick off an OOM adjustment pass
            updateOomAdj = true;
            // Only kick off an OOM adjustment pass if needed
            updateOomAdj |= queue.runningOomAdjusted;

            // Move to considering next runnable queue
            queue = nextQueue;
@@ -736,7 +736,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        if (DEBUG_BROADCAST) logv("Scheduling " + r + " to warm " + app);
        setDeliveryState(queue, app, r, index, receiver, BroadcastRecord.DELIVERY_SCHEDULED);

        final IApplicationThread thread = app.getThread();
        final IApplicationThread thread = app.getOnewayThread();
        if (thread != null) {
            try {
                if (receiver instanceof BroadcastFilter) {
@@ -777,7 +777,7 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
    private void scheduleResultTo(@NonNull BroadcastRecord r) {
        if ((r.resultToApp == null) || (r.resultTo == null)) return;
        final ProcessRecord app = r.resultToApp;
        final IApplicationThread thread = app.getThread();
        final IApplicationThread thread = app.getOnewayThread();
        if (thread != null) {
            mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(
                    app, OOM_ADJ_REASON_FINISH_RECEIVER);
@@ -1245,8 +1245,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
        if (queue.app != null) {
            queue.app.mReceivers.incrementCurReceivers();

            queue.app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);

            // Don't bump its LRU position if it's in the background restricted.
            if (mService.mInternal.getRestrictionLevel(
                    queue.uid) < ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
@@ -1256,9 +1254,12 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
            mService.mOomAdjuster.mCachedAppOptimizer.unfreezeTemporarily(queue.app,
                    OOM_ADJ_REASON_START_RECEIVER);

            if (queue.runningOomAdjusted) {
                queue.app.mState.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
                mService.enqueueOomAdjTargetLocked(queue.app);
            }
        }
    }

    /**
     * Inform other parts of OS that the given broadcast queue has stopped
@@ -1266,10 +1267,11 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
     */
    private void notifyStoppedRunning(@NonNull BroadcastProcessQueue queue) {
        if (queue.app != null) {
            // Update during our next pass; no need for an immediate update
            mService.enqueueOomAdjTargetLocked(queue.app);

            queue.app.mReceivers.decrementCurReceivers();

            if (queue.runningOomAdjusted) {
                mService.enqueueOomAdjTargetLocked(queue.app);
            }
        }
    }

+19 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.Zygote;
import com.android.server.FgThread;
import com.android.server.wm.WindowProcessController;
import com.android.server.wm.WindowProcessListener;

@@ -142,6 +143,13 @@ class ProcessRecord implements WindowProcessListener {
    @CompositeRWLock({"mService", "mProcLock"})
    private IApplicationThread mThread;

    /**
     * Instance of {@link #mThread} that will always meet the {@code oneway}
     * contract, possibly by using {@link SameProcessApplicationThread}.
     */
    @CompositeRWLock({"mService", "mProcLock"})
    private IApplicationThread mOnewayThread;

    /**
     * Always keep this application running?
     */
@@ -603,16 +611,27 @@ class ProcessRecord implements WindowProcessListener {
        return mThread;
    }

    @GuardedBy(anyOf = {"mService", "mProcLock"})
    IApplicationThread getOnewayThread() {
        return mOnewayThread;
    }

    @GuardedBy({"mService", "mProcLock"})
    public void makeActive(IApplicationThread thread, ProcessStatsService tracker) {
        mProfile.onProcessActive(thread, tracker);
        mThread = thread;
        if (mPid == Process.myPid()) {
            mOnewayThread = new SameProcessApplicationThread(thread, FgThread.getHandler());
        } else {
            mOnewayThread = thread;
        }
        mWindowProcessController.setThread(thread);
    }

    @GuardedBy({"mService", "mProcLock"})
    public void makeInactive(ProcessStatsService tracker) {
        mThread = null;
        mOnewayThread = null;
        mWindowProcessController.setThread(null);
        mProfile.onProcessInactive(tracker);
    }
+73 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.am;

import android.annotation.NonNull;
import android.app.IApplicationThread;
import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;

import java.util.Objects;

/**
 * Wrapper around an {@link IApplicationThread} that delegates selected calls
 * through a {@link Handler} so they meet the {@code oneway} contract of
 * returning immediately after dispatch.
 */
public class SameProcessApplicationThread extends IApplicationThread.Default {
    private final IApplicationThread mWrapped;
    private final Handler mHandler;

    public SameProcessApplicationThread(@NonNull IApplicationThread wrapped,
            @NonNull Handler handler) {
        mWrapped = Objects.requireNonNull(wrapped);
        mHandler = Objects.requireNonNull(handler);
    }

    @Override
    public void scheduleReceiver(Intent intent, ActivityInfo info, CompatibilityInfo compatInfo,
            int resultCode, String data, Bundle extras, boolean sync, int sendingUser,
            int processState) {
        mHandler.post(() -> {
            try {
                mWrapped.scheduleReceiver(intent, info, compatInfo, resultCode, data, extras, sync,
                        sendingUser, processState);
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
        });
    }

    @Override
    public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent, int resultCode,
            String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser,
            int processState) {
        mHandler.post(() -> {
            try {
                mWrapped.scheduleRegisteredReceiver(receiver, intent, resultCode, data, extras,
                        ordered, sticky, sendingUser, processState);
            } catch (RemoteException e) {
                throw new RuntimeException(e);
            }
        });
    }
}
+4 −0
Original line number Diff line number Diff line
@@ -87,6 +87,10 @@ public class BroadcastQueueModernImplTest {
        mHandlerThread.start();

        mConstants = new BroadcastConstants(Settings.Global.BROADCAST_FG_CONSTANTS);
        mConstants.DELAY_URGENT_MILLIS = -120_000;
        mConstants.DELAY_NORMAL_MILLIS = 10_000;
        mConstants.DELAY_CACHED_MILLIS = 120_000;

        mImpl = new BroadcastQueueModernImpl(mAms, mHandlerThread.getThreadHandler(),
                mConstants, mConstants);

Loading