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

Commit facccc24 authored by Christopher Tate's avatar Christopher Tate
Browse files

BroadcastOption for "this is an alarm broadcast"

Instead of a callback/observer mechanism between the alarm subsystem and
the broadcast delivery subsystem, there will be a direct
BroadcastOptions tag that the Alarm Manager uses to annotate broadcasts
that originate from an alarm firing.  Only the OS itself can use this
BroadcastOptions annotation.

Bug: 161537193
Test: atest CtsAlarmManagerTestCases
Test: atest BroadcastOptionsTest
Test: atest FrameworksMockingServicesTests:AlarmManagerServiceTest
Change-Id: Ie45fd67f9dd55931a3dc109dc198c118b2a55bce
parent a71e4bf9
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -334,12 +334,18 @@ public class AlarmManagerService extends SystemService {
            "REORDER_ALARMS_FOR_TARE",
    });

    BroadcastOptions mOptsWithFgs = BroadcastOptions.makeBasic();
    BroadcastOptions mOptsWithFgsForAlarmClock = BroadcastOptions.makeBasic();
    BroadcastOptions mOptsWithoutFgs = BroadcastOptions.makeBasic();
    BroadcastOptions mOptsTimeBroadcast = BroadcastOptions.makeBasic();
    BroadcastOptions mOptsWithFgs = makeBasicAlarmBroadcastOptions();
    BroadcastOptions mOptsWithFgsForAlarmClock = makeBasicAlarmBroadcastOptions();
    BroadcastOptions mOptsWithoutFgs = makeBasicAlarmBroadcastOptions();
    BroadcastOptions mOptsTimeBroadcast = makeBasicAlarmBroadcastOptions();
    ActivityOptions mActivityOptsRestrictBal = ActivityOptions.makeBasic();
    BroadcastOptions mBroadcastOptsRestrictBal = BroadcastOptions.makeBasic();
    BroadcastOptions mBroadcastOptsRestrictBal = makeBasicAlarmBroadcastOptions();

    private static BroadcastOptions makeBasicAlarmBroadcastOptions() {
        final BroadcastOptions b = BroadcastOptions.makeBasic();
        b.setAlarmBroadcast(true);
        return b;
    }

    // TODO(b/172085676): Move inside alarm store.
    private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
