diff options
author | Varun Shah <varunshah@google.com> | 2019-03-01 10:36:21 -0800 |
---|---|---|
committer | Varun Shah <varunshah@google.com> | 2019-03-04 19:06:32 +0000 |
commit | 9f58b7c00773159ad6ff3745a06536bbc456777d (patch) | |
tree | 8e0b7d8f8947da28630356251df5f137f77bb4e3 | |
parent | 6efe144d48fdcbde50e4f7eb595175be97f98cd6 (diff) |
Update #registerAppUsageLimitObserver to accept time remaining.
UsageStatsManager#registerAppUsageLimitObserver now accepts the time
remaining in addition to the total time limit.
The API now also uses java.time.Duration instead of long+TimeUnit for
the total time and remaining time.
Bug: 124272203
Test: atest FrameworksServicesTests:AppTimeLimitControllerTests
Test: atest android.app.usage.cts.UsageStatsTest#testObserveUsagePermissionForRegisterObserver
Test: atest android.app.usage.cts.UsageStatsTest#testObserveUsagePermissionForUnregisterObserver
Test: manual (mmma frameworks/base/tests/UsageStatsTest/)
Change-Id: I6f85ca9295cad46e10a30035b67e6210ae5c1886
7 files changed, 105 insertions, 62 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index 81e9322400fe..36476259138f 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -1172,7 +1172,7 @@ package android.app.usage { method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getAppStandbyBucket(String); method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public java.util.Map<java.lang.String,java.lang.Integer> getAppStandbyBuckets(); method public int getUsageSource(); - method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @Nullable android.app.PendingIntent); + method @RequiresPermission(allOf={android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int, @NonNull String[], @NonNull java.time.Duration, @NonNull java.time.Duration, @Nullable android.app.PendingIntent); method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerAppUsageObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent); method @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE) public void registerUsageSessionObserver(int, @NonNull String[], long, @NonNull java.util.concurrent.TimeUnit, long, @NonNull java.util.concurrent.TimeUnit, @NonNull android.app.PendingIntent, @Nullable android.app.PendingIntent); method public void reportUsageStart(@NonNull android.app.Activity, @NonNull String); diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl index b1500c193820..8a59d1dd79a6 100644 --- a/core/java/android/app/usage/IUsageStatsManager.aidl +++ b/core/java/android/app/usage/IUsageStatsManager.aidl @@ -56,7 +56,7 @@ interface IUsageStatsManager { in PendingIntent sessionEndCallbackIntent, String callingPackage); void unregisterUsageSessionObserver(int sessionObserverId, String callingPackage); void registerAppUsageLimitObserver(int observerId, in String[] packages, long timeLimitMs, - in PendingIntent callback, String callingPackage); + long timeRemainingMs, in PendingIntent callback, String callingPackage); void unregisterAppUsageLimitObserver(int observerId, String callingPackage); void reportUsageStart(in IBinder activity, String token, String callingPackage); void reportPastUsageStart(in IBinder activity, String token, long timeAgoMs, diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java index 9c6bd927dd56..fdc249df1871 100644 --- a/core/java/android/app/usage/UsageStatsManager.java +++ b/core/java/android/app/usage/UsageStatsManager.java @@ -35,6 +35,7 @@ import android.util.ArrayMap; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -736,6 +737,23 @@ public final class UsageStatsManager { } /** + * @deprecated use + * {@link #registerAppUsageLimitObserver(int, String[], Duration, Duration, PendingIntent)}. + * + * @removed + * @hide + */ + @Deprecated + @UnsupportedAppUsage + // STOPSHIP b/126917290: remove this method once ag/6591106 is merged and it's not being used. + public void registerAppUsageLimitObserver(int observerId, @NonNull String[] observedEntities, + long timeLimit, @NonNull TimeUnit timeUnit, @Nullable PendingIntent callbackIntent) { + final Duration timeLimitDuration = Duration.ofMillis(timeUnit.toMillis(timeLimit)); + registerAppUsageLimitObserver(observerId, observedEntities, + timeLimitDuration, timeLimitDuration, callbackIntent); + } + + /** * Register a usage limit observer that receives a callback on the provided intent when the * sum of usages of apps and tokens in the provided {@code observedEntities} array exceeds the * {@code timeLimit} specified. The structure of a token is a {@link String} with the reporting @@ -757,19 +775,21 @@ public final class UsageStatsManager { * @see android.content.pm.LauncherApps#getAppUsageLimit * * @param observerId A unique id associated with the group of apps to be monitored. There can - * be multiple groups with common packages and different time limits. + * be multiple groups with common packages and different time limits. * @param observedEntities The list of packages and token to observe for usage time. Cannot be * null and must include at least one package or token. * @param timeLimit The total time the set of apps can be in the foreground before the - * callbackIntent is delivered. Must be at least one minute. Note: a limit of - * 0 can be set to indicate that the user has already exhausted the limit for - * a group, in which case, the given {@code callbackIntent} will be ignored. - * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null. + * {@code callbackIntent} is delivered. Must be at least one minute. + * @param timeRemaining The remaining time the set of apps can be in the foreground before the + * {@code callbackIntent} is delivered. Must be greater than + * {@code timeLimit}. Note: a limit of 0 can be set to indicate that the + * user has already exhausted the limit for a group, in which case, + * the given {@code callbackIntent} will be ignored. * @param callbackIntent The PendingIntent that will be dispatched when the usage limit is * exceeded by the group of apps. The delivered Intent will also contain * the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and * {@link #EXTRA_TIME_USED}. Cannot be {@code null} unless the observer is - * being registered with a {@code timeLimit} of 0. + * being registered with a {@code timeRemaining} of 0. * @throws SecurityException if the caller doesn't have both SUSPEND_APPS and OBSERVE_APP_USAGE * permissions. * @hide @@ -779,10 +799,12 @@ public final class UsageStatsManager { android.Manifest.permission.SUSPEND_APPS, android.Manifest.permission.OBSERVE_APP_USAGE}) public void registerAppUsageLimitObserver(int observerId, @NonNull String[] observedEntities, - long timeLimit, @NonNull TimeUnit timeUnit, @Nullable PendingIntent callbackIntent) { + @NonNull Duration timeLimit, @NonNull Duration timeRemaining, + @Nullable PendingIntent callbackIntent) { try { mService.registerAppUsageLimitObserver(observerId, observedEntities, - timeUnit.toMillis(timeLimit), callbackIntent, mContext.getOpPackageName()); + timeLimit.toMillis(), timeRemaining.toMillis(), callbackIntent, + mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java index 8caa39dfc9e7..1f861716d380 100644 --- a/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java +++ b/services/tests/servicestests/src/com/android/server/usage/AppTimeLimitControllerTests.java @@ -175,9 +175,9 @@ public class AppTimeLimitControllerTests { /** Verify app usage limit observer is added */ @Test public void testAppUsageLimitObserver_AddObserver() { - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1)); - addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_30_MIN); assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID2)); assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1)); } @@ -203,7 +203,7 @@ public class AppTimeLimitControllerTests { /** Verify app usage limit observer is removed */ @Test public void testAppUsageLimitObserver_RemoveObserver() { - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1)); mController.removeAppUsageLimitObserver(UID, OBS_ID1, USER_ID); assertFalse("Observer wasn't removed", hasAppUsageLimitObserver(UID, OBS_ID1)); @@ -290,9 +290,9 @@ public class AppTimeLimitControllerTests { /** Re-adding an observer should result in only one copy */ @Test public void testAppUsageLimitObserver_ObserverReAdd() { - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1)); - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN, TIME_10_MIN); assertTrue("Observer wasn't added", getAppUsageLimitObserver(UID, OBS_ID1).getTimeLimitMs() == TIME_10_MIN); mController.removeAppUsageLimitObserver(UID, OBS_ID1, USER_ID); @@ -304,7 +304,7 @@ public class AppTimeLimitControllerTests { public void testAllObservers_ExclusiveObserverIds() { addAppUsageObserver(OBS_ID1, GROUP1, TIME_10_MIN); addUsageSessionObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_1_MIN); - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_10_MIN, TIME_10_MIN); assertTrue("Observer wasn't added", hasAppUsageObserver(UID, OBS_ID1)); assertTrue("Observer wasn't added", hasUsageSessionObserver(UID, OBS_ID1)); assertTrue("Observer wasn't added", hasAppUsageLimitObserver(UID, OBS_ID1)); @@ -396,7 +396,7 @@ public class AppTimeLimitControllerTests { @Test public void testAppUsageLimitObserver_Accumulation() throws Exception { setTime(0L); - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); startUsage(PKG_SOC1); // Add 10 mins setTime(TIME_10_MIN); @@ -456,7 +456,7 @@ public class AppTimeLimitControllerTests { @Test public void testAppUsageLimitObserver_TimeoutOtherApp() throws Exception { setTime(0L); - addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L); + addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L, 4_000L); startUsage(PKG_SOC2); assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS)); setTime(6_000L); @@ -498,7 +498,7 @@ public class AppTimeLimitControllerTests { @Test public void testAppUsageLimitObserver_Timeout() throws Exception { setTime(0L); - addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L); + addAppUsageLimitObserver(OBS_ID1, GROUP1, 4_000L, 4_000L); startUsage(PKG_SOC1); setTime(6_000L); assertTrue(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS)); @@ -551,7 +551,7 @@ public class AppTimeLimitControllerTests { setTime(TIME_10_MIN); startUsage(PKG_GAME1); setTime(TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID2, GROUP_GAME, TIME_30_MIN, TIME_30_MIN); setTime(TIME_30_MIN + TIME_10_MIN); stopUsage(PKG_GAME1); assertFalse(mLimitReachedLatch.await(1_000L, TimeUnit.MILLISECONDS)); @@ -612,7 +612,7 @@ public class AppTimeLimitControllerTests { startUsage(PKG_SOC1); setTime(TIME_10_MIN); // 10 second time limit - addAppUsageLimitObserver(OBS_ID1, GROUP_SOC, 10_000L); + addAppUsageLimitObserver(OBS_ID1, GROUP_SOC, 10_000L, 10_000L); setTime(TIME_10_MIN + 5_000L); // Shouldn't call back in 6 seconds assertFalse(mLimitReachedLatch.await(6_000L, TimeUnit.MILLISECONDS)); @@ -692,23 +692,23 @@ public class AppTimeLimitControllerTests { public void testAppUsageLimitObserver_MaxObserverLimit() throws Exception { boolean receivedException = false; int ANOTHER_UID = UID + 1; - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID2, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID3, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID4, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID6, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID7, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID8, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID9, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID10, GROUP1, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID2, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID3, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID4, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID6, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID7, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID8, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID9, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID10, GROUP1, TIME_30_MIN, TIME_30_MIN); // Readding an observer should not cause an IllegalStateException - addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID5, GROUP1, TIME_30_MIN, TIME_30_MIN); // Adding an observer for a different uid shouldn't cause an IllegalStateException mController.addAppUsageLimitObserver( - ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, null, USER_ID); + ANOTHER_UID, OBS_ID11, GROUP1, TIME_30_MIN, TIME_30_MIN, null, USER_ID); try { - addAppUsageLimitObserver(OBS_ID11, GROUP1, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID11, GROUP1, TIME_30_MIN, TIME_30_MIN); } catch (IllegalStateException ise) { receivedException = true; } @@ -748,9 +748,9 @@ public class AppTimeLimitControllerTests { public void testAppUsageLimitObserver_MinimumTimeLimit() throws Exception { boolean receivedException = false; // adding an observer with a one minute time limit should not cause an exception - addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT); + addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT, MIN_TIME_LIMIT); try { - addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1); + addAppUsageLimitObserver(OBS_ID1, GROUP1, MIN_TIME_LIMIT - 1, MIN_TIME_LIMIT - 1); } catch (IllegalArgumentException iae) { receivedException = true; } @@ -807,7 +807,7 @@ public class AppTimeLimitControllerTests { @Test public void testAppUsageLimitObserver_ConcurrentUsage() throws Exception { setTime(0L); - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); AppTimeLimitController.UsageGroup group = getAppUsageLimitObserver(UID, OBS_ID1); startUsage(PKG_SOC1); // Add 10 mins @@ -967,7 +967,7 @@ public class AppTimeLimitControllerTests { /** Verify app usage limit observer added correctly reports its total usage limit */ @Test public void testAppUsageLimitObserver_GetTotalUsageLimit() { - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); AppTimeLimitController.AppUsageLimitGroup group = getAppUsageLimitObserver(UID, OBS_ID1); assertNotNull("Observer wasn't added", group); assertEquals("Observer didn't correctly report total usage limit", @@ -978,7 +978,7 @@ public class AppTimeLimitControllerTests { @Test public void testAppUsageLimitObserver_GetUsageRemaining() { setTime(0L); - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); startUsage(PKG_SOC1); setTime(TIME_10_MIN); stopUsage(PKG_SOC1); @@ -993,8 +993,8 @@ public class AppTimeLimitControllerTests { */ @Test public void testAppUsageLimitObserver_GetAppUsageLimit() { - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, TIME_10_MIN); UsageStatsManagerInternal.AppUsageLimitData group = getAppUsageLimit(PKG_SOC1); assertEquals("Observer with the smallest usage limit remaining wasn't returned", TIME_10_MIN, group.getTotalUsageLimit()); @@ -1006,8 +1006,8 @@ public class AppTimeLimitControllerTests { @Test public void testAppUsageLimitObserver_GetAppUsageLimitUsed() { setTime(0L); - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, TIME_10_MIN); startUsage(PKG_GAME1); setTime(TIME_10_MIN * 2 + TIME_1_MIN); stopUsage(PKG_GAME1); @@ -1024,8 +1024,8 @@ public class AppTimeLimitControllerTests { @Test public void testAppUsageLimitObserver_GetAppUsageLimitAllUsed() { setTime(0L); - addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN); - addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN); + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_30_MIN, TIME_30_MIN); + addAppUsageLimitObserver(OBS_ID2, GROUP_SOC, TIME_10_MIN, TIME_10_MIN); startUsage(PKG_SOC1); setTime(TIME_10_MIN); stopUsage(PKG_SOC1); @@ -1035,10 +1035,21 @@ public class AppTimeLimitControllerTests { 0L, group.getUsageRemaining()); } + /** Verify that a limit of 0 is not allowed. */ + @Test + public void testAppUsageLimitObserver_ZeroTimeLimitIsNotAllowed() { + try { + addAppUsageLimitObserver(OBS_ID1, GROUP1, 0, 0); + fail("timeLimit of 0 should not be allowed."); + } catch (IllegalArgumentException expected) { + // Exception expected. + } + } + /** Verify that a limit of 0 is allowed for the special case of re-registering an observer. */ @Test - public void testAppUsageLimitObserver_ZeroTimeLimitIsAllowed() { - addAppUsageLimitObserver(OBS_ID1, GROUP1, 0); + public void testAppUsageLimitObserver_ZeroTimeRemainingIsAllowed() { + addAppUsageLimitObserver(OBS_ID1, GROUP1, TIME_1_MIN, 0); AppTimeLimitController.AppUsageLimitGroup group = getAppUsageLimitObserver(UID, OBS_ID1); assertNotNull("Observer wasn't added", group); assertEquals("Usage remaining was not 0.", 0, group.getUsageRemaining()); @@ -1066,8 +1077,10 @@ public class AppTimeLimitControllerTests { null, null, USER_ID); } - private void addAppUsageLimitObserver(int observerId, String[] packages, long timeLimit) { - mController.addAppUsageLimitObserver(UID, observerId, packages, timeLimit, null, USER_ID); + private void addAppUsageLimitObserver(int observerId, String[] packages, long timeLimit, + long timeRemaining) { + mController.addAppUsageLimitObserver(UID, observerId, packages, timeLimit, timeRemaining, + null, USER_ID); } /** Is there still an app usage observer by that id */ diff --git a/services/usage/java/com/android/server/usage/AppTimeLimitController.java b/services/usage/java/com/android/server/usage/AppTimeLimitController.java index 731cbf42eca7..f3d63873dc4b 100644 --- a/services/usage/java/com/android/server/usage/AppTimeLimitController.java +++ b/services/usage/java/com/android/server/usage/AppTimeLimitController.java @@ -511,8 +511,10 @@ public class AppTimeLimitController { class AppUsageLimitGroup extends UsageGroup { public AppUsageLimitGroup(UserData user, ObserverAppData observerApp, int observerId, - String[] observed, long timeLimitMs, PendingIntent limitReachedCallback) { + String[] observed, long timeLimitMs, long timeRemainingMs, + PendingIntent limitReachedCallback) { super(user, observerApp, observerId, observed, timeLimitMs, limitReachedCallback); + mUsageTimeMs = timeLimitMs - timeRemainingMs; } @Override @@ -839,9 +841,9 @@ public class AppTimeLimitController { * Existing app usage limit observer with the same observerId will be removed. */ public void addAppUsageLimitObserver(int requestingUid, int observerId, String[] observed, - long timeLimit, PendingIntent callbackIntent, @UserIdInt int userId) { - // Allow the special case of the limit being 0, but with no callback. - if (timeLimit != 0L && timeLimit < getMinTimeLimit()) { + long timeLimit, long timeRemaining, PendingIntent callbackIntent, + @UserIdInt int userId) { + if (timeLimit < getMinTimeLimit()) { throw new IllegalArgumentException("Time limit must be >= " + getMinTimeLimit()); } synchronized (mLock) { @@ -859,7 +861,7 @@ public class AppTimeLimitController { "Too many app usage observers added by uid " + requestingUid); } group = new AppUsageLimitGroup(user, observerApp, observerId, observed, timeLimit, - timeLimit == 0L ? null : callbackIntent); + timeRemaining, timeRemaining == 0L ? null : callbackIntent); observerApp.appUsageLimitGroups.append(observerId, group); if (DEBUG) { diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index ebb0210cb553..4c8a84a6e6cb 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -1399,7 +1399,8 @@ public class UsageStatsService extends SystemService implements @Override public void registerAppUsageLimitObserver(int observerId, String[] packages, - long timeLimitMs, PendingIntent callbackIntent, String callingPackage) { + long timeLimitMs, long timeRemainingMs, PendingIntent callbackIntent, + String callingPackage) { if (!hasPermissions(callingPackage, Manifest.permission.SUSPEND_APPS, Manifest.permission.OBSERVE_APP_USAGE)) { throw new SecurityException("Caller doesn't have both SUSPEND_APPS and " @@ -1409,7 +1410,11 @@ public class UsageStatsService extends SystemService implements if (packages == null || packages.length == 0) { throw new IllegalArgumentException("Must specify at least one package"); } - if (callbackIntent == null && timeLimitMs != 0L) { + if (timeRemainingMs > timeLimitMs) { + throw new IllegalArgumentException( + "Remaining time can't be greater than total time."); + } + if (callbackIntent == null && timeRemainingMs != 0L) { throw new NullPointerException("callbackIntent can't be null"); } final int callingUid = Binder.getCallingUid(); @@ -1417,7 +1422,7 @@ public class UsageStatsService extends SystemService implements final long token = Binder.clearCallingIdentity(); try { UsageStatsService.this.registerAppUsageLimitObserver(callingUid, observerId, - packages, timeLimitMs, callbackIntent, userId); + packages, timeLimitMs, timeRemainingMs, callbackIntent, userId); } finally { Binder.restoreCallingIdentity(token); } @@ -1545,9 +1550,9 @@ public class UsageStatsService extends SystemService implements } void registerAppUsageLimitObserver(int callingUid, int observerId, String[] packages, - long timeLimitMs, PendingIntent callbackIntent, int userId) { - mAppTimeLimit.addAppUsageLimitObserver(callingUid, observerId, packages, timeLimitMs, - callbackIntent, userId); + long timeLimitMs, long timeRemainingMs, PendingIntent callbackIntent, int userId) { + mAppTimeLimit.addAppUsageLimitObserver(callingUid, observerId, packages, + timeLimitMs, timeRemainingMs, callbackIntent, userId); } void unregisterAppUsageLimitObserver(int callingUid, int observerId, int userId) { diff --git a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java index 0105893adf9e..adcd11a08bff 100644 --- a/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java +++ b/tests/UsageStatsTest/src/com/android/tests/usagestats/UsageStatsActivity.java @@ -41,6 +41,7 @@ import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; +import java.time.Duration; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -196,8 +197,8 @@ public class UsageStatsActivity extends ListActivity { intent.setPackage(getPackageName()); intent.putExtra(EXTRA_KEY_TIMEOUT, true); mUsageStatsManager.registerAppUsageLimitObserver(1, packages, - 60, TimeUnit.SECONDS, PendingIntent.getActivity(UsageStatsActivity.this, - 1, intent, 0)); + Duration.ofSeconds(60), Duration.ofSeconds(60), + PendingIntent.getActivity(UsageStatsActivity.this, 1, intent, 0)); } } }); |