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

Commit d8ad2e53 authored by Tim Murray's avatar Tim Murray Committed by Android (Google) Code Review
Browse files

Merge "Add infinitely deferred broadcasts."

parents 9fb29304 3bb8afe6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -806,10 +806,12 @@ package android.app {
    method @Nullable public android.content.IntentFilter getDeliveryGroupMatchingFilter();
    method @Nullable public String getDeliveryGroupMatchingKey();
    method public int getDeliveryGroupPolicy();
    method public boolean isDeferUntilActive();
    method public boolean isPendingIntentBackgroundActivityLaunchAllowed();
    method public static android.app.BroadcastOptions makeBasic();
    method @RequiresPermission(android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS) public void recordResponseEventWhileInBackground(@IntRange(from=0) long);
    method @RequiresPermission(android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND) public void setBackgroundActivityStartsAllowed(boolean);
    method @NonNull public android.app.BroadcastOptions setDeferUntilActive(boolean);
    method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingFilter(@NonNull android.content.IntentFilter);
    method @NonNull public android.app.BroadcastOptions setDeliveryGroupMatchingKey(@NonNull String, @NonNull String);
    method @NonNull public android.app.BroadcastOptions setDeliveryGroupPolicy(int);
+46 −0
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ public class BroadcastOptions extends ComponentOptions {
    private long mRequireCompatChangeId = CHANGE_INVALID;
    private boolean mRequireCompatChangeEnabled = true;
    private boolean mIsAlarmBroadcast = false;
    private boolean mIsDeferUntilActive = false;
    private long mIdForResponseEvent;
    private @Nullable IntentFilter mRemoveMatchingFilter;
    private @DeliveryGroupPolicy int mDeliveryGroupPolicy;
@@ -200,6 +201,12 @@ public class BroadcastOptions extends ComponentOptions {
    private static final String KEY_REMOVE_MATCHING_FILTER =
            "android:broadcast.removeMatchingFilter";

    /**
     * Corresponds to {@link #setDeferUntilActive(boolean)}.
     */
    private static final String KEY_DEFER_UNTIL_ACTIVE =
            "android:broadcast.deferuntilactive";

    /**
     * Corresponds to {@link #setDeliveryGroupPolicy(int)}.
     */
@@ -320,6 +327,7 @@ public class BroadcastOptions extends ComponentOptions {
                BundleMerger.class);
        mDeliveryGroupMatchingFilter = opts.getParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER,
                IntentFilter.class);
        mIsDeferUntilActive = opts.getBoolean(KEY_DEFER_UNTIL_ACTIVE, false);
    }

    /**
@@ -699,6 +707,41 @@ public class BroadcastOptions extends ComponentOptions {
        return mIdForResponseEvent;
    }

    /**
     * Sets whether the broadcast should not run until the process is in an active process state
     * (ie, a process exists for the app and the app is not in a cached process state).
     *
     * Whether an app's process state is considered active is independent of its standby bucket.
     *
     * A broadcast that is deferred until the process is active will not execute until the process
     * is brought to an active state by some other action, like a job, alarm, or service binding. As
     * a result, the broadcast may be delayed indefinitely. This deferral only applies to runtime
     * registered receivers of a broadcast. Any manifest receivers will run immediately, similar to
     * how a manifest receiver would start a new process in order to run a broadcast receiver.
     *
     * Ordered broadcasts, alarm broadcasts, interactive broadcasts, and manifest broadcasts are
     * never deferred.
     *
     * Unordered broadcasts and unordered broadcasts with completion callbacks may be
     * deferred. Completion callbacks for broadcasts deferred until active are
     * best-effort. Completion callbacks will run when all eligible processes have finished
     * executing the broadcast. Processes in inactive process states that defer the broadcast are
     * not considered eligible and may not execute the broadcast prior to the completion callback.
     *
     * @hide
     */
    @SystemApi
    public @NonNull BroadcastOptions setDeferUntilActive(boolean shouldDefer) {
        mIsDeferUntilActive = shouldDefer;
        return this;
    }

    /** @hide */
    @SystemApi
    public boolean isDeferUntilActive() {
        return mIsDeferUntilActive;
    }

    /**
     * When enqueuing this broadcast, remove all pending broadcasts previously
     * sent by this app which match the given filter.
@@ -963,6 +1006,9 @@ public class BroadcastOptions extends ComponentOptions {
        if (mDeliveryGroupMatchingFilter != null) {
            b.putParcelable(KEY_DELIVERY_GROUP_MATCHING_FILTER, mDeliveryGroupMatchingFilter);
        }
        if (mIsDeferUntilActive) {
            b.putBoolean(KEY_DEFER_UNTIL_ACTIVE, mIsDeferUntilActive);
        }
        return b.isEmpty() ? null : b;
    }
}
+11 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.ActivityTaskManager;
import android.app.AlarmManager;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.app.WindowConfiguration;
@@ -391,6 +392,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
                    | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                    | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);

    private static final Bundle USER_PRESENT_INTENT_OPTIONS =
            BroadcastOptions.makeBasic()
                    .setDeferUntilActive(true)
                    .setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT)
                    .toBundle();

    /**
     * {@link #setKeyguardEnabled} waits on this condition when it re-enables
     * the keyguard.
@@ -2319,7 +2326,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
                        Context.USER_SERVICE);
                mUiBgExecutor.execute(() -> {
                    for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
                        mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
                        mContext.sendBroadcastAsUser(USER_PRESENT_INTENT,
                                UserHandle.of(profileId),
                                null,
                                USER_PRESENT_INTENT_OPTIONS);
                    }
                    mLockPatternUtils.userPresent(currentUserId);
                });
+10 −5
Original line number Diff line number Diff line
@@ -189,15 +189,20 @@ public final class BatteryService extends SystemService {
    private long mLastBatteryLevelChangedSentMs;

    private Bundle mBatteryChangedOptions = BroadcastOptions.makeRemovingMatchingFilter(
            new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).toBundle();
            new IntentFilter(Intent.ACTION_BATTERY_CHANGED)).setDeferUntilActive(true)
            .toBundle();
    private Bundle mPowerConnectedOptions = BroadcastOptions.makeRemovingMatchingFilter(
            new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).toBundle();
            new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)).setDeferUntilActive(true)
            .toBundle();
    private Bundle mPowerDisconnectedOptions = BroadcastOptions.makeRemovingMatchingFilter(
            new IntentFilter(Intent.ACTION_POWER_CONNECTED)).toBundle();
            new IntentFilter(Intent.ACTION_POWER_CONNECTED)).setDeferUntilActive(true)
            .toBundle();
    private Bundle mBatteryLowOptions = BroadcastOptions.makeRemovingMatchingFilter(
            new IntentFilter(Intent.ACTION_BATTERY_OKAY)).toBundle();
            new IntentFilter(Intent.ACTION_BATTERY_OKAY)).setDeferUntilActive(true)
            .toBundle();
    private Bundle mBatteryOkayOptions = BroadcastOptions.makeRemovingMatchingFilter(
            new IntentFilter(Intent.ACTION_BATTERY_LOW)).toBundle();
            new IntentFilter(Intent.ACTION_BATTERY_LOW)).setDeferUntilActive(true)
            .toBundle();

    private MetricsLogger mMetricsLogger;

+22 −2
Original line number Diff line number Diff line
@@ -14108,9 +14108,17 @@ public class ActivityManagerService extends IActivityManager.Stub
        if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST,
                (sticky ? "Broadcast sticky: ": "Broadcast: ") + intent
                + " ordered=" + ordered + " userid=" + userId);
        if ((resultTo != null) && !ordered && !mEnableModernQueue) {
        if ((resultTo != null) && !ordered) {
            if (!mEnableModernQueue) {
                Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
            }
            if (!UserHandle.isCore(callingUid)) {
                String msg = "Unauthorized unordered resultTo broadcast "
                             + intent + " sent from uid " + callingUid;
                Slog.w(TAG, msg);
                throw new SecurityException(msg);
            }
        }
        userId = mUserController.handleIncomingUser(callingPid, callingUid, userId, true,
                ALLOW_NON_FULL, "broadcast", callerPackage);
@@ -14190,6 +14198,18 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        // resultTo broadcasts are always infinitely deferrable.
        if ((resultTo != null) && !ordered && mEnableModernQueue) {
            if (brOptions == null) {
                brOptions = BroadcastOptions.makeBasic();
            }
            brOptions.setDeferUntilActive(true);
        }
        if (ordered && brOptions != null && brOptions.isDeferUntilActive()) {
            throw new IllegalArgumentException("Ordered broadcasts can't be deferred until active");
        }
        // Verify that protected broadcasts are only being sent by system code,
        // and that system code is only sending protected broadcasts.
        final boolean isProtectedBroadcast;
Loading