Loading apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +23 −2 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.AlarmManager; import android.app.AppOpsManager; import android.app.BroadcastOptions; Loading Loading @@ -317,6 +318,8 @@ public class AlarmManagerService extends SystemService { private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser = new SparseBooleanArray(); private boolean mNextAlarmClockMayChange; ActivityOptions mActivityOptsRestrictBal = ActivityOptions.makeBasic(); BroadcastOptions mBroadcastOptsRestrictBal = BroadcastOptions.makeBasic(); @GuardedBy("mLock") private final Runnable mAlarmClockUpdater = () -> mNextAlarmClockMayChange = true; Loading Loading @@ -1611,6 +1614,11 @@ public class AlarmManagerService extends SystemService { @Override public void onStart() { mInjector.init(); mOptsWithFgs.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsWithoutFgs.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsTimeBroadcast.setPendingIntentBackgroundActivityLaunchAllowed(false); mActivityOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false); mBroadcastOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false); mMetricsHelper = new MetricsHelper(getContext(), mLock); mListenerDeathRecipient = new IBinder.DeathRecipient() { Loading Loading @@ -4306,6 +4314,14 @@ public class AlarmManagerService extends SystemService { 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 class AlarmHandler extends Handler { Loading Loading @@ -4344,7 +4360,11 @@ public class AlarmManagerService extends SystemService { for (int i = 0; i < triggerList.size(); i++) { Alarm alarm = triggerList.get(i); 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) { if (alarm.repeatInterval > 0) { // This IntentSender is no longer valid, but this Loading Loading @@ -4906,9 +4926,10 @@ public class AlarmManagerService extends SystemService { mSendCount++; try { final Bundle bundle = getAlarmOperationBundle(alarm); alarm.operation.send(getContext(), 0, mBackgroundIntent.putExtra(Intent.EXTRA_ALARM_COUNT, alarm.count), mDeliveryTracker, mHandler, null, alarm.mIdleOptions); mDeliveryTracker, mHandler, null, bundle); } catch (PendingIntent.CanceledException e) { if (alarm.repeatInterval > 0) { // This IntentSender is no longer valid, but this Loading core/java/android/app/ActivityOptions.java +5 −5 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ import java.util.ArrayList; * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle) * Context.startActivity(Intent, Bundle)} and related methods. */ public class ActivityOptions { public class ActivityOptions extends ComponentOptions { private static final String TAG = "ActivityOptions"; /** Loading Loading @@ -1081,13 +1081,12 @@ public class ActivityOptions { } private ActivityOptions() { super(); } /** @hide */ public ActivityOptions(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); super(opts); mPackageName = opts.getString(KEY_PACKAGE_NAME); try { Loading Loading @@ -1832,8 +1831,9 @@ public class ActivityOptions { * object; you must not modify it, but can supply it to the startActivity * methods that take an options Bundle. */ @Override public Bundle toBundle() { Bundle b = new Bundle(); Bundle b = super.toBundle(); if (mPackageName != null) { b.putString(KEY_PACKAGE_NAME, mPackageName); } Loading core/java/android/app/BroadcastOptions.java +23 −2 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ import android.os.PowerExemptionManager.TempAllowListType; * {@hide} */ @SystemApi public class BroadcastOptions { public class BroadcastOptions extends ComponentOptions { private long mTemporaryAppAllowlistDuration; private @TempAllowListType int mTemporaryAppAllowlistType; private @ReasonCode int mTemporaryAppAllowlistReasonCode; Loading Loading @@ -108,12 +108,14 @@ public class BroadcastOptions { } private BroadcastOptions() { super(); resetTemporaryAppAllowlist(); } /** @hide */ @TestApi public BroadcastOptions(@NonNull Bundle opts) { super(opts); // Match the logic in toBundle(). if (opts.containsKey(KEY_TEMPORARY_APP_ALLOWLIST_DURATION)) { mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION); Loading Loading @@ -190,6 +192,24 @@ public class BroadcastOptions { 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}. * @hide Loading Loading @@ -308,8 +328,9 @@ public class BroadcastOptions { * object; you must not modify it, but can supply it to the sendBroadcast * methods that take an options Bundle. */ @Override public Bundle toBundle() { Bundle b = new Bundle(); Bundle b = super.toBundle(); if (isTemporaryAppAllowlistSet()) { b.putLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION, mTemporaryAppAllowlistDuration); b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE, mTemporaryAppAllowlistType); Loading core/java/android/app/ComponentOptions.java 0 → 100644 +83 −0 Original line number 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; } } services/core/java/com/android/server/am/PendingIntentRecord.java +21 −1 Original line number Diff line number Diff line Loading @@ -310,6 +310,25 @@ public final class PendingIntentRecord extends IIntentSender.Stub { 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, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) { Loading Loading @@ -431,7 +450,8 @@ public final class PendingIntentRecord extends IIntentSender.Stub { // temporarily allow receivers and services to open activities from background if the // PendingIntent.send() caller was foreground at the time of sendInner() call 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, // like pid or ProcessRecord, to the ActivityTaskManagerInternal calls below, because Loading Loading
apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +23 −2 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.AlarmManager; import android.app.AppOpsManager; import android.app.BroadcastOptions; Loading Loading @@ -317,6 +318,8 @@ public class AlarmManagerService extends SystemService { private final SparseBooleanArray mPendingSendNextAlarmClockChangedForUser = new SparseBooleanArray(); private boolean mNextAlarmClockMayChange; ActivityOptions mActivityOptsRestrictBal = ActivityOptions.makeBasic(); BroadcastOptions mBroadcastOptsRestrictBal = BroadcastOptions.makeBasic(); @GuardedBy("mLock") private final Runnable mAlarmClockUpdater = () -> mNextAlarmClockMayChange = true; Loading Loading @@ -1611,6 +1614,11 @@ public class AlarmManagerService extends SystemService { @Override public void onStart() { mInjector.init(); mOptsWithFgs.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsWithoutFgs.setPendingIntentBackgroundActivityLaunchAllowed(false); mOptsTimeBroadcast.setPendingIntentBackgroundActivityLaunchAllowed(false); mActivityOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false); mBroadcastOptsRestrictBal.setPendingIntentBackgroundActivityLaunchAllowed(false); mMetricsHelper = new MetricsHelper(getContext(), mLock); mListenerDeathRecipient = new IBinder.DeathRecipient() { Loading Loading @@ -4306,6 +4314,14 @@ public class AlarmManagerService extends SystemService { 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 class AlarmHandler extends Handler { Loading Loading @@ -4344,7 +4360,11 @@ public class AlarmManagerService extends SystemService { for (int i = 0; i < triggerList.size(); i++) { Alarm alarm = triggerList.get(i); 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) { if (alarm.repeatInterval > 0) { // This IntentSender is no longer valid, but this Loading Loading @@ -4906,9 +4926,10 @@ public class AlarmManagerService extends SystemService { mSendCount++; try { final Bundle bundle = getAlarmOperationBundle(alarm); alarm.operation.send(getContext(), 0, mBackgroundIntent.putExtra(Intent.EXTRA_ALARM_COUNT, alarm.count), mDeliveryTracker, mHandler, null, alarm.mIdleOptions); mDeliveryTracker, mHandler, null, bundle); } catch (PendingIntent.CanceledException e) { if (alarm.repeatInterval > 0) { // This IntentSender is no longer valid, but this Loading
core/java/android/app/ActivityOptions.java +5 −5 Original line number Diff line number Diff line Loading @@ -69,7 +69,7 @@ import java.util.ArrayList; * {@link android.content.Context#startActivity(android.content.Intent, android.os.Bundle) * Context.startActivity(Intent, Bundle)} and related methods. */ public class ActivityOptions { public class ActivityOptions extends ComponentOptions { private static final String TAG = "ActivityOptions"; /** Loading Loading @@ -1081,13 +1081,12 @@ public class ActivityOptions { } private ActivityOptions() { super(); } /** @hide */ public ActivityOptions(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); super(opts); mPackageName = opts.getString(KEY_PACKAGE_NAME); try { Loading Loading @@ -1832,8 +1831,9 @@ public class ActivityOptions { * object; you must not modify it, but can supply it to the startActivity * methods that take an options Bundle. */ @Override public Bundle toBundle() { Bundle b = new Bundle(); Bundle b = super.toBundle(); if (mPackageName != null) { b.putString(KEY_PACKAGE_NAME, mPackageName); } Loading
core/java/android/app/BroadcastOptions.java +23 −2 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ import android.os.PowerExemptionManager.TempAllowListType; * {@hide} */ @SystemApi public class BroadcastOptions { public class BroadcastOptions extends ComponentOptions { private long mTemporaryAppAllowlistDuration; private @TempAllowListType int mTemporaryAppAllowlistType; private @ReasonCode int mTemporaryAppAllowlistReasonCode; Loading Loading @@ -108,12 +108,14 @@ public class BroadcastOptions { } private BroadcastOptions() { super(); resetTemporaryAppAllowlist(); } /** @hide */ @TestApi public BroadcastOptions(@NonNull Bundle opts) { super(opts); // Match the logic in toBundle(). if (opts.containsKey(KEY_TEMPORARY_APP_ALLOWLIST_DURATION)) { mTemporaryAppAllowlistDuration = opts.getLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION); Loading Loading @@ -190,6 +192,24 @@ public class BroadcastOptions { 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}. * @hide Loading Loading @@ -308,8 +328,9 @@ public class BroadcastOptions { * object; you must not modify it, but can supply it to the sendBroadcast * methods that take an options Bundle. */ @Override public Bundle toBundle() { Bundle b = new Bundle(); Bundle b = super.toBundle(); if (isTemporaryAppAllowlistSet()) { b.putLong(KEY_TEMPORARY_APP_ALLOWLIST_DURATION, mTemporaryAppAllowlistDuration); b.putInt(KEY_TEMPORARY_APP_ALLOWLIST_TYPE, mTemporaryAppAllowlistType); Loading
core/java/android/app/ComponentOptions.java 0 → 100644 +83 −0 Original line number 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; } }
services/core/java/com/android/server/am/PendingIntentRecord.java +21 −1 Original line number Diff line number Diff line Loading @@ -310,6 +310,25 @@ public final class PendingIntentRecord extends IIntentSender.Stub { 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, IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo, String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) { Loading Loading @@ -431,7 +450,8 @@ public final class PendingIntentRecord extends IIntentSender.Stub { // temporarily allow receivers and services to open activities from background if the // PendingIntent.send() caller was foreground at the time of sendInner() call 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, // like pid or ProcessRecord, to the ActivityTaskManagerInternal calls below, because Loading