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

Commit 543f6be0 authored by Presubmit Automerger Backend's avatar Presubmit Automerger Backend
Browse files

[automerge] [DO NOT MERGE] Backport BAL restrictions from T to S, this blocks...

[automerge] [DO NOT MERGE] Backport BAL restrictions from T to S, this blocks apps from using Alarm 2p: 7a41e2fb

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20835978

Bug: 195756028
Change-Id: I03daa0f5a61ced10eb6003dd6d39e2510d01bed6
parents 5c6e0c3f 7a41e2fb
Loading
Loading
Loading
Loading
+23 −2
Original line number Original line Diff line number Diff line
@@ -56,6 +56,7 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.Activity;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.AlarmManager;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.BroadcastOptions;
@@ -317,6 +318,8 @@ public class AlarmManagerService extends SystemService {
    private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
    private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser =
            new SparseBooleanArray();
            new SparseBooleanArray();
    private boolean mNextAlarmClockMayChange;
    private boolean mNextAlarmClockMayChange;
    ActivityOptions mActivityOptsRestrictBal = ActivityOptions.makeBasic();
    BroadcastOptions mBroadcastOptsRestrictBal = BroadcastOptions.makeBasic();


    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private final Runnable mAlarmClockUpdater = () -> mNextAlarmClockMayChange = true;
    private final Runnable mAlarmClockUpdater = () -> mNextAlarmClockMayChange = true;
@@ -1611,6 +1614,11 @@ public class AlarmManagerService extends SystemService {
    @Override
    @Override
    public void onStart() {
    public void onStart() {
        mInjector.init();
        mInjector.init();
        mOptsWithFgs.setPendingIntentBackgroundActivityLaunchAllowed(false);
        mOptsWithoutFgs.setPendingIntentBackgroundActivityLaunchAllowed(false);
        mOptsTimeBroadcast.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() {
@@ -4306,6 +4314,14 @@ public class AlarmManagerService extends SystemService {
        return alarm.creatorUid;
        return alarm.creatorUid;
    }
    }


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


    @VisibleForTesting
    @VisibleForTesting
    class AlarmHandler extends Handler {
    class AlarmHandler extends Handler {
@@ -4344,7 +4360,11 @@ public class AlarmManagerService extends SystemService {
                    for (int i = 0; i < triggerList.size(); i++) {
                    for (int i = 0; i < triggerList.size(); i++) {
                        Alarm alarm = triggerList.get(i);
                        Alarm alarm = triggerList.get(i);
                        try {
                        try {
                            alarm.operation.send();
                            // Disallow AlarmManager to start random background activity.
                            final Bundle bundle = getAlarmOperationBundle(alarm);
                            alarm.operation.send(/* context */ null, /* code */0, /* intent */
                                    null, /* onFinished */null, /* handler */
                                    null, /* requiredPermission */ null, bundle);
                        } catch (PendingIntent.CanceledException e) {
                        } catch (PendingIntent.CanceledException e) {
                            if (alarm.repeatInterval > 0) {
                            if (alarm.repeatInterval > 0) {
                                // This IntentSender is no longer valid, but this
                                // This IntentSender is no longer valid, but this
@@ -4906,9 +4926,10 @@ public class AlarmManagerService extends SystemService {
                    mSendCount++;
                    mSendCount++;


                    try {
                    try {
                        final Bundle bundle = getAlarmOperationBundle(alarm);
                        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, alarm.mIdleOptions);
                                mDeliveryTracker, mHandler, null, bundle);
                    } catch (PendingIntent.CanceledException e) {
                    } catch (PendingIntent.CanceledException e) {
                        if (alarm.repeatInterval > 0) {
                        if (alarm.repeatInterval > 0) {
                            // This IntentSender is no longer valid, but this
                            // This IntentSender is no longer valid, but this
+5 −5
Original line number Original line Diff line number Diff line
@@ -68,7 +68,7 @@ import java.util.ArrayList;
 * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
 * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle)
 * Context.startActivity(Intent, Bundle)} and related methods.
 * Context.startActivity(Intent, Bundle)} and related methods.
 */
 */
public class ActivityOptions {
public class ActivityOptions extends ComponentOptions {
    private static final String TAG = "ActivityOptions";
    private static final String TAG = "ActivityOptions";


    /**
    /**
@@ -1071,13 +1071,12 @@ public class ActivityOptions {
    }
    }


    private ActivityOptions() {
    private ActivityOptions() {
        super();
    }
    }


    /** @hide */
    /** @hide */
    public ActivityOptions(Bundle opts) {
    public ActivityOptions(Bundle opts) {
        // If the remote side sent us bad parcelables, they won't get the
        super(opts);
        // results they want, which is their loss.
        opts.setDefusable(true);


        mPackageName = opts.getString(KEY_PACKAGE_NAME);
        mPackageName = opts.getString(KEY_PACKAGE_NAME);
        try {
        try {
@@ -1804,8 +1803,9 @@ public class ActivityOptions {
     * object; you must not modify it, but can supply it to the startActivity
     * object; you must not modify it, but can supply it to the startActivity
     * methods that take an options Bundle.
     * methods that take an options Bundle.
     */
     */
    @Override
    public Bundle toBundle() {
    public Bundle toBundle() {
        Bundle b = new Bundle();
        Bundle b = super.toBundle();
        if (mPackageName != null) {
        if (mPackageName != null) {
            b.putString(KEY_PACKAGE_NAME, mPackageName);
            b.putString(KEY_PACKAGE_NAME, mPackageName);
        }
        }
+23 −2
Original line number Original line Diff line number Diff line
@@ -34,7 +34,7 @@ import android.os.PowerExemptionManager.TempAllowListType;
 * {@hide}
 * {@hide}
 */
 */
@SystemApi
@SystemApi
public class BroadcastOptions {
public class BroadcastOptions extends ComponentOptions {
    private long mTemporaryAppAllowlistDuration;
    private long mTemporaryAppAllowlistDuration;
    private @TempAllowListType int mTemporaryAppAllowlistType;
    private @TempAllowListType int mTemporaryAppAllowlistType;
    private @ReasonCode int mTemporaryAppAllowlistReasonCode;
    private @ReasonCode int mTemporaryAppAllowlistReasonCode;
@@ -108,12 +108,14 @@ public class BroadcastOptions {
    }
    }


    private BroadcastOptions() {
    private BroadcastOptions() {
        super();
        resetTemporaryAppAllowlist();
        resetTemporaryAppAllowlist();
    }
    }


    /** @hide */
    /** @hide */
    @TestApi
    @TestApi
    public BroadcastOptions(@NonNull Bundle opts) {
    public BroadcastOptions(@NonNull Bundle opts) {
        super(opts);
        // Match the logic in toBundle().
        // Match the logic in toBundle().
        if (opts.containsKey(KEY_TEMPORARY_APP_ALLOWLIST_DURATION)) {
        if (opts.containsKey(KEY_TEMPORARY_APP_ALLOWLIST_DURATION)) {
            mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION);
            mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION);
@@ -190,6 +192,24 @@ public class BroadcastOptions {
        mTemporaryAppAllowlistReason = null;
        mTemporaryAppAllowlistReason = null;
    }
    }


    /**
     * Set PendingIntent activity is allowed to be started in the background if the caller
     * can start background activities.
     * @hide
     */
    public void setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed) {
        super.setPendingIntentBackgroundActivityLaunchAllowed(allowed);
    }

    /**
     * Get PendingIntent activity is allowed to be started in the background if the caller
     * can start background activities.
     * @hide
     */
    public boolean isPendingIntentBackgroundActivityLaunchAllowed() {
        return super.isPendingIntentBackgroundActivityLaunchAllowed();
    }

    /**
    /**
     * Return {@link #setTemporaryAppAllowlist}.
     * Return {@link #setTemporaryAppAllowlist}.
     * @hide
     * @hide
@@ -308,8 +328,9 @@ public class BroadcastOptions {
     * object; you must not modify it, but can supply it to the sendBroadcast
     * object; you must not modify it, but can supply it to the sendBroadcast
     * methods that take an options Bundle.
     * methods that take an options Bundle.
     */
     */
    @Override
    public Bundle toBundle() {
    public Bundle toBundle() {
        Bundle b = new Bundle();
        Bundle b = super.toBundle();
        if (isTemporaryAppAllowlistSet()) {
        if (isTemporaryAppAllowlistSet()) {
            b.putLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION, mTemporaryAppAllowlistDuration);
            b.putLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION, mTemporaryAppAllowlistDuration);
            b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE, mTemporaryAppAllowlistType);
            b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE, mTemporaryAppAllowlistType);
+83 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app;

import android.os.Bundle;

/**
 * @hide
 */
public class ComponentOptions {

    /**
     * Default value for KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED.
     * @hide
     **/
    public static final boolean PENDING_INTENT_BAL_ALLOWED_DEFAULT = true;

    /**
     * PendingIntent caller allows activity start even if PendingIntent creator is in background.
     * This only works if the PendingIntent caller is allowed to start background activities,
     * for example if it's in the foreground, or has BAL permission.
     * @hide
     */
    public static final String KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED =
            "android.pendingIntent.backgroundActivityAllowed";

    private boolean mPendingIntentBalAllowed = PENDING_INTENT_BAL_ALLOWED_DEFAULT;

    ComponentOptions() {
    }

    ComponentOptions(Bundle opts) {
        // If the remote side sent us bad parcelables, they won't get the
        // results they want, which is their loss.
        opts.setDefusable(true);
        setPendingIntentBackgroundActivityLaunchAllowed(
                opts.getBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED,
                        PENDING_INTENT_BAL_ALLOWED_DEFAULT));
    }

    /**
     * Set PendingIntent activity is allowed to be started in the background if the caller
     * can start background activities.
     *
     * @hide
     */
    public void setPendingIntentBackgroundActivityLaunchAllowed(boolean allowed) {
        mPendingIntentBalAllowed = allowed;
    }

    /**
     * Get PendingIntent activity is allowed to be started in the background if the caller
     * can start background activities.
     *
     * @hide
     */
    public boolean isPendingIntentBackgroundActivityLaunchAllowed() {
        return mPendingIntentBalAllowed;
    }

    /**
     * @hide
     */
    public Bundle toBundle() {
        Bundle bundle = new Bundle();
        bundle.putBoolean(KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED, mPendingIntentBalAllowed);
        return bundle;
    }
}
+21 −1
Original line number Original line Diff line number Diff line
@@ -310,6 +310,25 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
                requiredPermission, null, null, 0, 0, 0, options);
                requiredPermission, null, null, 0, 0, 0, options);
    }
    }


    /**
     * Return true if the activity options allows PendingIntent to use caller's BAL permission.
     */
    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) {
@@ -436,7 +455,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
Loading