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 @@ -4908,9 +4928,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; } } core/java/android/content/Intent.java +1 −1 Original line number Diff line number Diff line Loading @@ -11011,7 +11011,7 @@ public class Intent implements Parcelable, Cloneable { private void toUriInner(StringBuilder uri, String scheme, String defAction, String defPackage, int flags) { if (scheme != null) { uri.append("scheme=").append(scheme).append(';'); uri.append("scheme=").append(Uri.encode(scheme)).append(';'); } if (mAction != null && !mAction.equals(defAction)) { uri.append("action=").append(Uri.encode(mAction)).append(';'); 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 @@ -4908,9 +4928,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; } }
core/java/android/content/Intent.java +1 −1 Original line number Diff line number Diff line Loading @@ -11011,7 +11011,7 @@ public class Intent implements Parcelable, Cloneable { private void toUriInner(StringBuilder uri, String scheme, String defAction, String defPackage, int flags) { if (scheme != null) { uri.append("scheme=").append(scheme).append(';'); uri.append("scheme=").append(Uri.encode(scheme)).append(';'); } if (mAction != null && !mAction.equals(defAction)) { uri.append("action=").append(Uri.encode(mAction)).append(';'); Loading