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

Commit f4cedb27 authored by Ricky Wai's avatar Ricky Wai
Browse files

Add PendingIntent BroadcastOptions BAL API implementation

Now PendingIntent sender can use API to allow/block trampoline activity started
by broadcast created by PendingIntent creator.

Bug: 192341120
Test: atest BackgroundActivityLaunchTest
Change-Id: I4952e05f5d086483c5b3d3e1c16eb7a69e7141d0
parent 97064796
Loading
Loading
Loading
Loading
+16 −16
Original line number Original line Diff line number Diff line
@@ -326,6 +326,7 @@ public class AlarmManagerService extends SystemService {
    BroadcastOptions mOptsWithoutFgs = BroadcastOptions.makeBasic();
    BroadcastOptions mOptsWithoutFgs = BroadcastOptions.makeBasic();
    BroadcastOptions mOptsTimeBroadcast = BroadcastOptions.makeBasic();
    BroadcastOptions mOptsTimeBroadcast = BroadcastOptions.makeBasic();
    ActivityOptions mActivityOptsRestrictBal = ActivityOptions.makeBasic();
    ActivityOptions mActivityOptsRestrictBal = ActivityOptions.makeBasic();
    BroadcastOptions mBroadcastOptsRestrictBal = BroadcastOptions.makeBasic();


    // TODO(b/172085676): Move inside alarm store.
    // TODO(b/172085676): Move inside alarm store.
    private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
    private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
@@ -1700,6 +1701,7 @@ public class AlarmManagerService extends SystemService {
        mOptsWithoutFgs.setPendingIntentBackgroundActivityLaunchAllowed(false);
        mOptsWithoutFgs.setPendingIntentBackgroundActivityLaunchAllowed(false);
        mOptsTimeBroadcast.setPendingIntentBackgroundActivityLaunchAllowed(false);
        mOptsTimeBroadcast.setPendingIntentBackgroundActivityLaunchAllowed(false);
        mActivityOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false);
        mActivityOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false);
        mBroadcastOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false);
        mMetricsHelper = new MetricsHelper(getContext(), mLock);
        mMetricsHelper = new MetricsHelper(getContext(), mLock);


        mListenerDeathRecipient = new IBinder.DeathRecipient() {
        mListenerDeathRecipient = new IBinder.DeathRecipient() {
@@ -4560,6 +4562,18 @@ public class AlarmManagerService extends SystemService {
        return canAffordBillLocked(alarm, TareBill.getAppropriateBill(alarm));
        return canAffordBillLocked(alarm, TareBill.getAppropriateBill(alarm));
    }
    }


    private Bundle getAlarmOperationBundle(Alarm alarm) {
        if (alarm.mIdleOptions != null) {
            return alarm.mIdleOptions;
        } else {
            if (alarm.operation.isActivity()) {
                return mActivityOptsRestrictBal.toBundle();
            } else {
                return mBroadcastOptsRestrictBal.toBundle();
            }
        }
    }

    @VisibleForTesting
    @VisibleForTesting
    class AlarmHandler extends Handler {
    class AlarmHandler extends Handler {
        public static final int ALARM_EVENT = 1;
        public static final int ALARM_EVENT = 1;
@@ -4599,12 +4613,7 @@ public class AlarmManagerService extends SystemService {
                        Alarm alarm = triggerList.get(i);
                        Alarm alarm = triggerList.get(i);
                        try {
                        try {
                            // Disallow AlarmManager to start random background activity.
                            // Disallow AlarmManager to start random background activity.
                            final Bundle bundle;
                            final Bundle bundle = getAlarmOperationBundle(alarm);
                            if (alarm.operation.isActivity()) {
                                bundle = mActivityOptsRestrictBal.toBundle();
                            } else {
                                bundle = null;
                            }
                            alarm.operation.send(/* context */ null, /* code */0, /* intent */
                            alarm.operation.send(/* context */ null, /* code */0, /* intent */
                                    null, /* onFinished */null, /* handler */
                                    null, /* onFinished */null, /* handler */
                                    null, /* requiredPermission */ null, bundle);
                                    null, /* requiredPermission */ null, bundle);
@@ -5208,16 +5217,7 @@ public class AlarmManagerService extends SystemService {
                    mSendCount++;
                    mSendCount++;


                    try {
                    try {
                        final Bundle bundle;
                        final Bundle bundle = getAlarmOperationBundle(alarm);
                        if (alarm.mIdleOptions != null) {
                            bundle = alarm.mIdleOptions;
                        } else {
                            if (alarm.operation.isActivity()) {
                                bundle = mActivityOptsRestrictBal.toBundle();
                            } else {
                                bundle = null;
                            }
                        }
                        alarm.operation.send(getContext(), 0,
                        alarm.operation.send(getContext(), 0,
                                mBackgroundIntent.putExtra(Intent.EXTRA_ALARM_COUNT, alarm.count),
                                mBackgroundIntent.putExtra(Intent.EXTRA_ALARM_COUNT, alarm.count),
                                mDeliveryTracker, mHandler, null, bundle);
                                mDeliveryTracker, mHandler, null, bundle);
+18 −1
Original line number Original line Diff line number Diff line
@@ -310,6 +310,22 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
                requiredPermission, null, null, 0, 0, 0, options);
                requiredPermission, null, null, 0, 0, 0, options);
    }
    }


    public static boolean isPendingIntentBalAllowedByCaller(
            @Nullable ActivityOptions activityOptions) {
        if (activityOptions == null) {
            return ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT;
        }
        return isPendingIntentBalAllowedByCaller(activityOptions.toBundle());
    }

    private static boolean isPendingIntentBalAllowedByCaller(@Nullable Bundle options) {
        if (options == null) {
            return ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT;
        }
        return options.getBoolean(ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED,
                ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT);
    }

    public int sendInner(int code, Intent intent, String resolvedType, IBinder allowlistToken,
    public int sendInner(int code, Intent intent, String resolvedType, IBinder allowlistToken,
            IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo,
            IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo,
            String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) {
            String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) {
@@ -431,7 +447,8 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
            // temporarily allow receivers and services to open activities from background if the
            // temporarily allow receivers and services to open activities from background if the
            // PendingIntent.send() caller was foreground at the time of sendInner() call
            // PendingIntent.send() caller was foreground at the time of sendInner() call
            final boolean allowTrampoline = uid != callingUid
            final boolean allowTrampoline = uid != callingUid
                    && controller.mAtmInternal.isUidForeground(callingUid);
                    && controller.mAtmInternal.isUidForeground(callingUid)
                    && isPendingIntentBalAllowedByCaller(options);


            // note: we on purpose don't pass in the information about the PendingIntent's creator,
            // note: we on purpose don't pass in the information about the PendingIntent's creator,
            // like pid or ProcessRecord, to the ActivityTaskManagerInternal calls below, because
            // like pid or ProcessRecord, to the ActivityTaskManagerInternal calls below, because
+1 −13
Original line number Original line Diff line number Diff line
@@ -1254,18 +1254,6 @@ class ActivityStarter {
        return activity != null && packageName.equals(activity.getPackageName());
        return activity != null && packageName.equals(activity.getPackageName());
    }
    }


    private static boolean isPendingIntentBalAllowedByCaller(ActivityOptions activityOptions) {
        if (activityOptions == null) {
            return ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT;
        }
        final Bundle options = activityOptions.toBundle();
        if (options == null) {
            return ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT;
        }
        return options.getBoolean(ActivityOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED,
                ActivityOptions.PENDING_INTENT_BAL_ALLOWED_DEFAULT);
    }

    boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
    boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
            final String callingPackage, int realCallingUid, int realCallingPid,
            final String callingPackage, int realCallingUid, int realCallingPid,
            WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
            WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
@@ -1345,7 +1333,7 @@ class ActivityStarter {


        // Legacy behavior allows to use caller foreground state to bypass BAL restriction.
        // Legacy behavior allows to use caller foreground state to bypass BAL restriction.
        final boolean balAllowedByPiSender =
        final boolean balAllowedByPiSender =
                isPendingIntentBalAllowedByCaller(checkedOptions);
                PendingIntentRecord.isPendingIntentBalAllowedByCaller(checkedOptions);


        if (balAllowedByPiSender && realCallingUid != callingUid) {
        if (balAllowedByPiSender && realCallingUid != callingUid) {
            if (isPiBalOptionEnabled) {
            if (isPiBalOptionEnabled) {