+33 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ public class BroadcastOptions extends ComponentOptions {
    private String[] mRequireNoneOfPermissions;
    private long mRequireCompatChangeId = CHANGE_INVALID;
    private boolean mRequireCompatChangeEnabled = true;
    private boolean mIsAlarmBroadcast = false;
    private long mIdForResponseEvent;

    /**
@@ -148,6 +149,13 @@ public class BroadcastOptions extends ComponentOptions {
    private static final String KEY_REQUIRE_COMPAT_CHANGE_ENABLED =
            "android:broadcast.requireCompatChangeEnabled";

    /**
     * Corresponds to {@link #setAlarmBroadcast(boolean)}
     * @hide
     */
    public static final String KEY_ALARM_BROADCAST =
            "android:broadcast.is_alarm";

    /**
     * @hide
     * @deprecated Use {@link android.os.PowerExemptionManager#
@@ -207,6 +215,7 @@ public class BroadcastOptions extends ComponentOptions {
        mRequireCompatChangeId = opts.getLong(KEY_REQUIRE_COMPAT_CHANGE_ID, CHANGE_INVALID);
        mRequireCompatChangeEnabled = opts.getBoolean(KEY_REQUIRE_COMPAT_CHANGE_ENABLED, true);
        mIdForResponseEvent = opts.getLong(KEY_ID_FOR_RESPONSE_EVENT);
        mIsAlarmBroadcast = opts.getBoolean(KEY_ALARM_BROADCAST, false);
    }

    /**
@@ -498,6 +507,27 @@ public class BroadcastOptions extends ComponentOptions {
        mRequireCompatChangeEnabled = true;
    }

    /**
     * When set, this broadcast will be understood as having originated from an
     * alarm going off.  Only the OS itself can use this option; uses by other
     * senders will be ignored.
     * @hide
     *
     * @param senderIsAlarm Whether the broadcast is alarm-triggered.
     */
    public void setAlarmBroadcast(boolean senderIsAlarm) {
        mIsAlarmBroadcast = senderIsAlarm;
    }

    /**
     * Did this broadcast originate from an alarm triggering?
     * @return true if this broadcast is an alarm message, false otherwise
     * @hide
     */
    public boolean isAlarmBroadcast() {
        return mIsAlarmBroadcast;
    }

    /** {@hide} */
    public long getRequireCompatChangeId() {
        return mRequireCompatChangeId;
@@ -560,6 +590,9 @@ public class BroadcastOptions extends ComponentOptions {
            b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_REASON_CODE, mTemporaryAppAllowlistReasonCode);
            b.putString(KEY_TEMPORARY_APP_ALLOWLIST_REASON, mTemporaryAppAllowlistReason);
        }
        if (mIsAlarmBroadcast) {
            b.putBoolean(KEY_ALARM_BROADCAST, true);
        }
        if (mMinManifestReceiverApiLevel != 0) {
            b.putInt(KEY_MIN_MANIFEST_RECEIVER_API_LEVEL, mMinManifestReceiverApiLevel);
        }
+14 −0
Original line number Diff line number Diff line
@@ -14439,6 +14439,19 @@ public class ActivityManagerService extends IActivityManager.Stub
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            // Non-system callers can't declare that a broadcast is alarm-related.
            // The PendingIntent invocation case is handled in PendingIntentRecord.
            if (bOptions != null && callingUid != SYSTEM_UID) {
                if (bOptions.containsKey(BroadcastOptions.KEY_ALARM_BROADCAST)) {
                    if (DEBUG_BROADCAST) {
                        Slog.w(TAG, "Non-system caller " + callingUid
                                + " may not flag broadcast as alarm-related");
                    }
                    throw new SecurityException(
                            "Non-system callers may not flag broadcasts as alarm-related");
                }
            }
            final long origId = Binder.clearCallingIdentity();
            try {
                return broadcastIntentLocked(callerApp,
@@ -14452,6 +14465,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    // Not the binder call surface
    int broadcastIntentInPackage(String packageName, @Nullable String featureId, int uid,
            int realCallingUid, int realCallingPid, Intent intent, String resolvedType,
            IIntentReceiver resultTo, int resultCode, String resultData, Bundle resultExtras,
+3 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ final class BroadcastRecord extends Binder {
    final boolean callerInstantApp; // caller is an Instant App?
    final boolean ordered;  // serialize the send to receivers?
    final boolean sticky;   // originated from existing sticky data?
    final boolean alarm;    // originated from an alarm triggering?
    final boolean initialSticky; // initial broadcast from register to sticky?
    final int userId;       // user id this broadcast was for
    final String resolvedType; // the resolved data type
@@ -305,6 +306,7 @@ final class BroadcastRecord extends Binder {
        this.allowBackgroundActivityStarts = allowBackgroundActivityStarts;
        mBackgroundActivityStartsToken = backgroundActivityStartsToken;
        this.timeoutExempt = timeoutExempt;
        alarm = options != null && options.isAlarmBroadcast();
    }

    /**
@@ -357,6 +359,7 @@ final class BroadcastRecord extends Binder {
        allowBackgroundActivityStarts = from.allowBackgroundActivityStarts;
        mBackgroundActivityStartsToken = from.mBackgroundActivityStartsToken;
        timeoutExempt = from.timeoutExempt;
        alarm = from.alarm;
    }

    /**
+18 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.am;

import static android.app.ActivityManager.START_SUCCESS;

import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_LIGHT;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;

@@ -34,6 +35,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerWhitelistManager;
import android.os.PowerWhitelistManager.ReasonCode;
import android.os.Process;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
@@ -416,6 +418,22 @@ public final class PendingIntentRecord extends IIntentSender.Stub {

        final int callingUid = Binder.getCallingUid();
        final int callingPid = Binder.getCallingPid();

        // Only system senders can declare a broadcast to be alarm-originated.  We check
        // this here rather than in the general case handling below to fail before the other
        // invocation side effects such as allowlisting.
        if (callingUid != Process.SYSTEM_UID
                && key.type == ActivityManager.INTENT_SENDER_BROADCAST) {
            if (options.containsKey(BroadcastOptions.KEY_ALARM_BROADCAST)) {
                if (DEBUG_BROADCAST_LIGHT) {
                    Slog.w(TAG, "Non-system caller " + callingUid
                            + " may not flag broadcast as alarm-related");
                }
                throw new SecurityException(
                        "Non-system callers may not flag broadcasts as alarm-related");
            }
        }

        final long origId = Binder.clearCallingIdentity();

        int res = START_SUCCESS;
Loading