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

Commit 690ad9de authored by Christopher Tate's avatar Christopher Tate Committed by Chris 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.

Fixed unchecked null reference situation.

Bug: 161537193
Test: atest CtsAlarmManagerTestCases
Test: atest BroadcastOptionsTest
Test: atest FrameworksMockingServicesTests:AlarmManagerServiceTest
Change-Id: I70a7be35f198bcf9a3cfa232c309a381b2391e34
parent 9974dd6e
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -335,12 +335,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
@@ -14445,6 +14445,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,
@@ -14458,6 +14471,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 (options != null && 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