diff options
4 files changed, 65 insertions, 5 deletions
diff --git a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java index f96fc835b064..b62ece6759c6 100644 --- a/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java +++ b/apex/jobscheduler/framework/java/android/os/PowerExemptionManager.java @@ -236,7 +236,21 @@ public class PowerExemptionManager { * @hide */ public static final int REASON_BLUETOOTH_BROADCAST = 203; - + /** + * Broadcast {@link android.content.Intent#ACTION_TIMEZONE_CHANGED} + * @hide + */ + public static final int REASON_TIMEZONE_CHANGED = 204; + /** + * Broadcast {@link android.content.Intent#ACTION_TIME_CHANGED} + * @hide + */ + public static final int REASON_TIME_CHANGED = 205; + /** + * Broadcast {@link android.content.Intent#ACTION_LOCALE_CHANGED} + * @hide + */ + public static final int REASON_LOCALE_CHANGED = 206; /* Reason code range 300-399 are reserved for other internal reasons */ /** * Device idle system allow list, including EXCEPT-IDLE @@ -369,6 +383,9 @@ public class PowerExemptionManager { REASON_PRE_BOOT_COMPLETED, REASON_LOCKED_BOOT_COMPLETED, REASON_BLUETOOTH_BROADCAST, + REASON_TIMEZONE_CHANGED, + REASON_TIME_CHANGED, + REASON_LOCALE_CHANGED, REASON_SYSTEM_ALLOW_LISTED, REASON_ALARM_MANAGER_ALARM_CLOCK, REASON_ALARM_MANAGER_WHILE_IDLE, @@ -641,6 +658,12 @@ public class PowerExemptionManager { return "LOCKED_BOOT_COMPLETED"; case REASON_BLUETOOTH_BROADCAST: return "BLUETOOTH_BROADCAST"; + case REASON_TIMEZONE_CHANGED: + return "TIMEZONE_CHANGED"; + case REASON_TIME_CHANGED: + return "TIME_CHANGED"; + case REASON_LOCALE_CHANGED: + return "LOCALE_CHANGED"; case REASON_SYSTEM_ALLOW_LISTED: return "SYSTEM_ALLOW_LISTED"; case REASON_ALARM_MANAGER_ALARM_CLOCK: diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index 308866f542cc..70d0d5d18118 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -30,6 +30,7 @@ import static android.app.AlarmManager.INTERVAL_HOUR; import static android.app.AlarmManager.RTC; import static android.app.AlarmManager.RTC_WAKEUP; import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; +import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; import static android.os.PowerWhitelistManager.REASON_ALARM_MANAGER_WHILE_IDLE; import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED; import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED; @@ -81,6 +82,7 @@ import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.ParcelableException; +import android.os.PowerExemptionManager; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; @@ -295,6 +297,7 @@ public class AlarmManagerService extends SystemService { BroadcastOptions mOptsWithFgs = BroadcastOptions.makeBasic(); BroadcastOptions mOptsWithoutFgs = BroadcastOptions.makeBasic(); + BroadcastOptions mOptsTimeBroadcast = BroadcastOptions.makeBasic(); // TODO(b/172085676): Move inside alarm store. private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser = @@ -1789,7 +1792,12 @@ public class AlarmManagerService extends SystemService { | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); intent.putExtra(Intent.EXTRA_TIMEZONE, zone.getID()); - getContext().sendBroadcastAsUser(intent, UserHandle.ALL); + mOptsTimeBroadcast.setTemporaryAppAllowlist( + mActivityManagerInternal.getBootTimeTempAllowListDuration(), + TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, + PowerExemptionManager.REASON_TIMEZONE_CHANGED, ""); + getContext().sendBroadcastAsUser(intent, UserHandle.ALL, + null /* receiverPermission */, mOptsTimeBroadcast.toBundle()); } } @@ -3937,8 +3945,12 @@ public class AlarmManagerService extends SystemService { | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS); - getContext().sendBroadcastAsUser(intent, UserHandle.ALL); - + mOptsTimeBroadcast.setTemporaryAppAllowlist( + mActivityManagerInternal.getBootTimeTempAllowListDuration(), + TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, + PowerExemptionManager.REASON_TIME_CHANGED, ""); + getContext().sendBroadcastAsUser(intent, UserHandle.ALL, + null /* receiverPermission */, mOptsTimeBroadcast.toBundle()); // The world has changed on us, so we need to re-evaluate alarms // regardless of whether the kernel has told us one went off. result |= IS_WAKEUP_MASK; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index cf0ba7e93d3d..6a3cb6f22886 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -15840,8 +15840,12 @@ public class ActivityManagerService extends IActivityManager.Stub if (initLocale || !mProcessesReady) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); } + final BroadcastOptions bOptions = BroadcastOptions.makeBasic(); + bOptions.setTemporaryAppAllowlist(mInternal.getBootTimeTempAllowListDuration(), + TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, + PowerExemptionManager.REASON_LOCALE_CHANGED, ""); broadcastIntentLocked(null, null, null, intent, null, null, 0, null, null, null, - null, OP_NONE, null, false, false, MY_PID, SYSTEM_UID, + null, OP_NONE, bOptions.toBundle(), false, false, MY_PID, SYSTEM_UID, Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL); } diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java index 8382ff4cb506..72342810c4b6 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java @@ -129,9 +129,11 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.PowerExemptionManager; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemProperties; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.provider.DeviceConfig; @@ -369,6 +371,7 @@ public class AlarmManagerServiceTest { .mockStatic(MetricsHelper.class) .mockStatic(Settings.Global.class) .mockStatic(ServiceManager.class) + .mockStatic(SystemProperties.class) .spyStatic(UserHandle.class) .strictness(Strictness.WARN) .startMocking(); @@ -2579,6 +2582,24 @@ public class AlarmManagerServiceTest { verify(() -> MetricsHelper.pushAlarmBatchDelivered(10, 5)); } + @Test + public void setTimeZoneImpl() { + final long durationMs = 20000L; + when(mActivityManagerInternal.getBootTimeTempAllowListDuration()).thenReturn(durationMs); + mService.setTimeZoneImpl("UTC"); + final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); + final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class); + verify(mMockContext).sendBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL), + isNull(), bundleCaptor.capture()); + assertEquals(Intent.ACTION_TIMEZONE_CHANGED, intentCaptor.getValue().getAction()); + final BroadcastOptions bOptions = new BroadcastOptions(bundleCaptor.getValue()); + assertEquals(durationMs, bOptions.getTemporaryAppAllowlistDuration()); + assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, + bOptions.getTemporaryAppAllowlistType()); + assertEquals(PowerExemptionManager.REASON_TIMEZONE_CHANGED, + bOptions.getTemporaryAppAllowlistReasonCode()); + } + @After public void tearDown() { if (mMockingSession != null) { |