blob: 9c6bd927dd56c8f9442baf7b41b961e0577553be [file] [log] [blame]
Adam Lesinski0debc9a2014-07-16 19:09:13 -07001/**
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy
6 * of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16
17package android.app.usage;
18
Amith Yamasaniafbccb72017-11-27 10:44:24 -080019import android.annotation.IntDef;
Amith Yamasanibc813eb2018-03-20 19:37:46 -070020import android.annotation.NonNull;
Michael Wachenschwanz641e3382018-10-23 23:21:48 -070021import android.annotation.Nullable;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060022import android.annotation.RequiresPermission;
Amith Yamasaniaf575b92015-05-29 15:35:26 -070023import android.annotation.SystemApi;
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060024import android.annotation.SystemService;
Michael Wachenschwanz0b4ab1f2019-01-07 13:59:10 -080025import android.annotation.TestApi;
Mathew Inwood61e8ae62018-08-14 14:17:44 +010026import android.annotation.UnsupportedAppUsage;
Michael Wachenschwanz36778522018-11-12 11:06:19 -080027import android.app.Activity;
Amith Yamasani62ec27e92018-03-11 14:42:06 -070028import android.app.PendingIntent;
Adam Lesinski0debc9a2014-07-16 19:09:13 -070029import android.content.Context;
Adam Lesinski35168002014-07-21 15:25:30 -070030import android.content.pm.ParceledListSlice;
Mathew Inwood8c854f82018-09-14 12:35:36 +010031import android.os.Build;
Adam Lesinski0debc9a2014-07-16 19:09:13 -070032import android.os.RemoteException;
Amith Yamasanicf768722015-04-23 20:36:41 -070033import android.os.UserHandle;
Adam Lesinski35168002014-07-21 15:25:30 -070034import android.util.ArrayMap;
Adam Lesinski0debc9a2014-07-16 19:09:13 -070035
Amith Yamasaniafbccb72017-11-27 10:44:24 -080036import java.lang.annotation.Retention;
37import java.lang.annotation.RetentionPolicy;
Suprabh Shukla868bde22018-02-20 20:59:52 -080038import java.util.ArrayList;
Adam Lesinski35168002014-07-21 15:25:30 -070039import java.util.Collections;
40import java.util.List;
Adam Lesinskicc562a82014-08-27 11:52:52 -070041import java.util.Map;
Amith Yamasani62ec27e92018-03-11 14:42:06 -070042import java.util.concurrent.TimeUnit;
Adam Lesinski35168002014-07-21 15:25:30 -070043
44/**
45 * Provides access to device usage history and statistics. Usage data is aggregated into
46 * time intervals: days, weeks, months, and years.
47 * <p />
48 * When requesting usage data since a particular time, the request might look something like this:
49 * <pre>
50 * PAST REQUEST_TIME TODAY FUTURE
51 * ————————————————————————————||———————————————————————————¦-----------------------|
52 * YEAR || ¦ |
53 * ————————————————————————————||———————————————————————————¦-----------------------|
54 * MONTH | || MONTH ¦ |
55 * ——————————————————|—————————||———————————————————————————¦-----------------------|
56 * | WEEK | WEEK|| | WEEK | WE¦EK | WEEK |
57 * ————————————————————————————||———————————————————|———————¦-----------------------|
58 * || |DAY|DAY|DAY|DAY¦DAY|DAY|DAY|DAY|DAY|DAY|
59 * ————————————————————————————||———————————————————————————¦-----------------------|
60 * </pre>
61 * A request for data in the middle of a time interval will include that interval.
62 * <p/>
Suprabh Shukla217ccda2018-02-23 17:57:12 -080063 * <b>NOTE:</b> Most methods on this API require the permission
64 * android.permission.PACKAGE_USAGE_STATS. However, declaring the permission implies intention to
65 * use the API and the user of the device still needs to grant permission through the Settings
66 * application.
67 * See {@link android.provider.Settings#ACTION_USAGE_ACCESS_SETTINGS}.
68 * Methods which only return the information for the calling package do not require this permission.
69 * E.g. {@link #getAppStandbyBucket()} and {@link #queryEventsForSelf(long, long)}.
Adam Lesinski35168002014-07-21 15:25:30 -070070 */
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -060071@SystemService(Context.USAGE_STATS_SERVICE)
Adam Lesinski0debc9a2014-07-16 19:09:13 -070072public final class UsageStatsManager {
Adam Lesinski0debc9a2014-07-16 19:09:13 -070073
74 /**
Adam Lesinski35168002014-07-21 15:25:30 -070075 * An interval type that spans a day. See {@link #queryUsageStats(int, long, long)}.
Adam Lesinski0debc9a2014-07-16 19:09:13 -070076 */
Adam Lesinski35168002014-07-21 15:25:30 -070077 public static final int INTERVAL_DAILY = 0;
Adam Lesinski0debc9a2014-07-16 19:09:13 -070078
79 /**
Adam Lesinski35168002014-07-21 15:25:30 -070080 * An interval type that spans a week. See {@link #queryUsageStats(int, long, long)}.
Adam Lesinski0debc9a2014-07-16 19:09:13 -070081 */
Adam Lesinski35168002014-07-21 15:25:30 -070082 public static final int INTERVAL_WEEKLY = 1;
Adam Lesinski0debc9a2014-07-16 19:09:13 -070083
84 /**
Adam Lesinski35168002014-07-21 15:25:30 -070085 * An interval type that spans a month. See {@link #queryUsageStats(int, long, long)}.
Adam Lesinski0debc9a2014-07-16 19:09:13 -070086 */
Adam Lesinski35168002014-07-21 15:25:30 -070087 public static final int INTERVAL_MONTHLY = 2;
Adam Lesinski0debc9a2014-07-16 19:09:13 -070088
89 /**
Adam Lesinski35168002014-07-21 15:25:30 -070090 * An interval type that spans a year. See {@link #queryUsageStats(int, long, long)}.
91 */
92 public static final int INTERVAL_YEARLY = 3;
93
94 /**
95 * An interval type that will use the best fit interval for the given time range.
96 * See {@link #queryUsageStats(int, long, long)}.
97 */
98 public static final int INTERVAL_BEST = 4;
99
100 /**
101 * The number of available intervals. Does not include {@link #INTERVAL_BEST}, since it
102 * is a pseudo interval (it actually selects a real interval).
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700103 * {@hide}
104 */
Adam Lesinski35168002014-07-21 15:25:30 -0700105 public static final int INTERVAL_COUNT = 4;
106
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800107
108 /**
109 * The app is whitelisted for some reason and the bucket cannot be changed.
110 * {@hide}
111 */
112 @SystemApi
113 public static final int STANDBY_BUCKET_EXEMPTED = 5;
114
115 /**
Amith Yamasani853e53f2018-03-16 16:08:57 -0700116 * The app was used very recently, currently in use or likely to be used very soon. Standby
117 * bucket values that are &le; {@link #STANDBY_BUCKET_ACTIVE} will not be throttled by the
118 * system while they are in this bucket. Buckets &gt; {@link #STANDBY_BUCKET_ACTIVE} will most
119 * likely be restricted in some way. For instance, jobs and alarms may be deferred.
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800120 * @see #getAppStandbyBucket()
121 */
122 public static final int STANDBY_BUCKET_ACTIVE = 10;
123
124 /**
Amith Yamasani853e53f2018-03-16 16:08:57 -0700125 * The app was used recently and/or likely to be used in the next few hours. Restrictions will
126 * apply to these apps, such as deferral of jobs and alarms.
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800127 * @see #getAppStandbyBucket()
128 */
129 public static final int STANDBY_BUCKET_WORKING_SET = 20;
130
131 /**
132 * The app was used in the last few days and/or likely to be used in the next few days.
Amith Yamasani853e53f2018-03-16 16:08:57 -0700133 * Restrictions will apply to these apps, such as deferral of jobs and alarms. The delays may be
134 * greater than for apps in higher buckets (lower bucket value). Bucket values &gt;
135 * {@link #STANDBY_BUCKET_FREQUENT} may additionally have network access limited.
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800136 * @see #getAppStandbyBucket()
137 */
138 public static final int STANDBY_BUCKET_FREQUENT = 30;
139
140 /**
141 * The app has not be used for several days and/or is unlikely to be used for several days.
Amith Yamasani853e53f2018-03-16 16:08:57 -0700142 * Apps in this bucket will have the most restrictions, including network restrictions, except
143 * during certain short periods (at a minimum, once a day) when they are allowed to execute
144 * jobs, access the network, etc.
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800145 * @see #getAppStandbyBucket()
146 */
147 public static final int STANDBY_BUCKET_RARE = 40;
148
149 /**
150 * The app has never been used.
151 * {@hide}
152 */
153 @SystemApi
154 public static final int STANDBY_BUCKET_NEVER = 50;
155
Amith Yamasani119be9a2018-02-18 22:23:00 -0800156 /** @hide */
157 public static final int REASON_MAIN_MASK = 0xFF00;
158 /** @hide */
159 public static final int REASON_MAIN_DEFAULT = 0x0100;
160 /** @hide */
161 public static final int REASON_MAIN_TIMEOUT = 0x0200;
162 /** @hide */
163 public static final int REASON_MAIN_USAGE = 0x0300;
164 /** @hide */
165 public static final int REASON_MAIN_FORCED = 0x0400;
166 /** @hide */
167 public static final int REASON_MAIN_PREDICTED = 0x0500;
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800168
Amith Yamasani119be9a2018-02-18 22:23:00 -0800169 /** @hide */
170 public static final int REASON_SUB_MASK = 0x00FF;
171 /** @hide */
172 public static final int REASON_SUB_USAGE_SYSTEM_INTERACTION = 0x0001;
173 /** @hide */
174 public static final int REASON_SUB_USAGE_NOTIFICATION_SEEN = 0x0002;
175 /** @hide */
176 public static final int REASON_SUB_USAGE_USER_INTERACTION = 0x0003;
177 /** @hide */
178 public static final int REASON_SUB_USAGE_MOVE_TO_FOREGROUND = 0x0004;
179 /** @hide */
180 public static final int REASON_SUB_USAGE_MOVE_TO_BACKGROUND = 0x0005;
181 /** @hide */
182 public static final int REASON_SUB_USAGE_SYSTEM_UPDATE = 0x0006;
183 /** @hide */
184 public static final int REASON_SUB_USAGE_ACTIVE_TIMEOUT = 0x0007;
185 /** @hide */
186 public static final int REASON_SUB_USAGE_SYNC_ADAPTER = 0x0008;
Amith Yamasani80c4be82018-03-26 10:54:04 -0700187 /** @hide */
188 public static final int REASON_SUB_USAGE_SLICE_PINNED = 0x0009;
189 /** @hide */
190 public static final int REASON_SUB_USAGE_SLICE_PINNED_PRIV = 0x000A;
Makoto Onuki75ad2492018-03-28 14:42:42 -0700191 /** @hide */
Makoto Onukid5f25d22018-05-22 16:02:17 -0700192 public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE = 0x000B;
193 /** @hide */
194 public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE = 0x000C;
195 /** @hide */
196 public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000D;
Hui Yue361a232018-10-04 15:05:21 -0700197 /** @hide */
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700198 public static final int REASON_SUB_PREDICTED_RESTORED = 0x0001;
199
Makoto Onuki75ad2492018-03-28 14:42:42 -0700200
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700201 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700202 @IntDef(flag = false, prefix = { "STANDBY_BUCKET_" }, value = {
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800203 STANDBY_BUCKET_EXEMPTED,
204 STANDBY_BUCKET_ACTIVE,
205 STANDBY_BUCKET_WORKING_SET,
206 STANDBY_BUCKET_FREQUENT,
207 STANDBY_BUCKET_RARE,
208 STANDBY_BUCKET_NEVER,
209 })
210 @Retention(RetentionPolicy.SOURCE)
211 public @interface StandbyBuckets {}
212
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700213 /**
214 * Observer id of the registered observer for the group of packages that reached the usage
215 * time limit. Included as an extra in the PendingIntent that was registered.
216 * @hide
217 */
218 @SystemApi
219 public static final String EXTRA_OBSERVER_ID = "android.app.usage.extra.OBSERVER_ID";
220
221 /**
222 * Original time limit in milliseconds specified by the registered observer for the group of
223 * packages that reached the usage time limit. Included as an extra in the PendingIntent that
224 * was registered.
225 * @hide
226 */
227 @SystemApi
228 public static final String EXTRA_TIME_LIMIT = "android.app.usage.extra.TIME_LIMIT";
229
230 /**
231 * Actual usage time in milliseconds for the group of packages that reached the specified time
232 * limit. Included as an extra in the PendingIntent that was registered.
233 * @hide
234 */
235 @SystemApi
236 public static final String EXTRA_TIME_USED = "android.app.usage.extra.TIME_USED";
237
Michael Wachenschwanz0b4ab1f2019-01-07 13:59:10 -0800238
239 /**
240 * App usage observers will consider the task root package the source of usage.
241 * @hide
242 */
243 @SystemApi
244 public static final int USAGE_SOURCE_TASK_ROOT_ACTIVITY = 1;
245
246 /**
247 * App usage observers will consider the visible activity's package the source of usage.
248 * @hide
249 */
250 @SystemApi
251 public static final int USAGE_SOURCE_CURRENT_ACTIVITY = 2;
252
253 /** @hide */
254 @IntDef(prefix = { "USAGE_SOURCE_" }, value = {
255 USAGE_SOURCE_TASK_ROOT_ACTIVITY,
256 USAGE_SOURCE_CURRENT_ACTIVITY,
257 })
258 @Retention(RetentionPolicy.SOURCE)
259 public @interface UsageSource {}
260
Mathew Inwood31755f92018-12-20 13:53:36 +0000261 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Adam Lesinski35168002014-07-21 15:25:30 -0700262 private static final UsageEvents sEmptyResults = new UsageEvents();
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700263
Mathew Inwood8c854f82018-09-14 12:35:36 +0100264 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700265 private final Context mContext;
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100266 @UnsupportedAppUsage
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700267 private final IUsageStatsManager mService;
268
269 /**
270 * {@hide}
271 */
272 public UsageStatsManager(Context context, IUsageStatsManager service) {
273 mContext = context;
274 mService = service;
275 }
276
Adam Lesinski35168002014-07-21 15:25:30 -0700277 /**
278 * Gets application usage stats for the given time range, aggregated by the specified interval.
279 * <p>The returned list will contain a {@link UsageStats} object for each package that
280 * has data for an interval that is a subset of the time range given. To illustrate:</p>
281 * <pre>
282 * intervalType = INTERVAL_YEARLY
283 * beginTime = 2013
284 * endTime = 2015 (exclusive)
285 *
286 * Results:
287 * 2013 - com.example.alpha
288 * 2013 - com.example.beta
289 * 2014 - com.example.alpha
290 * 2014 - com.example.beta
291 * 2014 - com.example.charlie
292 * </pre>
293 *
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800294 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
295 *
Adam Lesinski35168002014-07-21 15:25:30 -0700296 * @param intervalType The time interval by which the stats are aggregated.
297 * @param beginTime The inclusive beginning of the range of stats to include in the results.
298 * @param endTime The exclusive end of the range of stats to include in the results.
Esteban Talaverafa962312017-10-09 14:58:28 +0100299 * @return A list of {@link UsageStats}
Adam Lesinski35168002014-07-21 15:25:30 -0700300 *
301 * @see #INTERVAL_DAILY
302 * @see #INTERVAL_WEEKLY
303 * @see #INTERVAL_MONTHLY
304 * @see #INTERVAL_YEARLY
305 * @see #INTERVAL_BEST
306 */
Adam Lesinski35168002014-07-21 15:25:30 -0700307 public List<UsageStats> queryUsageStats(int intervalType, long beginTime, long endTime) {
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700308 try {
Adam Lesinski7f61e962014-09-02 16:43:52 -0700309 @SuppressWarnings("unchecked")
Adam Lesinski35168002014-07-21 15:25:30 -0700310 ParceledListSlice<UsageStats> slice = mService.queryUsageStats(intervalType, beginTime,
311 endTime, mContext.getOpPackageName());
312 if (slice != null) {
313 return slice.getList();
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700314 }
Adam Lesinski35168002014-07-21 15:25:30 -0700315 } catch (RemoteException e) {
Esteban Talaverafa962312017-10-09 14:58:28 +0100316 // fallthrough and return the empty list.
Adam Lesinski35168002014-07-21 15:25:30 -0700317 }
Adam Lesinski7f61e962014-09-02 16:43:52 -0700318 return Collections.emptyList();
319 }
320
321 /**
322 * Gets the hardware configurations the device was in for the given time range, aggregated by
323 * the specified interval. The results are ordered as in
324 * {@link #queryUsageStats(int, long, long)}.
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800325 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
Adam Lesinski7f61e962014-09-02 16:43:52 -0700326 *
327 * @param intervalType The time interval by which the stats are aggregated.
328 * @param beginTime The inclusive beginning of the range of stats to include in the results.
329 * @param endTime The exclusive end of the range of stats to include in the results.
Esteban Talaverafa962312017-10-09 14:58:28 +0100330 * @return A list of {@link ConfigurationStats}
Adam Lesinski7f61e962014-09-02 16:43:52 -0700331 */
332 public List<ConfigurationStats> queryConfigurations(int intervalType, long beginTime,
333 long endTime) {
334 try {
335 @SuppressWarnings("unchecked")
336 ParceledListSlice<ConfigurationStats> slice = mService.queryConfigurationStats(
337 intervalType, beginTime, endTime, mContext.getOpPackageName());
338 if (slice != null) {
339 return slice.getList();
340 }
341 } catch (RemoteException e) {
342 // fallthrough and return the empty list.
343 }
344 return Collections.emptyList();
Adam Lesinski35168002014-07-21 15:25:30 -0700345 }
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700346
Adam Lesinski35168002014-07-21 15:25:30 -0700347 /**
Dianne Hackbornced54392018-02-26 13:07:42 -0800348 * Gets aggregated event stats for the given time range, aggregated by the specified interval.
349 * <p>The returned list will contain a {@link EventStats} object for each event type that
350 * is being aggregated and has data for an interval that is a subset of the time range given.
351 *
352 * <p>The current event types that will be aggregated here are:</p>
353 * <ul>
354 * <li>{@link UsageEvents.Event#SCREEN_INTERACTIVE}</li>
355 * <li>{@link UsageEvents.Event#SCREEN_NON_INTERACTIVE}</li>
Dianne Hackborn3378aa92018-03-30 17:43:49 -0700356 * <li>{@link UsageEvents.Event#KEYGUARD_SHOWN}</li>
357 * <li>{@link UsageEvents.Event#KEYGUARD_HIDDEN}</li>
Dianne Hackbornced54392018-02-26 13:07:42 -0800358 * </ul>
359 *
360 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
361 *
362 * @param intervalType The time interval by which the stats are aggregated.
363 * @param beginTime The inclusive beginning of the range of stats to include in the results.
364 * @param endTime The exclusive end of the range of stats to include in the results.
365 * @return A list of {@link EventStats}
366 *
367 * @see #INTERVAL_DAILY
368 * @see #INTERVAL_WEEKLY
369 * @see #INTERVAL_MONTHLY
370 * @see #INTERVAL_YEARLY
371 * @see #INTERVAL_BEST
372 */
373 public List<EventStats> queryEventStats(int intervalType, long beginTime, long endTime) {
374 try {
375 @SuppressWarnings("unchecked")
376 ParceledListSlice<EventStats> slice = mService.queryEventStats(intervalType, beginTime,
377 endTime, mContext.getOpPackageName());
378 if (slice != null) {
379 return slice.getList();
380 }
381 } catch (RemoteException e) {
382 // fallthrough and return the empty list.
383 }
384 return Collections.emptyList();
385 }
386
387 /**
Adam Lesinski35168002014-07-21 15:25:30 -0700388 * Query for events in the given time range. Events are only kept by the system for a few
389 * days.
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800390 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
Adam Lesinski35168002014-07-21 15:25:30 -0700391 *
392 * @param beginTime The inclusive beginning of the range of events to include in the results.
393 * @param endTime The exclusive end of the range of events to include in the results.
394 * @return A {@link UsageEvents}.
395 */
Adam Lesinski35168002014-07-21 15:25:30 -0700396 public UsageEvents queryEvents(long beginTime, long endTime) {
397 try {
398 UsageEvents iter = mService.queryEvents(beginTime, endTime,
399 mContext.getOpPackageName());
400 if (iter != null) {
401 return iter;
402 }
403 } catch (RemoteException e) {
Esteban Talaverafa962312017-10-09 14:58:28 +0100404 // fallthrough and return empty result.
Adam Lesinski35168002014-07-21 15:25:30 -0700405 }
406 return sEmptyResults;
407 }
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700408
Adam Lesinski35168002014-07-21 15:25:30 -0700409 /**
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800410 * Like {@link #queryEvents(long, long)}, but only returns events for the calling package.
411 *
412 * @param beginTime The inclusive beginning of the range of events to include in the results.
413 * @param endTime The exclusive end of the range of events to include in the results.
414 * @return A {@link UsageEvents} object.
415 *
416 * @see #queryEvents(long, long)
417 */
418 public UsageEvents queryEventsForSelf(long beginTime, long endTime) {
419 try {
420 final UsageEvents events = mService.queryEventsForPackage(beginTime, endTime,
421 mContext.getOpPackageName());
422 if (events != null) {
423 return events;
424 }
425 } catch (RemoteException e) {
426 // fallthrough
427 }
428 return sEmptyResults;
429 }
430
431 /**
Adam Lesinski35168002014-07-21 15:25:30 -0700432 * A convenience method that queries for all stats in the given range (using the best interval
433 * for that range), merges the resulting data, and keys it by package name.
434 * See {@link #queryUsageStats(int, long, long)}.
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800435 * <p> The caller must have {@link android.Manifest.permission#PACKAGE_USAGE_STATS} </p>
Adam Lesinski35168002014-07-21 15:25:30 -0700436 *
437 * @param beginTime The inclusive beginning of the range of stats to include in the results.
438 * @param endTime The exclusive end of the range of stats to include in the results.
Esteban Talaverafa962312017-10-09 14:58:28 +0100439 * @return A {@link java.util.Map} keyed by package name
Adam Lesinski35168002014-07-21 15:25:30 -0700440 */
Adam Lesinskicc562a82014-08-27 11:52:52 -0700441 public Map<String, UsageStats> queryAndAggregateUsageStats(long beginTime, long endTime) {
Adam Lesinski35168002014-07-21 15:25:30 -0700442 List<UsageStats> stats = queryUsageStats(INTERVAL_BEST, beginTime, endTime);
443 if (stats.isEmpty()) {
Adam Lesinskicc562a82014-08-27 11:52:52 -0700444 return Collections.emptyMap();
Adam Lesinski35168002014-07-21 15:25:30 -0700445 }
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700446
Adam Lesinski35168002014-07-21 15:25:30 -0700447 ArrayMap<String, UsageStats> aggregatedStats = new ArrayMap<>();
448 final int statCount = stats.size();
449 for (int i = 0; i < statCount; i++) {
450 UsageStats newStat = stats.get(i);
451 UsageStats existingStat = aggregatedStats.get(newStat.getPackageName());
452 if (existingStat == null) {
453 aggregatedStats.put(newStat.mPackageName, newStat);
454 } else {
455 existingStat.add(newStat);
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700456 }
457 }
458 return aggregatedStats;
459 }
Amith Yamasanicf768722015-04-23 20:36:41 -0700460
461 /**
Amith Yamasanie5f33042015-05-08 13:20:22 -0700462 * Returns whether the specified app is currently considered inactive. This will be true if the
Amith Yamasanicf768722015-04-23 20:36:41 -0700463 * app hasn't been used directly or indirectly for a period of time defined by the system. This
464 * could be of the order of several hours or days.
465 * @param packageName The package name of the app to query
Amith Yamasanie5f33042015-05-08 13:20:22 -0700466 * @return whether the app is currently considered inactive
Amith Yamasanicf768722015-04-23 20:36:41 -0700467 */
Amith Yamasanie5f33042015-05-08 13:20:22 -0700468 public boolean isAppInactive(String packageName) {
Amith Yamasanicf768722015-04-23 20:36:41 -0700469 try {
Jeff Sharkeyad357d12018-02-02 13:25:31 -0700470 return mService.isAppInactive(packageName, mContext.getUserId());
Amith Yamasanicf768722015-04-23 20:36:41 -0700471 } catch (RemoteException e) {
472 // fall through and return default
473 }
474 return false;
475 }
Amith Yamasani901e9242015-05-13 18:21:09 -0700476
477 /**
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800478 * {@hide}
Amith Yamasani901e9242015-05-13 18:21:09 -0700479 */
480 public void setAppInactive(String packageName, boolean inactive) {
481 try {
Jeff Sharkeyad357d12018-02-02 13:25:31 -0700482 mService.setAppInactive(packageName, inactive, mContext.getUserId());
Amith Yamasani901e9242015-05-13 18:21:09 -0700483 } catch (RemoteException e) {
484 // fall through
485 }
486 }
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700487
488 /**
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800489 * Returns the current standby bucket of the calling app. The system determines the standby
490 * state of the app based on app usage patterns. Standby buckets determine how much an app will
Amith Yamasani853e53f2018-03-16 16:08:57 -0700491 * be restricted from running background tasks such as jobs and alarms.
Amith Yamasanie8789312017-12-10 14:34:26 -0800492 * <p>Restrictions increase progressively from {@link #STANDBY_BUCKET_ACTIVE} to
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800493 * {@link #STANDBY_BUCKET_RARE}, with {@link #STANDBY_BUCKET_ACTIVE} being the least
494 * restrictive. The battery level of the device might also affect the restrictions.
Amith Yamasani853e53f2018-03-16 16:08:57 -0700495 * <p>Apps in buckets &le; {@link #STANDBY_BUCKET_ACTIVE} have no standby restrictions imposed.
496 * Apps in buckets &gt; {@link #STANDBY_BUCKET_FREQUENT} may have network access restricted when
497 * running in the background.
498 * <p>The standby state of an app can change at any time either due to a user interaction or a
499 * system interaction or some algorithm determining that the app can be restricted for a period
500 * of time before the user has a need for it.
501 * <p>You can also query the recent history of standby bucket changes by calling
502 * {@link #queryEventsForSelf(long, long)} and searching for
503 * {@link UsageEvents.Event#STANDBY_BUCKET_CHANGED}.
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800504 *
Amith Yamasanie8789312017-12-10 14:34:26 -0800505 * @return the current standby bucket of the calling app. One of STANDBY_BUCKET_* constants.
Amith Yamasani17fffee2017-09-29 13:17:43 -0700506 */
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800507 public @StandbyBuckets int getAppStandbyBucket() {
508 try {
509 return mService.getAppStandbyBucket(mContext.getOpPackageName(),
510 mContext.getOpPackageName(),
511 mContext.getUserId());
512 } catch (RemoteException e) {
513 }
514 return STANDBY_BUCKET_ACTIVE;
515 }
516
517 /**
518 * {@hide}
519 * Returns the current standby bucket of the specified app. The caller must hold the permission
520 * android.permission.PACKAGE_USAGE_STATS.
521 * @param packageName the package for which to fetch the current standby bucket.
522 */
523 @SystemApi
524 @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
Amith Yamasani17fffee2017-09-29 13:17:43 -0700525 public @StandbyBuckets int getAppStandbyBucket(String packageName) {
526 try {
527 return mService.getAppStandbyBucket(packageName, mContext.getOpPackageName(),
528 mContext.getUserId());
529 } catch (RemoteException e) {
530 }
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800531 return STANDBY_BUCKET_ACTIVE;
Amith Yamasani17fffee2017-09-29 13:17:43 -0700532 }
533
534 /**
Amith Yamasaniafbccb72017-11-27 10:44:24 -0800535 * {@hide}
Amith Yamasanie8789312017-12-10 14:34:26 -0800536 * Changes an app's standby bucket to the provided value. The caller can only set the standby
537 * bucket for a different app than itself.
538 * @param packageName the package name of the app to set the bucket for. A SecurityException
539 * will be thrown if the package name is that of the caller.
540 * @param bucket the standby bucket to set it to, which should be one of STANDBY_BUCKET_*.
541 * Setting a standby bucket outside of the range of STANDBY_BUCKET_ACTIVE to
542 * STANDBY_BUCKET_NEVER will result in a SecurityException.
Amith Yamasani17fffee2017-09-29 13:17:43 -0700543 */
Amith Yamasani4470ab92017-10-31 13:29:00 -0700544 @SystemApi
545 @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE)
Amith Yamasani17fffee2017-09-29 13:17:43 -0700546 public void setAppStandbyBucket(String packageName, @StandbyBuckets int bucket) {
547 try {
548 mService.setAppStandbyBucket(packageName, bucket, mContext.getUserId());
549 } catch (RemoteException e) {
Amith Yamasanifd44f272018-05-14 14:47:19 -0700550 throw e.rethrowFromSystemServer();
Amith Yamasani17fffee2017-09-29 13:17:43 -0700551 }
552 }
553
554 /**
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700555 * {@hide}
Amith Yamasanie8789312017-12-10 14:34:26 -0800556 * Returns the current standby bucket of every app that has a bucket assigned to it.
557 * The caller must hold the permission android.permission.PACKAGE_USAGE_STATS. The key of the
558 * returned Map is the package name and the value is the bucket assigned to the package.
559 * @see #getAppStandbyBucket()
560 */
561 @SystemApi
562 @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
563 public Map<String, Integer> getAppStandbyBuckets() {
564 try {
Suprabh Shukla868bde22018-02-20 20:59:52 -0800565 final ParceledListSlice<AppStandbyInfo> slice = mService.getAppStandbyBuckets(
Amith Yamasanie8789312017-12-10 14:34:26 -0800566 mContext.getOpPackageName(), mContext.getUserId());
Suprabh Shukla868bde22018-02-20 20:59:52 -0800567 final List<AppStandbyInfo> bucketList = slice.getList();
568 final ArrayMap<String, Integer> bucketMap = new ArrayMap<>();
569 final int n = bucketList.size();
570 for (int i = 0; i < n; i++) {
571 final AppStandbyInfo bucketInfo = bucketList.get(i);
572 bucketMap.put(bucketInfo.mPackageName, bucketInfo.mStandbyBucket);
573 }
574 return bucketMap;
Amith Yamasanie8789312017-12-10 14:34:26 -0800575 } catch (RemoteException e) {
Amith Yamasanifd44f272018-05-14 14:47:19 -0700576 throw e.rethrowFromSystemServer();
Amith Yamasanie8789312017-12-10 14:34:26 -0800577 }
Amith Yamasanie8789312017-12-10 14:34:26 -0800578 }
579
580 /**
581 * {@hide}
582 * Changes the app standby bucket for multiple apps at once. The Map is keyed by the package
583 * name and the value is one of STANDBY_BUCKET_*.
584 * @param appBuckets a map of package name to bucket value.
585 */
586 @SystemApi
587 @RequiresPermission(android.Manifest.permission.CHANGE_APP_IDLE_STATE)
588 public void setAppStandbyBuckets(Map<String, Integer> appBuckets) {
Suprabh Shukla868bde22018-02-20 20:59:52 -0800589 if (appBuckets == null) {
590 return;
591 }
592 final List<AppStandbyInfo> bucketInfoList = new ArrayList<>(appBuckets.size());
593 for (Map.Entry<String, Integer> bucketEntry : appBuckets.entrySet()) {
594 bucketInfoList.add(new AppStandbyInfo(bucketEntry.getKey(), bucketEntry.getValue()));
595 }
596 final ParceledListSlice<AppStandbyInfo> slice = new ParceledListSlice<>(bucketInfoList);
Amith Yamasanie8789312017-12-10 14:34:26 -0800597 try {
Suprabh Shukla868bde22018-02-20 20:59:52 -0800598 mService.setAppStandbyBuckets(slice, mContext.getUserId());
Amith Yamasanie8789312017-12-10 14:34:26 -0800599 } catch (RemoteException e) {
Amith Yamasanifd44f272018-05-14 14:47:19 -0700600 throw e.rethrowFromSystemServer();
Amith Yamasanie8789312017-12-10 14:34:26 -0800601 }
602 }
603
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700604 /**
605 * @hide
606 * Register an app usage limit observer that receives a callback on the provided intent when
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800607 * the sum of usages of apps and tokens in the {@code observed} array exceeds the
608 * {@code timeLimit} specified. The structure of a token is a String with the reporting
609 * package's name and a token the reporting app will use, separated by the forward slash
610 * character. Example: com.reporting.package/5OM3*0P4QU3-7OK3N
611 * The observer will automatically be unregistered when the time limit is reached and the
612 * intent is delivered. Registering an {@code observerId} that was already registered will
613 * override the previous one. No more than 1000 unique {@code observerId} may be registered by
614 * a single uid at any one time.
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700615 * @param observerId A unique id associated with the group of apps to be monitored. There can
616 * be multiple groups with common packages and different time limits.
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800617 * @param observedEntities The list of packages and token to observe for usage time. Cannot be
618 * null and must include at least one package or token.
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700619 * @param timeLimit The total time the set of apps can be in the foreground before the
Michael Wachenschwanzc8703092018-05-01 16:02:45 -0700620 * callbackIntent is delivered. Must be at least one minute.
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700621 * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null.
Varun Shah2546cef2019-01-11 15:50:54 -0800622 * @param callbackIntent The PendingIntent that will be dispatched when the usage limit is
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700623 * exceeded by the group of apps. The delivered Intent will also contain
624 * the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700625 * {@link #EXTRA_TIME_USED}. Cannot be null.
Michael Wachenschwanz641e3382018-10-23 23:21:48 -0700626 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700627 * is not the profile owner of this user.
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700628 */
629 @SystemApi
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700630 @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800631 public void registerAppUsageObserver(int observerId, @NonNull String[] observedEntities,
632 long timeLimit, @NonNull TimeUnit timeUnit, @NonNull PendingIntent callbackIntent) {
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700633 try {
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800634 mService.registerAppUsageObserver(observerId, observedEntities,
635 timeUnit.toMillis(timeLimit), callbackIntent, mContext.getOpPackageName());
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700636 } catch (RemoteException e) {
Amith Yamasanifd44f272018-05-14 14:47:19 -0700637 throw e.rethrowFromSystemServer();
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700638 }
639 }
640
641 /**
642 * @hide
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700643 * Unregister the app usage observer specified by the {@code observerId}. This will only apply
644 * to any observer registered by this application. Unregistering an observer that was already
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700645 * unregistered or never registered will have no effect.
646 * @param observerId The id of the observer that was previously registered.
Michael Wachenschwanz641e3382018-10-23 23:21:48 -0700647 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and is
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700648 * not the profile owner of this user.
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700649 */
650 @SystemApi
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700651 @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700652 public void unregisterAppUsageObserver(int observerId) {
653 try {
654 mService.unregisterAppUsageObserver(observerId, mContext.getOpPackageName());
655 } catch (RemoteException e) {
Amith Yamasanifd44f272018-05-14 14:47:19 -0700656 throw e.rethrowFromSystemServer();
Amith Yamasani62ec27e92018-03-11 14:42:06 -0700657 }
658 }
659
Michael Wachenschwanz641e3382018-10-23 23:21:48 -0700660 /**
661 * Register a usage session observer that receives a callback on the provided {@code
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800662 * limitReachedCallbackIntent} when the sum of usages of apps and tokens in the {@code
663 * observed} array exceeds the {@code timeLimit} specified within a usage session. The
664 * structure of a token is a String with the reporting packages' name and a token the
665 * reporting app will use, separated by the forward slash character.
666 * Example: com.reporting.package/5OM3*0P4QU3-7OK3N
667 * After the {@code timeLimit} has been reached, the usage session observer will receive a
668 * callback on the provided {@code sessionEndCallbackIntent} when the usage session ends.
669 * Registering another session observer against a {@code sessionObserverId} that has already
670 * been registered will override the previous session observer.
Michael Wachenschwanz641e3382018-10-23 23:21:48 -0700671 *
672 * @param sessionObserverId A unique id associated with the group of apps to be
673 * monitored. There can be multiple groups with common
674 * packages and different time limits.
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800675 * @param observedEntities The list of packages and token to observe for usage time. Cannot be
676 * null and must include at least one package or token.
Michael Wachenschwanz641e3382018-10-23 23:21:48 -0700677 * @param timeLimit The total time the set of apps can be used continuously before the {@code
678 * limitReachedCallbackIntent} is delivered. Must be at least one minute.
679 * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null.
680 * @param sessionThresholdTime The time that can take place between usage sessions before the
681 * next session is considered a new session. Must be non-negative.
682 * @param sessionThresholdTimeUnit The unit for time specified in {@code sessionThreshold}.
683 * Cannot be null.
684 * @param limitReachedCallbackIntent The {@link PendingIntent} that will be dispatched when the
Varun Shah2546cef2019-01-11 15:50:54 -0800685 * usage limit is exceeded by the group of apps. The
686 * delivered Intent will also contain the extras {@link
Michael Wachenschwanz641e3382018-10-23 23:21:48 -0700687 * #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and {@link
688 * #EXTRA_TIME_USED}. Cannot be null.
689 * @param sessionEndCallbackIntent The {@link PendingIntent} that will be dispatched when the
Varun Shah2546cef2019-01-11 15:50:54 -0800690 * session has ended after the usage limit has been exceeded.
691 * The session is considered at its end after the {@code
692 * observed} usage has stopped and an additional {@code
Michael Wachenschwanz641e3382018-10-23 23:21:48 -0700693 * sessionThresholdTime} has passed. The delivered Intent will
694 * also contain the extras {@link #EXTRA_OBSERVER_ID} and {@link
695 * #EXTRA_TIME_USED}. Can be null.
696 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and
697 * is not the profile owner of this user.
698 * @hide
699 */
700 @SystemApi
701 @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800702 public void registerUsageSessionObserver(int sessionObserverId,
703 @NonNull String[] observedEntities, long timeLimit, @NonNull TimeUnit timeUnit,
704 long sessionThresholdTime, @NonNull TimeUnit sessionThresholdTimeUnit,
Michael Wachenschwanz641e3382018-10-23 23:21:48 -0700705 @NonNull PendingIntent limitReachedCallbackIntent,
706 @Nullable PendingIntent sessionEndCallbackIntent) {
707 try {
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800708 mService.registerUsageSessionObserver(sessionObserverId, observedEntities,
Michael Wachenschwanz641e3382018-10-23 23:21:48 -0700709 timeUnit.toMillis(timeLimit),
710 sessionThresholdTimeUnit.toMillis(sessionThresholdTime),
711 limitReachedCallbackIntent, sessionEndCallbackIntent,
712 mContext.getOpPackageName());
713 } catch (RemoteException e) {
714 throw e.rethrowFromSystemServer();
715 }
716 }
717
718 /**
719 * Unregister the usage session observer specified by the {@code sessionObserverId}. This will
720 * only apply to any app session observer registered by this application. Unregistering an
721 * observer that was already unregistered or never registered will have no effect.
722 *
723 * @param sessionObserverId The id of the observer that was previously registered.
724 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and
725 * is not the profile owner of this user.
726 * @hide
727 */
728 @SystemApi
729 @RequiresPermission(android.Manifest.permission.OBSERVE_APP_USAGE)
730 public void unregisterUsageSessionObserver(int sessionObserverId) {
731 try {
732 mService.unregisterUsageSessionObserver(sessionObserverId, mContext.getOpPackageName());
733 } catch (RemoteException e) {
734 throw e.rethrowFromSystemServer();
735 }
736 }
737
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800738 /**
Varun Shah2546cef2019-01-11 15:50:54 -0800739 * Register a usage limit observer that receives a callback on the provided intent when the
740 * sum of usages of apps and tokens in the provided {@code observedEntities} array exceeds the
741 * {@code timeLimit} specified. The structure of a token is a {@link String} with the reporting
742 * package's name and a token that the calling app will use, separated by the forward slash
743 * character. Example: com.reporting.package/5OM3*0P4QU3-7OK3N
744 * <p>
745 * Registering an {@code observerId} that was already registered will override the previous one.
746 * No more than 1000 unique {@code observerId} may be registered by a single uid
747 * at any one time.
Varun Shah54f7f7f2019-02-07 10:21:17 -0800748 * A limit is not cleared when the usage time is exceeded. It needs to be unregistered via
749 * {@link #unregisterAppUsageLimitObserver}.
750 * <p>
751 * Note: usage limits are not persisted in the system and are cleared on reboots. Callers
752 * must reset any limits that they need on reboots.
Varun Shah2546cef2019-01-11 15:50:54 -0800753 * <p>
754 * This method is similar to {@link #registerAppUsageObserver}, but the usage limit set here
755 * will be visible to the launcher so that it can report the limit to the user and how much
756 * of it is remaining.
757 * @see android.content.pm.LauncherApps#getAppUsageLimit
758 *
759 * @param observerId A unique id associated with the group of apps to be monitored. There can
760 * be multiple groups with common packages and different time limits.
761 * @param observedEntities The list of packages and token to observe for usage time. Cannot be
762 * null and must include at least one package or token.
763 * @param timeLimit The total time the set of apps can be in the foreground before the
Varun Shah54f7f7f2019-02-07 10:21:17 -0800764 * callbackIntent is delivered. Must be at least one minute. Note: a limit of
765 * 0 can be set to indicate that the user has already exhausted the limit for
766 * a group, in which case, the given {@code callbackIntent} will be ignored.
Varun Shah2546cef2019-01-11 15:50:54 -0800767 * @param timeUnit The unit for time specified in {@code timeLimit}. Cannot be null.
Varun Shah54f7f7f2019-02-07 10:21:17 -0800768 * @param callbackIntent The PendingIntent that will be dispatched when the usage limit is
Varun Shah2546cef2019-01-11 15:50:54 -0800769 * exceeded by the group of apps. The delivered Intent will also contain
770 * the extras {@link #EXTRA_OBSERVER_ID}, {@link #EXTRA_TIME_LIMIT} and
Varun Shah54f7f7f2019-02-07 10:21:17 -0800771 * {@link #EXTRA_TIME_USED}. Cannot be {@code null} unless the observer is
772 * being registered with a {@code timeLimit} of 0.
Varun Shah2546cef2019-01-11 15:50:54 -0800773 * @throws SecurityException if the caller doesn't have both SUSPEND_APPS and OBSERVE_APP_USAGE
774 * permissions.
775 * @hide
776 */
777 @SystemApi
778 @RequiresPermission(allOf = {
779 android.Manifest.permission.SUSPEND_APPS,
780 android.Manifest.permission.OBSERVE_APP_USAGE})
781 public void registerAppUsageLimitObserver(int observerId, @NonNull String[] observedEntities,
Varun Shah9c169892019-02-15 10:21:27 -0800782 long timeLimit, @NonNull TimeUnit timeUnit, @Nullable PendingIntent callbackIntent) {
Varun Shah2546cef2019-01-11 15:50:54 -0800783 try {
784 mService.registerAppUsageLimitObserver(observerId, observedEntities,
785 timeUnit.toMillis(timeLimit), callbackIntent, mContext.getOpPackageName());
786 } catch (RemoteException e) {
787 throw e.rethrowFromSystemServer();
788 }
789 }
790
791 /**
792 * Unregister the app usage limit observer specified by the {@code observerId}.
793 * This will only apply to any observer registered by this application. Unregistering
794 * an observer that was already unregistered or never registered will have no effect.
795 *
796 * @param observerId The id of the observer that was previously registered.
797 * @throws SecurityException if the caller doesn't have both SUSPEND_APPS and OBSERVE_APP_USAGE
798 * permissions.
799 * @hide
800 */
801 @SystemApi
802 @RequiresPermission(allOf = {
803 android.Manifest.permission.SUSPEND_APPS,
804 android.Manifest.permission.OBSERVE_APP_USAGE})
805 public void unregisterAppUsageLimitObserver(int observerId) {
806 try {
807 mService.unregisterAppUsageLimitObserver(observerId, mContext.getOpPackageName());
808 } catch (RemoteException e) {
809 throw e.rethrowFromSystemServer();
810 }
811 }
812
813 /**
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800814 * Report usage associated with a particular {@code token} has started. Tokens are app defined
815 * strings used to represent usage of in-app features. Apps with the {@link
816 * android.Manifest.permission#OBSERVE_APP_USAGE} permission can register time limit observers
817 * to monitor the usage of a token. In app usage can only associated with an {@code activity}
818 * and usage will be considered stopped if the activity stops or crashes.
819 * @see #registerAppUsageObserver
820 * @see #registerUsageSessionObserver
Varun Shah2546cef2019-01-11 15:50:54 -0800821 * @see #registerAppUsageLimitObserver
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800822 *
823 * @param activity The activity {@code token} is associated with.
824 * @param token The token to report usage against.
825 * @hide
826 */
827 @SystemApi
828 public void reportUsageStart(@NonNull Activity activity, @NonNull String token) {
829 try {
830 mService.reportUsageStart(activity.getActivityToken(), token,
831 mContext.getOpPackageName());
832 } catch (RemoteException e) {
833 throw e.rethrowFromSystemServer();
834 }
835 }
836
837 /**
838 * Report usage associated with a particular {@code token} had started some amount of time in
839 * the past. Tokens are app defined strings used to represent usage of in-app features. Apps
840 * with the {@link android.Manifest.permission#OBSERVE_APP_USAGE} permission can register time
841 * limit observers to monitor the usage of a token. In app usage can only associated with an
842 * {@code activity} and usage will be considered stopped if the activity stops or crashes.
843 * @see #registerAppUsageObserver
844 * @see #registerUsageSessionObserver
Varun Shah2546cef2019-01-11 15:50:54 -0800845 * @see #registerAppUsageLimitObserver
Michael Wachenschwanz36778522018-11-12 11:06:19 -0800846 *
847 * @param activity The activity {@code token} is associated with.
848 * @param token The token to report usage against.
849 * @param timeAgoMs How long ago the start of usage took place
850 * @hide
851 */
852 @SystemApi
853 public void reportUsageStart(@NonNull Activity activity, @NonNull String token,
854 long timeAgoMs) {
855 try {
856 mService.reportPastUsageStart(activity.getActivityToken(), token, timeAgoMs,
857 mContext.getOpPackageName());
858 } catch (RemoteException e) {
859 throw e.rethrowFromSystemServer();
860 }
861 }
862
863 /**
864 * Report the usage associated with a particular {@code token} has stopped.
865 *
866 * @param activity The activity {@code token} is associated with.
867 * @param token The token to report usage against.
868 * @hide
869 */
870 @SystemApi
871 public void reportUsageStop(@NonNull Activity activity, @NonNull String token) {
872 try {
873 mService.reportUsageStop(activity.getActivityToken(), token,
874 mContext.getOpPackageName());
875 } catch (RemoteException e) {
876 throw e.rethrowFromSystemServer();
877 }
878 }
879
Michael Wachenschwanz0b4ab1f2019-01-07 13:59:10 -0800880 /**
881 * Get what App Usage Observers will consider the source of usage for an activity. Usage Source
882 * is decided at boot and will not change until next boot.
883 * @see #USAGE_SOURCE_TASK_ROOT_ACTIVITY
884 * @see #USAGE_SOURCE_CURRENT_ACTIVITY
885 *
886 * @throws SecurityException if the caller doesn't have the OBSERVE_APP_USAGE permission and
887 * is not the profile owner of this user.
888 * @hide
889 */
890 @SystemApi
891 public @UsageSource int getUsageSource() {
892 try {
893 return mService.getUsageSource();
894 } catch (RemoteException e) {
895 throw e.rethrowFromSystemServer();
896 }
897 }
898
899 /**
900 * Force the Usage Source be reread from global settings.
901 * @hide
902 */
903 @TestApi
904 public void forceUsageSourceSettingRead() {
905 try {
906 mService.forceUsageSourceSettingRead();
907 } catch (RemoteException e) {
908 throw e.rethrowFromSystemServer();
909 }
910 }
911
Amith Yamasani119be9a2018-02-18 22:23:00 -0800912 /** @hide */
913 public static String reasonToString(int standbyReason) {
914 StringBuilder sb = new StringBuilder();
915 switch (standbyReason & REASON_MAIN_MASK) {
916 case REASON_MAIN_DEFAULT:
917 sb.append("d");
918 break;
919 case REASON_MAIN_FORCED:
920 sb.append("f");
921 break;
922 case REASON_MAIN_PREDICTED:
923 sb.append("p");
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700924 switch (standbyReason & REASON_SUB_MASK) {
925 case REASON_SUB_PREDICTED_RESTORED:
926 sb.append("-r");
927 break;
928 }
Amith Yamasani119be9a2018-02-18 22:23:00 -0800929 break;
930 case REASON_MAIN_TIMEOUT:
931 sb.append("t");
932 break;
933 case REASON_MAIN_USAGE:
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700934 sb.append("u");
Amith Yamasani119be9a2018-02-18 22:23:00 -0800935 switch (standbyReason & REASON_SUB_MASK) {
936 case REASON_SUB_USAGE_SYSTEM_INTERACTION:
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700937 sb.append("-si");
Amith Yamasani119be9a2018-02-18 22:23:00 -0800938 break;
939 case REASON_SUB_USAGE_NOTIFICATION_SEEN:
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700940 sb.append("-ns");
Amith Yamasani119be9a2018-02-18 22:23:00 -0800941 break;
942 case REASON_SUB_USAGE_USER_INTERACTION:
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700943 sb.append("-ui");
Amith Yamasani119be9a2018-02-18 22:23:00 -0800944 break;
945 case REASON_SUB_USAGE_MOVE_TO_FOREGROUND:
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700946 sb.append("-mf");
Amith Yamasani119be9a2018-02-18 22:23:00 -0800947 break;
948 case REASON_SUB_USAGE_MOVE_TO_BACKGROUND:
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700949 sb.append("-mb");
Amith Yamasani119be9a2018-02-18 22:23:00 -0800950 break;
951 case REASON_SUB_USAGE_SYSTEM_UPDATE:
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700952 sb.append("-su");
Amith Yamasani119be9a2018-02-18 22:23:00 -0800953 break;
954 case REASON_SUB_USAGE_ACTIVE_TIMEOUT:
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700955 sb.append("-at");
Amith Yamasani119be9a2018-02-18 22:23:00 -0800956 break;
957 case REASON_SUB_USAGE_SYNC_ADAPTER:
Amith Yamasani3154dcf2018-03-27 18:24:04 -0700958 sb.append("-sa");
Amith Yamasani119be9a2018-02-18 22:23:00 -0800959 break;
Amith Yamasani80c4be82018-03-26 10:54:04 -0700960 case REASON_SUB_USAGE_SLICE_PINNED:
Makoto Onukid5f25d22018-05-22 16:02:17 -0700961 sb.append("-lp");
Amith Yamasani80c4be82018-03-26 10:54:04 -0700962 break;
963 case REASON_SUB_USAGE_SLICE_PINNED_PRIV:
Makoto Onukid5f25d22018-05-22 16:02:17 -0700964 sb.append("-lv");
965 break;
966 case REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_NON_DOZE:
967 sb.append("-en");
968 break;
969 case REASON_SUB_USAGE_EXEMPTED_SYNC_SCHEDULED_DOZE:
970 sb.append("-ed");
Amith Yamasani80c4be82018-03-26 10:54:04 -0700971 break;
Makoto Onuki75ad2492018-03-28 14:42:42 -0700972 case REASON_SUB_USAGE_EXEMPTED_SYNC_START:
Makoto Onukid5f25d22018-05-22 16:02:17 -0700973 sb.append("-es");
Makoto Onuki75ad2492018-03-28 14:42:42 -0700974 break;
Amith Yamasani119be9a2018-02-18 22:23:00 -0800975 }
976 break;
977 }
978 return sb.toString();
979 }
980
Michael Wachenschwanz0b4ab1f2019-01-07 13:59:10 -0800981 /** @hide */
982 public static String usageSourceToString(int usageSource) {
983 switch (usageSource) {
984 case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
985 return "TASK_ROOT_ACTIVITY";
986 case USAGE_SOURCE_CURRENT_ACTIVITY:
987 return "CURRENT_ACTIVITY";
988 default:
989 StringBuilder sb = new StringBuilder();
990 sb.append("UNKNOWN(");
991 sb.append(usageSource);
992 sb.append(")");
993 return sb.toString();
994 }
995 }
996
Amith Yamasanie8789312017-12-10 14:34:26 -0800997 /**
998 * {@hide}
Amith Yamasaniaf575b92015-05-29 15:35:26 -0700999 * Temporarily whitelist the specified app for a short duration. This is to allow an app
1000 * receiving a high priority message to be able to access the network and acquire wakelocks
1001 * even if the device is in power-save mode or the app is currently considered inactive.
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001002 * @param packageName The package name of the app to whitelist.
1003 * @param duration Duration to whitelist the app for, in milliseconds. It is recommended that
1004 * this be limited to 10s of seconds. Requested duration will be clamped to a few minutes.
1005 * @param user The user for whom the package should be whitelisted. Passing in a user that is
1006 * not the same as the caller's process will require the INTERACT_ACROSS_USERS permission.
1007 * @see #isAppInactive(String)
1008 */
1009 @SystemApi
Jeff Sharkeyd86b8fe2017-06-02 17:36:26 -06001010 @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001011 public void whitelistAppTemporarily(String packageName, long duration, UserHandle user) {
1012 try {
1013 mService.whitelistAppTemporarily(packageName, duration, user.getIdentifier());
1014 } catch (RemoteException re) {
Amith Yamasanifd44f272018-05-14 14:47:19 -07001015 throw re.rethrowFromSystemServer();
Amith Yamasaniaf575b92015-05-29 15:35:26 -07001016 }
1017 }
Amith Yamasani4ec63682016-02-19 12:55:27 -08001018
1019 /**
1020 * Inform usage stats that the carrier privileged apps access rules have changed.
1021 * @hide
1022 */
1023 public void onCarrierPrivilegedAppsChanged() {
1024 try {
1025 mService.onCarrierPrivilegedAppsChanged();
1026 } catch (RemoteException re) {
Amith Yamasanifd44f272018-05-14 14:47:19 -07001027 throw re.rethrowFromSystemServer();
Amith Yamasani4ec63682016-02-19 12:55:27 -08001028 }
1029 }
Kang Li53b43142016-11-14 14:38:25 -08001030
1031 /**
1032 * Reports a Chooser action to the UsageStatsManager.
1033 *
1034 * @param packageName The package name of the app that is selected.
1035 * @param userId The user id of who makes the selection.
1036 * @param contentType The type of the content, e.g., Image, Video, App.
1037 * @param annotations The annotations of the content, e.g., Game, Selfie.
1038 * @param action The action type of Intent that invokes ChooserActivity.
1039 * {@link UsageEvents}
1040 * @hide
1041 */
1042 public void reportChooserSelection(String packageName, int userId, String contentType,
1043 String[] annotations, String action) {
1044 try {
1045 mService.reportChooserSelection(packageName, userId, contentType, annotations, action);
1046 } catch (RemoteException re) {
1047 }
1048 }
Adam Lesinski0debc9a2014-07-16 19:09:13 -07001049}