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

Commit 207cd287 authored by Hui Yu's avatar Hui Yu
Browse files

Defer LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts.

Until the first time any process in the UID is started.

This feature is enabled by device_config flag "defer_boot_completed_broadcast" which has possible value:
0 defer none.
1 defer LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts of all apps.
2 defer UID that is background restricted.
4 defer UID that has targetSdkVersion T+.
Except value -1 and 1, other values can be bit-OR-ed to combine multiple
conditions.

The default is to defer apps that are both background restricted AND targetSdkVersion T+.

Bug: 203704822
Test: atest services/tests/servicestests/src/com/android/server/am/BroadcastRecordTest#testDeferBootCompletedBroadcast and #testDeferBootCompletedBroadcast_dispatcher
Change-Id: Ia48ca3704a2f371e8bbe4d93df90652191dc2f99
parent 5479e1e0
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGRO
import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_NONE;

import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;
import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_BACKGROUND_RESTRICTED_ONLY;
import static com.android.server.am.BroadcastConstants.DEFER_BOOT_COMPLETED_BROADCAST_TARGET_T_ONLY;

import android.annotation.NonNull;
import android.app.ActivityThread;
@@ -203,6 +205,10 @@ final class ActivityManagerConstants extends ContentObserver {
    private static final boolean DEFAULT_ENABLE_COMPONENT_ALIAS = false;
    private static final String DEFAULT_COMPONENT_ALIAS_OVERRIDES = "";

    private static final int DEFAULT_DEFER_BOOT_COMPLETED_BROADCAST =
            DEFER_BOOT_COMPLETED_BROADCAST_BACKGROUND_RESTRICTED_ONLY
            | DEFER_BOOT_COMPLETED_BROADCAST_TARGET_T_ONLY;

    // Flag stored in the DeviceConfig API.
    /**
     * Maximum number of cached processes.
@@ -292,6 +298,9 @@ final class ActivityManagerConstants extends ContentObserver {
     */
    private static final String KEY_PROCESS_KILL_TIMEOUT = "process_kill_timeout";

    private static final String KEY_DEFER_BOOT_COMPLETED_BROADCAST =
            "defer_boot_completed_broadcast";

    // Maximum number of cached processes we will allow.
    public int MAX_CACHED_PROCESSES = DEFAULT_MAX_CACHED_PROCESSES;

@@ -602,6 +611,15 @@ final class ActivityManagerConstants extends ContentObserver {
     */
    volatile boolean mEnableComponentAlias = DEFAULT_ENABLE_COMPONENT_ALIAS;

    /**
     * Where or not to defer LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts until the first
     * time the process of the UID is started.
     * Defined in {@link BroadcastConstants#DeferBootCompletedBroadcastType}
     */
    @GuardedBy("mService")
    volatile @BroadcastConstants.DeferBootCompletedBroadcastType int mDeferBootCompletedBroadcast =
            DEFAULT_DEFER_BOOT_COMPLETED_BROADCAST;

    /**
     * Defines component aliases. Format
     * ComponentName ":" ComponentName ( "," ComponentName ":" ComponentName )*
@@ -846,6 +864,9 @@ final class ActivityManagerConstants extends ContentObserver {
                            case KEY_PROCESS_KILL_TIMEOUT:
                                updateProcessKillTimeout();
                                break;
                            case KEY_DEFER_BOOT_COMPLETED_BROADCAST:
                                updateDeferBootCompletedBroadcast();
                                break;
                            default:
                                break;
                        }
@@ -1258,6 +1279,13 @@ final class ActivityManagerConstants extends ContentObserver {
        }
    }

    private void updateDeferBootCompletedBroadcast() {
        mDeferBootCompletedBroadcast = DeviceConfig.getInt(
                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                KEY_DEFER_BOOT_COMPLETED_BROADCAST,
                DEFAULT_DEFER_BOOT_COMPLETED_BROADCAST);
    }

    private long[] parseLongArray(@NonNull String key, @NonNull long[] def) {
        final String val = DeviceConfig.getString(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                key, null);
@@ -1529,6 +1557,8 @@ final class ActivityManagerConstants extends ContentObserver {
        pw.print("="); pw.println(mEnableComponentAlias);
        pw.print("  "); pw.print(KEY_COMPONENT_ALIAS_OVERRIDES);
        pw.print("="); pw.println(mComponentAliasOverrides);
        pw.print("  "); pw.print(KEY_DEFER_BOOT_COMPLETED_BROADCAST);
        pw.print("="); pw.println(mDeferBootCompletedBroadcast);

        pw.println();
        if (mOverrideMaxCachedProcesses >= 0) {
+13 −1
Original line number Diff line number Diff line
@@ -4856,6 +4856,10 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        if (!badApp) {
            updateUidReadyForBootCompletedBroadcastLocked(app.uid);
        }
        // Check if a next-broadcast receiver is in this process...
        if (!badApp && isPendingBroadcastProcessLocked(pid)) {
            try {
@@ -6482,7 +6486,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        return isBackgroundRestrictedNoCheck(callingUid, packageName);
    }
    boolean isBackgroundRestrictedNoCheck(final int uid, final String packageName) {
    @VisibleForTesting
    public boolean isBackgroundRestrictedNoCheck(final int uid, final String packageName) {
        final int mode = getAppOpsManager().checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND,
                uid, packageName);
        return mode != AppOpsManager.MODE_ALLOWED;
@@ -12764,6 +12769,13 @@ public class ActivityManagerService extends IActivityManager.Stub
        return didSomething;
    }
    void updateUidReadyForBootCompletedBroadcastLocked(int uid) {
        for (BroadcastQueue queue : mBroadcastQueues) {
            queue.updateUidReadyForBootCompletedBroadcastLocked(uid);
            queue.scheduleBroadcastsLocked();
        }
    }
    /**
     * @deprecated Use {@link #registerReceiverWithFeature}
     */
+47 −0
Original line number Diff line number Diff line
@@ -16,6 +16,10 @@

package com.android.server.am;

import android.annotation.IntDef;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.Overridable;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.os.Build;
@@ -26,6 +30,8 @@ import android.util.Slog;
import android.util.TimeUtils;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Tunable parameters for broadcast dispatch policy
@@ -51,6 +57,47 @@ public class BroadcastConstants {
    private static final long DEFAULT_ALLOW_BG_ACTIVITY_START_TIMEOUT =
            10_000 * Build.HW_TIMEOUT_MULTIPLIER;

    /**
     * Defer LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts until the first time any process in
     * the UID is started.
     */
    @ChangeId
    @EnabledAfter(targetSdkVersion = android.os.Build.VERSION_CODES.S_V2)
    @Overridable
    static final long DEFER_BOOT_COMPLETED_BROADCAST_CHANGE_ID = 203704822L;

    /**
     * Do not defer LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts.
     */
    public static final int DEFER_BOOT_COMPLETED_BROADCAST_NONE = 0;
    /**
     * Defer all LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts.
     */
    public static final int DEFER_BOOT_COMPLETED_BROADCAST_ALL = 1 << 0;
    /**
     * Defer LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts if app is background restricted.
     */
    public static final int DEFER_BOOT_COMPLETED_BROADCAST_BACKGROUND_RESTRICTED_ONLY = 1 << 1;
    /**
     * Defer LOCKED_BOOT_COMPLETED and BOOT_COMPLETED broadcasts if app's targetSdkVersion is T
     * and above.
     */
    public static final int DEFER_BOOT_COMPLETED_BROADCAST_TARGET_T_ONLY = 1 << 2;

    /**
     * The list of DEFER_BOOT_COMPLETED_BROADCAST types.
     * If multiple flags are selected, all conditions must be met to defer the broadcast.
     * @hide
     */
    @IntDef(flag = true, prefix = { "DEFER_BOOT_COMPLETED_BROADCAST_" }, value = {
            DEFER_BOOT_COMPLETED_BROADCAST_NONE,
            DEFER_BOOT_COMPLETED_BROADCAST_ALL,
            DEFER_BOOT_COMPLETED_BROADCAST_BACKGROUND_RESTRICTED_ONLY,
            DEFER_BOOT_COMPLETED_BROADCAST_TARGET_T_ONLY,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface DeferBootCompletedBroadcastType {}

    // All time constants are in milliseconds

    // Timeout period for this broadcast queue
+372 −4

File changed.

Preview size limit exceeded, changes collapsed.

+11 −2
Original line number Diff line number Diff line
@@ -249,11 +249,13 @@ public final class BroadcastQueue {
    }

    public void enqueueParallelBroadcastLocked(BroadcastRecord r) {
        r.enqueueClockTime = System.currentTimeMillis();
        mParallelBroadcasts.add(r);
        enqueueBroadcastHelper(r);
    }

    public void enqueueOrderedBroadcastLocked(BroadcastRecord r) {
        r.enqueueClockTime = System.currentTimeMillis();
        mDispatcher.enqueueOrderedBroadcastLocked(r);
        enqueueBroadcastHelper(r);
    }
@@ -263,8 +265,6 @@ public final class BroadcastQueue {
     * enqueueOrderedBroadcastLocked.
     */
    private void enqueueBroadcastHelper(BroadcastRecord r) {
        r.enqueueClockTime = System.currentTimeMillis();

        if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
            Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                createBroadcastTraceTitle(r, BroadcastRecord.DELIVERY_PENDING),
@@ -368,6 +368,15 @@ public final class BroadcastQueue {
        }
    }

    /**
     * Called by ActivityManagerService to notify that the uid has process started, if there is any
     * deferred BOOT_COMPLETED broadcast, the BroadcastDispatcher can dispatch the broadcast now.
     * @param uid
     */
    public void updateUidReadyForBootCompletedBroadcastLocked(int uid) {
        mDispatcher.updateUidReadyForBootCompletedBroadcastLocked(uid);
    }

    public boolean sendPendingBroadcastsLocked(ProcessRecord app) {
        boolean didSomething = false;
        final BroadcastRecord br = mPendingBroadcast;
Loading