Loading apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +28 −72 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.alarm; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE; Loading @@ -27,14 +28,13 @@ import static android.os.UserHandle.USER_SYSTEM; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.AppOpsManager; import android.app.BroadcastOptions; import android.app.IAlarmCompleteListener; import android.app.IAlarmListener; import android.app.IAlarmManager; import android.app.IUidObserver; import android.app.PendingIntent; import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManagerInternal; Loading Loading @@ -183,6 +183,7 @@ public class AlarmManagerService extends SystemService { AppOpsManager mAppOps; DeviceIdleInternal mLocalDeviceIdleController; private UsageStatsManagerInternal mUsageStatsManagerInternal; private ActivityManagerInternal mActivityManagerInternal; final Object mLock = new Object(); Loading Loading @@ -1572,15 +1573,6 @@ public class AlarmManagerService extends SystemService { } else { Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler."); } try { ActivityManager.getService().registerUidObserver(new UidObserver(), ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_ACTIVE, ActivityManager.PROCESS_STATE_UNKNOWN, null); } catch (RemoteException e) { // ignored; both services live in system_server } } publishLocalService(AlarmManagerInternal.class, new LocalService()); publishBinderService(Context.ALARM_SERVICE, mService); Loading @@ -1592,6 +1584,7 @@ public class AlarmManagerService extends SystemService { synchronized (mLock) { mConstants.start(getContext().getContentResolver()); mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); mLocalDeviceIdleController = LocalServices.getService(DeviceIdleInternal.class); mUsageStatsManagerInternal = Loading Loading @@ -1790,14 +1783,11 @@ public class AlarmManagerService extends SystemService { Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval, operation, directReceiver, listenerTag, workSource, flags, alarmClock, callingUid, callingPackage); try { if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) { if (mActivityManagerInternal.isAppStartModeDisabled(callingUid, callingPackage)) { Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a + " -- package not allowed to start"); return; } } catch (RemoteException e) { } removeLocked(operation, directReceiver); incrementAlarmCount(a.uid); setImplLocked(a, false, doValidate); Loading Loading @@ -2147,10 +2137,11 @@ public class AlarmManagerService extends SystemService { @Override public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) { userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */, if (mActivityManagerInternal != null) { userId = mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, /*allowAll=*/false, ALLOW_NON_FULL, "getNextAlarmClock", null); } return getNextAlarmClockImpl(userId); } Loading Loading @@ -3226,15 +3217,8 @@ public class AlarmManagerService extends SystemService { return; } boolean didRemove = false; final Predicate<Alarm> whichAlarms = (Alarm a) -> { try { if (a.uid == uid && ActivityManager.getService().isAppStartModeDisabled( uid, a.packageName)) { return true; } } catch (RemoteException e) { /* fall through */} return false; }; final Predicate<Alarm> whichAlarms = (a) -> (a.uid == uid && mActivityManagerInternal.isAppStartModeDisabled(uid, a.packageName)); for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); didRemove |= b.remove(whichAlarms, false); Loading Loading @@ -3822,8 +3806,8 @@ public class AlarmManagerService extends SystemService { Slog.v(TAG, "sending alarm " + alarm); } if (RECORD_ALARMS_IN_HISTORY) { ActivityManager.noteAlarmStart(alarm.operation, alarm.workSource, alarm.uid, alarm.statsTag); mActivityManagerInternal.noteAlarmStart(alarm.operation, alarm.workSource, alarm.uid, alarm.statsTag); } mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle); } catch (RuntimeException e) { Loading Loading @@ -4128,17 +4112,12 @@ public class AlarmManagerService extends SystemService { public static final int REPORT_ALARMS_ACTIVE = 4; public static final int APP_STANDBY_BUCKET_CHANGED = 5; public static final int CHARGING_STATUS_CHANGED = 6; public static final int REMOVE_FOR_STOPPED = 7; public static final int REMOVE_FOR_CANCELED = 8; public static final int REMOVE_FOR_CANCELED = 7; AlarmHandler() { super(Looper.myLooper()); } public void postRemoveForStopped(int uid) { obtainMessage(REMOVE_FOR_STOPPED, uid, 0).sendToTarget(); } @Override public void handleMessage(Message msg) { switch (msg.what) { Loading Loading @@ -4206,12 +4185,6 @@ public class AlarmManagerService extends SystemService { } break; case REMOVE_FOR_STOPPED: synchronized (mLock) { removeForStoppedLocked(msg.arg1); } break; case REMOVE_FOR_CANCELED: final PendingIntent operation = (PendingIntent) msg.obj; synchronized (mLock) { Loading Loading @@ -4418,30 +4391,6 @@ public class AlarmManagerService extends SystemService { } } final class UidObserver extends IUidObserver.Stub { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { } @Override public void onUidGone(int uid, boolean disabled) { if (disabled) { mHandler.postRemoveForStopped(uid); } } @Override public void onUidActive(int uid) { } @Override public void onUidIdle(int uid, boolean disabled) { if (disabled) { mHandler.postRemoveForStopped(uid); } } @Override public void onUidCachedChanged(int uid, boolean cached) { } } /** * Tracking of app assignments to standby buckets */ Loading Loading @@ -4493,6 +4442,13 @@ public class AlarmManagerService extends SystemService { } } } @Override public void removeAlarmsForUid(int uid) { synchronized (mLock) { removeForStoppedLocked(uid); } } }; private final BroadcastStats getStatsLocked(PendingIntent pi) { Loading Loading @@ -4570,8 +4526,8 @@ public class AlarmManagerService extends SystemService { fs.aggregateTime += nowELAPSED - fs.startTime; } if (RECORD_ALARMS_IN_HISTORY) { ActivityManager.noteAlarmFinish(inflight.mPendingIntent, inflight.mWorkSource, inflight.mUid, inflight.mTag); mActivityManagerInternal.noteAlarmFinish(inflight.mPendingIntent, inflight.mWorkSource, inflight.mUid, inflight.mTag); } } Loading Loading @@ -4808,7 +4764,7 @@ public class AlarmManagerService extends SystemService { || alarm.type == RTC_WAKEUP) { bs.numWakeup++; fs.numWakeup++; ActivityManager.noteWakeupAlarm( mActivityManagerInternal.noteWakeupAlarm( alarm.operation, alarm.workSource, alarm.uid, alarm.packageName, alarm.statsTag); } Loading core/java/android/app/ActivityManagerInternal.java +28 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.TransactionTooLargeException; import android.os.WorkSource; import java.util.ArrayList; import java.util.List; Loading Loading @@ -262,6 +263,33 @@ public abstract class ActivityManagerInternal { */ public abstract boolean shouldConfirmCredentials(@UserIdInt int userId); /** * Used in conjunction with {@link #noteAlarmStart(PendingIntent, WorkSource, int, String)} to * note an alarm duration for battery attribution */ public abstract void noteAlarmFinish(PendingIntent ps, WorkSource workSource, int sourceUid, String tag); /** * Used in conjunction with {@link #noteAlarmFinish(PendingIntent, WorkSource, int, String)} to * note an alarm duration for battery attribution */ public abstract void noteAlarmStart(PendingIntent ps, WorkSource workSource, int sourceUid, String tag); /** * Used to note a wakeup alarm for battery attribution. */ public abstract void noteWakeupAlarm(PendingIntent ps, WorkSource workSource, int sourceUid, String sourcePkg, String tag); /** * Returns whether this app is disallowed to run in the background. * * @see ActivityManager#APP_START_MODE_DISABLED */ public abstract boolean isAppStartModeDisabled(int uid, String packageName); public abstract int[] getCurrentProfileIds(); public abstract UserInfo getCurrentUser(); public abstract void ensureNotSpecialUser(@UserIdInt int userId); Loading services/core/java/com/android/server/AppStateTracker.java +24 −4 Original line number Diff line number Diff line Loading @@ -398,6 +398,14 @@ public class AppStateTracker { */ public void onUidForeground(int uid, boolean foreground) { } /** * Called when an ephemeral uid goes to the background, so its alarms need to be removed. * * @param uid */ public void removeAlarmsForUid(int uid) { } } public AppStateTracker(Context context, Looper looper) { Loading Loading @@ -910,14 +918,26 @@ public class AppStateTracker { handleUidActive(msg.arg1); return; case MSG_ON_UID_GONE: handleUidGone(msg.arg1, msg.arg1 != 0); handleUidGone(msg.arg1); if (msg.arg2 != 0) { handleUidDisabled(msg.arg1); } return; case MSG_ON_UID_IDLE: handleUidIdle(msg.arg1, msg.arg1 != 0); handleUidIdle(msg.arg1); if (msg.arg2 != 0) { handleUidDisabled(msg.arg1); } return; } } private void handleUidDisabled(int uid) { for (Listener l : cloneListeners()) { l.removeAlarmsForUid(uid); } } public void handleUidStateChanged(int uid, int procState) { synchronized (mLock) { if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { Loading @@ -940,11 +960,11 @@ public class AppStateTracker { } } public void handleUidGone(int uid, boolean disabled) { public void handleUidGone(int uid) { removeUid(uid, true); } public void handleUidIdle(int uid, boolean disabled) { public void handleUidIdle(int uid) { // Just to avoid excessive memcpy, don't remove from the array in this case. removeUid(uid, false); } Loading services/core/java/com/android/server/am/ActivityManagerService.java +26 −0 Original line number Diff line number Diff line Loading @@ -19269,6 +19269,32 @@ public class ActivityManagerService extends IActivityManager.Stub return mUserController.shouldConfirmCredentials(userId); } @Override public void noteAlarmFinish(PendingIntent ps, WorkSource workSource, int sourceUid, String tag) { ActivityManagerService.this.noteAlarmFinish((ps != null) ? ps.getTarget() : null, workSource, sourceUid, tag); } @Override public void noteAlarmStart(PendingIntent ps, WorkSource workSource, int sourceUid, String tag) { ActivityManagerService.this.noteAlarmStart((ps != null) ? ps.getTarget() : null, workSource, sourceUid, tag); } @Override public void noteWakeupAlarm(PendingIntent ps, WorkSource workSource, int sourceUid, String sourcePkg, String tag) { ActivityManagerService.this.noteWakeupAlarm((ps != null) ? ps.getTarget() : null, workSource, sourceUid, sourcePkg, tag); } @Override public boolean isAppStartModeDisabled(int uid, String packageName) { return ActivityManagerService.this.isAppStartModeDisabled(uid, packageName); } @Override public int[] getCurrentProfileIds() { return mUserController.getCurrentProfileIds(); services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +27 −4 Original line number Diff line number Diff line Loading @@ -60,11 +60,11 @@ import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.atLeastOnce; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.IActivityManager; import android.app.IAlarmCompleteListener; import android.app.IAlarmListener; import android.app.IUidObserver; import android.app.PendingIntent; import android.app.usage.UsageStatsManagerInternal; import android.content.ContentResolver; Loading Loading @@ -129,6 +129,8 @@ public class AlarmManagerServiceTest { @Mock private AppStandbyInternal mAppStandbyInternal; @Mock private ActivityManagerInternal mActivityManagerInternal; @Mock private AppStateTracker mAppStateTracker; @Mock private AlarmManagerService.ClockReceiver mClockReceiver; Loading Loading @@ -253,7 +255,7 @@ public class AlarmManagerServiceTest { } @Before public final void setUp() throws Exception { public final void setUp() { mMockingSession = mockitoSession() .initMocks(this) .spyStatic(ActivityManager.class) Loading @@ -265,6 +267,8 @@ public class AlarmManagerServiceTest { .strictness(Strictness.WARN) .startMocking(); doReturn(mIActivityManager).when(ActivityManager::getService); doReturn(mActivityManagerInternal).when( () -> LocalServices.getService(ActivityManagerInternal.class)); doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class)); doReturn(mAppStandbyInternal).when( () -> LocalServices.getService(AppStandbyInternal.class)); Loading Loading @@ -294,8 +298,6 @@ public class AlarmManagerServiceTest { assertEquals(mService.mSystemUiUid, SYSTEM_UI_UID); assertEquals(mService.mClockReceiver, mClockReceiver); assertEquals(mService.mWakeLock, mWakeLock); verify(mIActivityManager).registerUidObserver(any(IUidObserver.class), anyInt(), anyInt(), isNull()); // Other boot phases don't matter mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); Loading Loading @@ -791,6 +793,27 @@ public class AlarmManagerServiceTest { assertNull(restrictedAlarms.get(TEST_CALLING_UID)); } @Test public void alarmsRemovedOnAppStartModeDisabled() { final ArgumentCaptor<AppStateTracker.Listener> listenerArgumentCaptor = ArgumentCaptor.forClass(AppStateTracker.Listener.class); verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture()); final AppStateTracker.Listener listener = listenerArgumentCaptor.getValue(); final PendingIntent alarmPi1 = getNewMockPendingIntent(); final PendingIntent alarmPi2 = getNewMockPendingIntent(); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, alarmPi1); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 4, alarmPi2); assertEquals(2, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); when(mActivityManagerInternal.isAppStartModeDisabled(TEST_CALLING_UID, TEST_CALLING_PACKAGE)).thenReturn(true); listener.removeAlarmsForUid(TEST_CALLING_UID); assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); } @Test public void sendsTimeTickOnInteractive() { final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); Loading Loading
apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +28 −72 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.alarm; import static android.app.ActivityManagerInternal.ALLOW_NON_FULL; import static android.app.AlarmManager.ELAPSED_REALTIME; import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE; Loading @@ -27,14 +28,13 @@ import static android.os.UserHandle.USER_SYSTEM; import android.annotation.UserIdInt; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.AppOpsManager; import android.app.BroadcastOptions; import android.app.IAlarmCompleteListener; import android.app.IAlarmListener; import android.app.IAlarmManager; import android.app.IUidObserver; import android.app.PendingIntent; import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManagerInternal; Loading Loading @@ -183,6 +183,7 @@ public class AlarmManagerService extends SystemService { AppOpsManager mAppOps; DeviceIdleInternal mLocalDeviceIdleController; private UsageStatsManagerInternal mUsageStatsManagerInternal; private ActivityManagerInternal mActivityManagerInternal; final Object mLock = new Object(); Loading Loading @@ -1572,15 +1573,6 @@ public class AlarmManagerService extends SystemService { } else { Slog.w(TAG, "Failed to open alarm driver. Falling back to a handler."); } try { ActivityManager.getService().registerUidObserver(new UidObserver(), ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE | ActivityManager.UID_OBSERVER_ACTIVE, ActivityManager.PROCESS_STATE_UNKNOWN, null); } catch (RemoteException e) { // ignored; both services live in system_server } } publishLocalService(AlarmManagerInternal.class, new LocalService()); publishBinderService(Context.ALARM_SERVICE, mService); Loading @@ -1592,6 +1584,7 @@ public class AlarmManagerService extends SystemService { synchronized (mLock) { mConstants.start(getContext().getContentResolver()); mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); mLocalDeviceIdleController = LocalServices.getService(DeviceIdleInternal.class); mUsageStatsManagerInternal = Loading Loading @@ -1790,14 +1783,11 @@ public class AlarmManagerService extends SystemService { Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval, operation, directReceiver, listenerTag, workSource, flags, alarmClock, callingUid, callingPackage); try { if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) { if (mActivityManagerInternal.isAppStartModeDisabled(callingUid, callingPackage)) { Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a + " -- package not allowed to start"); return; } } catch (RemoteException e) { } removeLocked(operation, directReceiver); incrementAlarmCount(a.uid); setImplLocked(a, false, doValidate); Loading Loading @@ -2147,10 +2137,11 @@ public class AlarmManagerService extends SystemService { @Override public AlarmManager.AlarmClockInfo getNextAlarmClock(int userId) { userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false /* allowAll */, false /* requireFull */, if (mActivityManagerInternal != null) { userId = mActivityManagerInternal.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, /*allowAll=*/false, ALLOW_NON_FULL, "getNextAlarmClock", null); } return getNextAlarmClockImpl(userId); } Loading Loading @@ -3226,15 +3217,8 @@ public class AlarmManagerService extends SystemService { return; } boolean didRemove = false; final Predicate<Alarm> whichAlarms = (Alarm a) -> { try { if (a.uid == uid && ActivityManager.getService().isAppStartModeDisabled( uid, a.packageName)) { return true; } } catch (RemoteException e) { /* fall through */} return false; }; final Predicate<Alarm> whichAlarms = (a) -> (a.uid == uid && mActivityManagerInternal.isAppStartModeDisabled(uid, a.packageName)); for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { Batch b = mAlarmBatches.get(i); didRemove |= b.remove(whichAlarms, false); Loading Loading @@ -3822,8 +3806,8 @@ public class AlarmManagerService extends SystemService { Slog.v(TAG, "sending alarm " + alarm); } if (RECORD_ALARMS_IN_HISTORY) { ActivityManager.noteAlarmStart(alarm.operation, alarm.workSource, alarm.uid, alarm.statsTag); mActivityManagerInternal.noteAlarmStart(alarm.operation, alarm.workSource, alarm.uid, alarm.statsTag); } mDeliveryTracker.deliverLocked(alarm, nowELAPSED, allowWhileIdle); } catch (RuntimeException e) { Loading Loading @@ -4128,17 +4112,12 @@ public class AlarmManagerService extends SystemService { public static final int REPORT_ALARMS_ACTIVE = 4; public static final int APP_STANDBY_BUCKET_CHANGED = 5; public static final int CHARGING_STATUS_CHANGED = 6; public static final int REMOVE_FOR_STOPPED = 7; public static final int REMOVE_FOR_CANCELED = 8; public static final int REMOVE_FOR_CANCELED = 7; AlarmHandler() { super(Looper.myLooper()); } public void postRemoveForStopped(int uid) { obtainMessage(REMOVE_FOR_STOPPED, uid, 0).sendToTarget(); } @Override public void handleMessage(Message msg) { switch (msg.what) { Loading Loading @@ -4206,12 +4185,6 @@ public class AlarmManagerService extends SystemService { } break; case REMOVE_FOR_STOPPED: synchronized (mLock) { removeForStoppedLocked(msg.arg1); } break; case REMOVE_FOR_CANCELED: final PendingIntent operation = (PendingIntent) msg.obj; synchronized (mLock) { Loading Loading @@ -4418,30 +4391,6 @@ public class AlarmManagerService extends SystemService { } } final class UidObserver extends IUidObserver.Stub { @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) { } @Override public void onUidGone(int uid, boolean disabled) { if (disabled) { mHandler.postRemoveForStopped(uid); } } @Override public void onUidActive(int uid) { } @Override public void onUidIdle(int uid, boolean disabled) { if (disabled) { mHandler.postRemoveForStopped(uid); } } @Override public void onUidCachedChanged(int uid, boolean cached) { } } /** * Tracking of app assignments to standby buckets */ Loading Loading @@ -4493,6 +4442,13 @@ public class AlarmManagerService extends SystemService { } } } @Override public void removeAlarmsForUid(int uid) { synchronized (mLock) { removeForStoppedLocked(uid); } } }; private final BroadcastStats getStatsLocked(PendingIntent pi) { Loading Loading @@ -4570,8 +4526,8 @@ public class AlarmManagerService extends SystemService { fs.aggregateTime += nowELAPSED - fs.startTime; } if (RECORD_ALARMS_IN_HISTORY) { ActivityManager.noteAlarmFinish(inflight.mPendingIntent, inflight.mWorkSource, inflight.mUid, inflight.mTag); mActivityManagerInternal.noteAlarmFinish(inflight.mPendingIntent, inflight.mWorkSource, inflight.mUid, inflight.mTag); } } Loading Loading @@ -4808,7 +4764,7 @@ public class AlarmManagerService extends SystemService { || alarm.type == RTC_WAKEUP) { bs.numWakeup++; fs.numWakeup++; ActivityManager.noteWakeupAlarm( mActivityManagerInternal.noteWakeupAlarm( alarm.operation, alarm.workSource, alarm.uid, alarm.packageName, alarm.statsTag); } Loading
core/java/android/app/ActivityManagerInternal.java +28 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.IBinder; import android.os.TransactionTooLargeException; import android.os.WorkSource; import java.util.ArrayList; import java.util.List; Loading Loading @@ -262,6 +263,33 @@ public abstract class ActivityManagerInternal { */ public abstract boolean shouldConfirmCredentials(@UserIdInt int userId); /** * Used in conjunction with {@link #noteAlarmStart(PendingIntent, WorkSource, int, String)} to * note an alarm duration for battery attribution */ public abstract void noteAlarmFinish(PendingIntent ps, WorkSource workSource, int sourceUid, String tag); /** * Used in conjunction with {@link #noteAlarmFinish(PendingIntent, WorkSource, int, String)} to * note an alarm duration for battery attribution */ public abstract void noteAlarmStart(PendingIntent ps, WorkSource workSource, int sourceUid, String tag); /** * Used to note a wakeup alarm for battery attribution. */ public abstract void noteWakeupAlarm(PendingIntent ps, WorkSource workSource, int sourceUid, String sourcePkg, String tag); /** * Returns whether this app is disallowed to run in the background. * * @see ActivityManager#APP_START_MODE_DISABLED */ public abstract boolean isAppStartModeDisabled(int uid, String packageName); public abstract int[] getCurrentProfileIds(); public abstract UserInfo getCurrentUser(); public abstract void ensureNotSpecialUser(@UserIdInt int userId); Loading
services/core/java/com/android/server/AppStateTracker.java +24 −4 Original line number Diff line number Diff line Loading @@ -398,6 +398,14 @@ public class AppStateTracker { */ public void onUidForeground(int uid, boolean foreground) { } /** * Called when an ephemeral uid goes to the background, so its alarms need to be removed. * * @param uid */ public void removeAlarmsForUid(int uid) { } } public AppStateTracker(Context context, Looper looper) { Loading Loading @@ -910,14 +918,26 @@ public class AppStateTracker { handleUidActive(msg.arg1); return; case MSG_ON_UID_GONE: handleUidGone(msg.arg1, msg.arg1 != 0); handleUidGone(msg.arg1); if (msg.arg2 != 0) { handleUidDisabled(msg.arg1); } return; case MSG_ON_UID_IDLE: handleUidIdle(msg.arg1, msg.arg1 != 0); handleUidIdle(msg.arg1); if (msg.arg2 != 0) { handleUidDisabled(msg.arg1); } return; } } private void handleUidDisabled(int uid) { for (Listener l : cloneListeners()) { l.removeAlarmsForUid(uid); } } public void handleUidStateChanged(int uid, int procState) { synchronized (mLock) { if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { Loading @@ -940,11 +960,11 @@ public class AppStateTracker { } } public void handleUidGone(int uid, boolean disabled) { public void handleUidGone(int uid) { removeUid(uid, true); } public void handleUidIdle(int uid, boolean disabled) { public void handleUidIdle(int uid) { // Just to avoid excessive memcpy, don't remove from the array in this case. removeUid(uid, false); } Loading
services/core/java/com/android/server/am/ActivityManagerService.java +26 −0 Original line number Diff line number Diff line Loading @@ -19269,6 +19269,32 @@ public class ActivityManagerService extends IActivityManager.Stub return mUserController.shouldConfirmCredentials(userId); } @Override public void noteAlarmFinish(PendingIntent ps, WorkSource workSource, int sourceUid, String tag) { ActivityManagerService.this.noteAlarmFinish((ps != null) ? ps.getTarget() : null, workSource, sourceUid, tag); } @Override public void noteAlarmStart(PendingIntent ps, WorkSource workSource, int sourceUid, String tag) { ActivityManagerService.this.noteAlarmStart((ps != null) ? ps.getTarget() : null, workSource, sourceUid, tag); } @Override public void noteWakeupAlarm(PendingIntent ps, WorkSource workSource, int sourceUid, String sourcePkg, String tag) { ActivityManagerService.this.noteWakeupAlarm((ps != null) ? ps.getTarget() : null, workSource, sourceUid, sourcePkg, tag); } @Override public boolean isAppStartModeDisabled(int uid, String packageName) { return ActivityManagerService.this.isAppStartModeDisabled(uid, packageName); } @Override public int[] getCurrentProfileIds() { return mUserController.getCurrentProfileIds();
services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +27 −4 Original line number Diff line number Diff line Loading @@ -60,11 +60,11 @@ import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.atLeastOnce; import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AlarmManager; import android.app.IActivityManager; import android.app.IAlarmCompleteListener; import android.app.IAlarmListener; import android.app.IUidObserver; import android.app.PendingIntent; import android.app.usage.UsageStatsManagerInternal; import android.content.ContentResolver; Loading Loading @@ -129,6 +129,8 @@ public class AlarmManagerServiceTest { @Mock private AppStandbyInternal mAppStandbyInternal; @Mock private ActivityManagerInternal mActivityManagerInternal; @Mock private AppStateTracker mAppStateTracker; @Mock private AlarmManagerService.ClockReceiver mClockReceiver; Loading Loading @@ -253,7 +255,7 @@ public class AlarmManagerServiceTest { } @Before public final void setUp() throws Exception { public final void setUp() { mMockingSession = mockitoSession() .initMocks(this) .spyStatic(ActivityManager.class) Loading @@ -265,6 +267,8 @@ public class AlarmManagerServiceTest { .strictness(Strictness.WARN) .startMocking(); doReturn(mIActivityManager).when(ActivityManager::getService); doReturn(mActivityManagerInternal).when( () -> LocalServices.getService(ActivityManagerInternal.class)); doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class)); doReturn(mAppStandbyInternal).when( () -> LocalServices.getService(AppStandbyInternal.class)); Loading Loading @@ -294,8 +298,6 @@ public class AlarmManagerServiceTest { assertEquals(mService.mSystemUiUid, SYSTEM_UI_UID); assertEquals(mService.mClockReceiver, mClockReceiver); assertEquals(mService.mWakeLock, mWakeLock); verify(mIActivityManager).registerUidObserver(any(IUidObserver.class), anyInt(), anyInt(), isNull()); // Other boot phases don't matter mService.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY); Loading Loading @@ -791,6 +793,27 @@ public class AlarmManagerServiceTest { assertNull(restrictedAlarms.get(TEST_CALLING_UID)); } @Test public void alarmsRemovedOnAppStartModeDisabled() { final ArgumentCaptor<AppStateTracker.Listener> listenerArgumentCaptor = ArgumentCaptor.forClass(AppStateTracker.Listener.class); verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture()); final AppStateTracker.Listener listener = listenerArgumentCaptor.getValue(); final PendingIntent alarmPi1 = getNewMockPendingIntent(); final PendingIntent alarmPi2 = getNewMockPendingIntent(); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, alarmPi1); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 4, alarmPi2); assertEquals(2, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); when(mActivityManagerInternal.isAppStartModeDisabled(TEST_CALLING_UID, TEST_CALLING_PACKAGE)).thenReturn(true); listener.removeAlarmsForUid(TEST_CALLING_UID); assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID)); } @Test public void sendsTimeTickOnInteractive() { final ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); Loading