blob: 97efa01e982b870e7fd3859a8db881e20e407760 [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
Hui Yu03d12402018-12-06 18:00:37 -080019import static android.app.usage.UsageEvents.Event.ACTIVITY_DESTROYED;
20import static android.app.usage.UsageEvents.Event.ACTIVITY_PAUSED;
21import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED;
22import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED;
Hui Yue361a232018-10-04 15:05:21 -070023import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE;
Hui Yub1d243a2018-12-13 12:02:00 -080024import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
Hui Yue361a232018-10-04 15:05:21 -070025import static android.app.usage.UsageEvents.Event.END_OF_DAY;
Hui Yu03d12402018-12-06 18:00:37 -080026import static android.app.usage.UsageEvents.Event.FLUSH_TO_DISK;
Hui Yue361a232018-10-04 15:05:21 -070027import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_START;
28import static android.app.usage.UsageEvents.Event.FOREGROUND_SERVICE_STOP;
Hui Yue361a232018-10-04 15:05:21 -070029import static android.app.usage.UsageEvents.Event.ROLLOVER_FOREGROUND_SERVICE;
30
Amith Yamasanibc813eb2018-03-20 19:37:46 -070031import android.annotation.SystemApi;
Mathew Inwood61e8ae62018-08-14 14:17:44 +010032import android.annotation.UnsupportedAppUsage;
Mathew Inwood31755f92018-12-20 13:53:36 +000033import android.os.Build;
Kang Li53b43142016-11-14 14:38:25 -080034import android.os.Bundle;
Adam Lesinski0debc9a2014-07-16 19:09:13 -070035import android.os.Parcel;
36import android.os.Parcelable;
Kang Li53b43142016-11-14 14:38:25 -080037import android.util.ArrayMap;
Hui Yu03d12402018-12-06 18:00:37 -080038import android.util.SparseIntArray;
Adam Lesinski0debc9a2014-07-16 19:09:13 -070039
Adam Lesinski35168002014-07-21 15:25:30 -070040/**
41 * Contains usage statistics for an app package for a specific
42 * time range.
43 */
Adam Lesinski0debc9a2014-07-16 19:09:13 -070044public final class UsageStats implements Parcelable {
Adam Lesinski0debc9a2014-07-16 19:09:13 -070045
46 /**
47 * {@hide}
48 */
Mathew Inwood31755f92018-12-20 13:53:36 +000049 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Adam Lesinski35168002014-07-21 15:25:30 -070050 public String mPackageName;
Adam Lesinski0debc9a2014-07-16 19:09:13 -070051
52 /**
53 * {@hide}
54 */
Mathew Inwood31755f92018-12-20 13:53:36 +000055 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Adam Lesinski0debc9a2014-07-16 19:09:13 -070056 public long mBeginTimeStamp;
57
58 /**
59 * {@hide}
60 */
Mathew Inwood31755f92018-12-20 13:53:36 +000061 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Adam Lesinski0debc9a2014-07-16 19:09:13 -070062 public long mEndTimeStamp;
63
64 /**
Hui Yu03d12402018-12-06 18:00:37 -080065 * Last time an activity is at foreground (have focus), this is corresponding to
66 * {@link android.app.usage.UsageEvents.Event#ACTIVITY_RESUMED} event.
Adam Lesinski0debc9a2014-07-16 19:09:13 -070067 * {@hide}
68 */
Mathew Inwood31755f92018-12-20 13:53:36 +000069 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Adam Lesinski35168002014-07-21 15:25:30 -070070 public long mLastTimeUsed;
Adam Lesinski0debc9a2014-07-16 19:09:13 -070071
72 /**
Hui Yu03d12402018-12-06 18:00:37 -080073 * Last time an activity is visible.
74 * @hide
75 */
76 public long mLastTimeVisible;
77
78 /**
Hui Yue361a232018-10-04 15:05:21 -070079 * Total time this package's activity is in foreground.
Adam Lesinski0debc9a2014-07-16 19:09:13 -070080 * {@hide}
81 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +010082 @UnsupportedAppUsage
Adam Lesinski35168002014-07-21 15:25:30 -070083 public long mTotalTimeInForeground;
84
85 /**
Hui Yu03d12402018-12-06 18:00:37 -080086 * Total time this package's activity is visible.
87 * {@hide}
88 */
89 public long mTotalTimeVisible;
90
91 /**
Hui Yue361a232018-10-04 15:05:21 -070092 * Last time foreground service is started.
93 * {@hide}
94 */
95 public long mLastTimeForegroundServiceUsed;
96
97 /**
98 * Total time this package's foreground service is started.
99 * {@hide}
100 */
101 public long mTotalTimeForegroundServiceUsed;
102
103 /**
Adam Lesinski35168002014-07-21 15:25:30 -0700104 * {@hide}
105 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100106 @UnsupportedAppUsage
Adam Lesinski35168002014-07-21 15:25:30 -0700107 public int mLaunchCount;
108
109 /**
110 * {@hide}
111 */
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700112 public int mAppLaunchCount;
113
Hui Yu03d12402018-12-06 18:00:37 -0800114 /** Last activity ACTIVITY_RESUMED or ACTIVITY_PAUSED event.
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700115 * {@hide}
Hui Yu03d12402018-12-06 18:00:37 -0800116 * @deprecated use {@link #mActivities} instead.
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700117 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +0100118 @UnsupportedAppUsage
Hui Yue361a232018-10-04 15:05:21 -0700119 @Deprecated
Adam Lesinski35168002014-07-21 15:25:30 -0700120 public int mLastEvent;
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700121
122 /**
Hui Yu03d12402018-12-06 18:00:37 -0800123 * Key is instanceId of the activity (ActivityRecode appToken hashCode)..
Hui Yub1d243a2018-12-13 12:02:00 -0800124 * Value is this activity's last event, one of ACTIVITY_RESUMED, ACTIVITY_PAUSED or
125 * ACTIVITY_STOPPED.
Hui Yue361a232018-10-04 15:05:21 -0700126 * {@hide}
127 */
Hui Yu03d12402018-12-06 18:00:37 -0800128 public SparseIntArray mActivities = new SparseIntArray();
Hui Yue361a232018-10-04 15:05:21 -0700129 /**
130 * If a foreground service is started, it has one entry in this map.
Hui Yu03d12402018-12-06 18:00:37 -0800131 * When a foreground service is stopped, it is removed from this set.
Hui Yue361a232018-10-04 15:05:21 -0700132 * Key is foreground service class name.
Hui Yu03d12402018-12-06 18:00:37 -0800133 * Value is the foreground service's last event, it is FOREGROUND_SERVICE_START.
Hui Yue361a232018-10-04 15:05:21 -0700134 * {@hide}
135 */
Hui Yu03d12402018-12-06 18:00:37 -0800136 public ArrayMap<String, Integer> mForegroundServices = new ArrayMap<>();
Hui Yue361a232018-10-04 15:05:21 -0700137
138 /**
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700139 * {@hide}
140 */
Hui Yue361a232018-10-04 15:05:21 -0700141 public ArrayMap<String, ArrayMap<String, Integer>> mChooserCounts = new ArrayMap<>();
Kang Li53b43142016-11-14 14:38:25 -0800142
143 /**
144 * {@hide}
145 */
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700146 public UsageStats() {
147 }
148
149 public UsageStats(UsageStats stats) {
Adam Lesinski35168002014-07-21 15:25:30 -0700150 mPackageName = stats.mPackageName;
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700151 mBeginTimeStamp = stats.mBeginTimeStamp;
152 mEndTimeStamp = stats.mEndTimeStamp;
Adam Lesinski35168002014-07-21 15:25:30 -0700153 mLastTimeUsed = stats.mLastTimeUsed;
Hui Yu03d12402018-12-06 18:00:37 -0800154 mLastTimeVisible = stats.mLastTimeVisible;
Hui Yue361a232018-10-04 15:05:21 -0700155 mLastTimeForegroundServiceUsed = stats.mLastTimeForegroundServiceUsed;
Adam Lesinski35168002014-07-21 15:25:30 -0700156 mTotalTimeInForeground = stats.mTotalTimeInForeground;
Hui Yu03d12402018-12-06 18:00:37 -0800157 mTotalTimeVisible = stats.mTotalTimeVisible;
Hui Yue361a232018-10-04 15:05:21 -0700158 mTotalTimeForegroundServiceUsed = stats.mTotalTimeForegroundServiceUsed;
Adam Lesinski35168002014-07-21 15:25:30 -0700159 mLaunchCount = stats.mLaunchCount;
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700160 mAppLaunchCount = stats.mAppLaunchCount;
Adam Lesinski35168002014-07-21 15:25:30 -0700161 mLastEvent = stats.mLastEvent;
Hui Yu03d12402018-12-06 18:00:37 -0800162 mActivities = stats.mActivities;
163 mForegroundServices = stats.mForegroundServices;
Kang Li53b43142016-11-14 14:38:25 -0800164 mChooserCounts = stats.mChooserCounts;
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700165 }
166
Makoto Onukiad623012017-05-15 09:29:34 -0700167 /**
168 * {@hide}
169 */
170 public UsageStats getObfuscatedForInstantApp() {
171 final UsageStats ret = new UsageStats(this);
172
173 ret.mPackageName = UsageEvents.INSTANT_APP_PACKAGE_NAME;
174
175 return ret;
176 }
177
Adam Lesinski35168002014-07-21 15:25:30 -0700178 public String getPackageName() {
179 return mPackageName;
180 }
181
182 /**
Adam Lesinskicc562a82014-08-27 11:52:52 -0700183 * Get the beginning of the time range this {@link android.app.usage.UsageStats} represents,
184 * measured in milliseconds since the epoch.
185 * <p/>
186 * See {@link System#currentTimeMillis()}.
Adam Lesinski35168002014-07-21 15:25:30 -0700187 */
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700188 public long getFirstTimeStamp() {
189 return mBeginTimeStamp;
190 }
191
Adam Lesinski35168002014-07-21 15:25:30 -0700192 /**
Adam Lesinskicc562a82014-08-27 11:52:52 -0700193 * Get the end of the time range this {@link android.app.usage.UsageStats} represents,
194 * measured in milliseconds since the epoch.
195 * <p/>
196 * See {@link System#currentTimeMillis()}.
Adam Lesinski35168002014-07-21 15:25:30 -0700197 */
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700198 public long getLastTimeStamp() {
199 return mEndTimeStamp;
200 }
201
Adam Lesinski35168002014-07-21 15:25:30 -0700202 /**
Hui Yue361a232018-10-04 15:05:21 -0700203 * Get the last time this package's activity was used, measured in milliseconds since the epoch.
Adam Lesinskicc562a82014-08-27 11:52:52 -0700204 * <p/>
205 * See {@link System#currentTimeMillis()}.
Adam Lesinski35168002014-07-21 15:25:30 -0700206 */
207 public long getLastTimeUsed() {
208 return mLastTimeUsed;
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700209 }
210
211 /**
Hui Yu03d12402018-12-06 18:00:37 -0800212 * Get the last time this package's activity is visible in the UI, measured in milliseconds
213 * since the epoch.
214 */
215 public long getLastTimeVisible() {
216 return mLastTimeVisible;
217 }
218
219 /**
Adam Lesinskicc562a82014-08-27 11:52:52 -0700220 * Get the total time this package spent in the foreground, measured in milliseconds.
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700221 */
Adam Lesinski35168002014-07-21 15:25:30 -0700222 public long getTotalTimeInForeground() {
223 return mTotalTimeInForeground;
224 }
225
226 /**
Hui Yu03d12402018-12-06 18:00:37 -0800227 * Get the total time this package's activity is visible in the UI, measured in milliseconds.
228 */
229 public long getTotalTimeVisible() {
230 return mTotalTimeVisible;
231 }
232
233 /**
Hui Yue361a232018-10-04 15:05:21 -0700234 * Get the last time this package's foreground service was used, measured in milliseconds since
235 * the epoch.
236 * <p/>
237 * See {@link System#currentTimeMillis()}.
238 */
239 public long getLastTimeForegroundServiceUsed() {
240 return mLastTimeForegroundServiceUsed;
241 }
242
243 /**
244 * Get the total time this package's foreground services are started, measured in milliseconds.
245 */
246 public long getTotalTimeForegroundServiceUsed() {
247 return mTotalTimeForegroundServiceUsed;
248 }
249
250 /**
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700251 * Returns the number of times the app was launched as an activity from outside of the app.
252 * Excludes intra-app activity transitions.
253 * @hide
254 */
255 @SystemApi
256 public int getAppLaunchCount() {
257 return mAppLaunchCount;
258 }
259
Hui Yu03d12402018-12-06 18:00:37 -0800260 private void mergeEventMap(SparseIntArray left, SparseIntArray right) {
261 final int size = right.size();
262 for (int i = 0; i < size; i++) {
263 final int instanceId = right.keyAt(i);
264 final int event = right.valueAt(i);
265 final int index = left.indexOfKey(instanceId);
266 if (index >= 0) {
267 left.put(instanceId, Math.max(left.valueAt(index), event));
268 } else {
269 left.put(instanceId, event);
270 }
271 }
272 }
273
Hui Yue361a232018-10-04 15:05:21 -0700274 private void mergeEventMap(ArrayMap<String, Integer> left, ArrayMap<String, Integer> right) {
275 final int size = right.size();
276 for (int i = 0; i < size; i++) {
277 final String className = right.keyAt(i);
278 final Integer event = right.valueAt(i);
279 if (left.containsKey(className)) {
280 left.put(className, Math.max(left.get(className), event));
281 } else {
282 left.put(className, event);
283 }
284 }
285 }
286
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700287 /**
Adam Lesinski35168002014-07-21 15:25:30 -0700288 * Add the statistics from the right {@link UsageStats} to the left. The package name for
289 * both {@link UsageStats} objects must be the same.
290 * @param right The {@link UsageStats} object to merge into this one.
291 * @throws java.lang.IllegalArgumentException if the package names of the two
292 * {@link UsageStats} objects are different.
293 */
294 public void add(UsageStats right) {
295 if (!mPackageName.equals(right.mPackageName)) {
296 throw new IllegalArgumentException("Can't merge UsageStats for package '" +
297 mPackageName + "' with UsageStats for package '" + right.mPackageName + "'.");
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700298 }
Adam Lesinski35168002014-07-21 15:25:30 -0700299
Daniel Nishibaa38112017-02-07 16:47:57 -0800300 // We use the mBeginTimeStamp due to a bug where UsageStats files can overlap with
301 // regards to their mEndTimeStamp.
Adam Lesinskib2d3ffa2016-01-26 18:18:19 -0800302 if (right.mBeginTimeStamp > mBeginTimeStamp) {
Daniel Nishibaa38112017-02-07 16:47:57 -0800303 // Even though incoming UsageStat begins after this one, its last time used fields
304 // may somehow be empty or chronologically preceding the older UsageStat.
Hui Yu03d12402018-12-06 18:00:37 -0800305 mergeEventMap(mActivities, right.mActivities);
306 mergeEventMap(mForegroundServices, right.mForegroundServices);
Daniel Nishibaa38112017-02-07 16:47:57 -0800307 mLastTimeUsed = Math.max(mLastTimeUsed, right.mLastTimeUsed);
Hui Yu03d12402018-12-06 18:00:37 -0800308 mLastTimeVisible = Math.max(mLastTimeVisible, right.mLastTimeVisible);
Hui Yue361a232018-10-04 15:05:21 -0700309 mLastTimeForegroundServiceUsed = Math.max(mLastTimeForegroundServiceUsed,
310 right.mLastTimeForegroundServiceUsed);
Adam Lesinski35168002014-07-21 15:25:30 -0700311 }
312 mBeginTimeStamp = Math.min(mBeginTimeStamp, right.mBeginTimeStamp);
Adam Lesinskib2d3ffa2016-01-26 18:18:19 -0800313 mEndTimeStamp = Math.max(mEndTimeStamp, right.mEndTimeStamp);
Adam Lesinski35168002014-07-21 15:25:30 -0700314 mTotalTimeInForeground += right.mTotalTimeInForeground;
Hui Yu03d12402018-12-06 18:00:37 -0800315 mTotalTimeVisible += right.mTotalTimeVisible;
Hui Yue361a232018-10-04 15:05:21 -0700316 mTotalTimeForegroundServiceUsed += right.mTotalTimeForegroundServiceUsed;
Adam Lesinski35168002014-07-21 15:25:30 -0700317 mLaunchCount += right.mLaunchCount;
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700318 mAppLaunchCount += right.mAppLaunchCount;
Kang Li53b43142016-11-14 14:38:25 -0800319 if (mChooserCounts == null) {
320 mChooserCounts = right.mChooserCounts;
321 } else if (right.mChooserCounts != null) {
322 final int chooserCountsSize = right.mChooserCounts.size();
323 for (int i = 0; i < chooserCountsSize; i++) {
324 String action = right.mChooserCounts.keyAt(i);
325 ArrayMap<String, Integer> counts = right.mChooserCounts.valueAt(i);
326 if (!mChooserCounts.containsKey(action) || mChooserCounts.get(action) == null) {
327 mChooserCounts.put(action, counts);
328 continue;
329 }
330 final int annotationSize = counts.size();
331 for (int j = 0; j < annotationSize; j++) {
332 String key = counts.keyAt(j);
333 int rightValue = counts.valueAt(j);
334 int leftValue = mChooserCounts.get(action).getOrDefault(key, 0);
335 mChooserCounts.get(action).put(key, leftValue + rightValue);
336 }
337 }
338 }
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700339 }
340
Hui Yue361a232018-10-04 15:05:21 -0700341 /**
Hui Yu03d12402018-12-06 18:00:37 -0800342 * Tell if any activity is in foreground.
343 * @return
Hui Yue361a232018-10-04 15:05:21 -0700344 */
Hui Yu03d12402018-12-06 18:00:37 -0800345 private boolean hasForegroundActivity() {
346 final int size = mActivities.size();
347 for (int i = 0; i < size; i++) {
348 if (mActivities.valueAt(i) == ACTIVITY_RESUMED) {
349 return true;
350 }
351 }
352 return false;
Hui Yue361a232018-10-04 15:05:21 -0700353 }
354
355 /**
Hui Yu03d12402018-12-06 18:00:37 -0800356 * Tell if any activity is visible.
357 * @return
Hui Yue361a232018-10-04 15:05:21 -0700358 */
Hui Yu03d12402018-12-06 18:00:37 -0800359 private boolean hasVisibleActivity() {
360 final int size = mActivities.size();
361 for (int i = 0; i < size; i++) {
362 final int type = mActivities.valueAt(i);
363 if (type == ACTIVITY_RESUMED
364 || type == ACTIVITY_PAUSED) {
365 return true;
366 }
367 }
368 return false;
Hui Yue361a232018-10-04 15:05:21 -0700369 }
370
371 /**
Hui Yu03d12402018-12-06 18:00:37 -0800372 * Tell if any foreground service is started.
373 * @return
Hui Yue361a232018-10-04 15:05:21 -0700374 */
Hui Yu03d12402018-12-06 18:00:37 -0800375 private boolean anyForegroundServiceStarted() {
376 return !mForegroundServices.isEmpty();
377 }
378
379 /**
380 * Increment total time in foreground and update last time in foreground.
381 * @param timeStamp current timestamp.
382 */
383 private void incrementTimeUsed(long timeStamp) {
384 if (timeStamp > mLastTimeUsed) {
385 mTotalTimeInForeground += timeStamp - mLastTimeUsed;
386 mLastTimeUsed = timeStamp;
387 }
388 }
389
390 /**
391 * Increment total time visible and update last time visible.
392 * @param timeStamp current timestmap.
393 */
394 private void incrementTimeVisible(long timeStamp) {
395 if (timeStamp > mLastTimeVisible) {
396 mTotalTimeVisible += timeStamp - mLastTimeVisible;
397 mLastTimeVisible = timeStamp;
398 }
399 }
400
401 /**
402 * Increment total time foreground service is used and update last time foreground service is
403 * used.
404 * @param timeStamp current timestamp.
405 */
406 private void incrementServiceTimeUsed(long timeStamp) {
407 if (timeStamp > mLastTimeForegroundServiceUsed) {
408 mTotalTimeForegroundServiceUsed +=
409 timeStamp - mLastTimeForegroundServiceUsed;
410 mLastTimeForegroundServiceUsed = timeStamp;
411 }
Hui Yue361a232018-10-04 15:05:21 -0700412 }
413
414 /**
415 * Update by an event of an activity.
416 * @param className className of the activity.
417 * @param timeStamp timeStamp of the event.
418 * @param eventType type of the event.
Hui Yu03d12402018-12-06 18:00:37 -0800419 * @param instanceId hashCode of the ActivityRecord's appToken.
Hui Yue361a232018-10-04 15:05:21 -0700420 * @hide
421 */
Hui Yu03d12402018-12-06 18:00:37 -0800422 private void updateActivity(String className, long timeStamp, int eventType, int instanceId) {
423 if (eventType != ACTIVITY_RESUMED
424 && eventType != ACTIVITY_PAUSED
425 && eventType != ACTIVITY_STOPPED
426 && eventType != ACTIVITY_DESTROYED) {
Hui Yue361a232018-10-04 15:05:21 -0700427 return;
428 }
429
Hui Yu03d12402018-12-06 18:00:37 -0800430 // update usage.
431 final int index = mActivities.indexOfKey(instanceId);
432 if (index >= 0) {
433 final int lastEvent = mActivities.valueAt(index);
434 switch (lastEvent) {
435 case ACTIVITY_RESUMED:
436 incrementTimeUsed(timeStamp);
437 incrementTimeVisible(timeStamp);
438 break;
439 case ACTIVITY_PAUSED:
440 incrementTimeVisible(timeStamp);
441 break;
442 default:
443 break;
444 }
445 }
446
447 // update current event.
448 switch(eventType) {
449 case ACTIVITY_RESUMED:
450 if (!hasVisibleActivity()) {
451 // this is the first visible activity.
452 mLastTimeUsed = timeStamp;
453 mLastTimeVisible = timeStamp;
454 } else if (!hasForegroundActivity()) {
455 // this is the first foreground activity.
Hui Yue361a232018-10-04 15:05:21 -0700456 mLastTimeUsed = timeStamp;
457 }
Hui Yu03d12402018-12-06 18:00:37 -0800458 mActivities.put(instanceId, eventType);
459 break;
460 case ACTIVITY_PAUSED:
461 if (!hasVisibleActivity()) {
462 // this is the first visible activity.
463 mLastTimeVisible = timeStamp;
464 }
465 mActivities.put(instanceId, eventType);
466 break;
467 case ACTIVITY_STOPPED:
Hui Yu03d12402018-12-06 18:00:37 -0800468 case ACTIVITY_DESTROYED:
469 // remove activity from the map.
470 mActivities.delete(instanceId);
471 break;
472 default:
473 break;
Hui Yue361a232018-10-04 15:05:21 -0700474 }
475 }
476
477 /**
478 * Update by an event of an foreground service.
479 * @param className className of the foreground service.
480 * @param timeStamp timeStamp of the event.
481 * @param eventType type of the event.
482 * @hide
483 */
484 private void updateForegroundService(String className, long timeStamp, int eventType) {
485 if (eventType != FOREGROUND_SERVICE_STOP
Hui Yu03d12402018-12-06 18:00:37 -0800486 && eventType != FOREGROUND_SERVICE_START) {
Hui Yue361a232018-10-04 15:05:21 -0700487 return;
488 }
Hui Yu03d12402018-12-06 18:00:37 -0800489 final Integer lastEvent = mForegroundServices.get(className);
490 // update usage.
Hui Yue361a232018-10-04 15:05:21 -0700491 if (lastEvent != null) {
Hui Yu03d12402018-12-06 18:00:37 -0800492 switch (lastEvent) {
493 case FOREGROUND_SERVICE_START:
494 case CONTINUING_FOREGROUND_SERVICE:
495 incrementServiceTimeUsed(timeStamp);
496 break;
497 default:
498 break;
499 }
500 }
501
502 // update current event.
503 switch (eventType) {
504 case FOREGROUND_SERVICE_START:
505 if (!anyForegroundServiceStarted()) {
Hui Yue361a232018-10-04 15:05:21 -0700506 mLastTimeForegroundServiceUsed = timeStamp;
507 }
Hui Yu03d12402018-12-06 18:00:37 -0800508 mForegroundServices.put(className, eventType);
509 break;
510 case FOREGROUND_SERVICE_STOP:
511 mForegroundServices.remove(className);
512 break;
513 default:
514 break;
Hui Yue361a232018-10-04 15:05:21 -0700515 }
516 }
517
518 /**
519 * Update the UsageStats by a activity or foreground service event.
Hui Yu03d12402018-12-06 18:00:37 -0800520 * @param className class name of a activity or foreground service, could be null to if this
521 * is sent to all activities/services in this package.
Hui Yue361a232018-10-04 15:05:21 -0700522 * @param timeStamp Epoch timestamp in milliseconds.
523 * @param eventType event type as in {@link UsageEvents.Event}
Hui Yu03d12402018-12-06 18:00:37 -0800524 * @param instanceId if className is an activity, the hashCode of ActivityRecord's appToken.
525 * if className is not an activity, instanceId is not used.
Hui Yue361a232018-10-04 15:05:21 -0700526 * @hide
527 */
Hui Yu03d12402018-12-06 18:00:37 -0800528 public void update(String className, long timeStamp, int eventType, int instanceId) {
Hui Yue361a232018-10-04 15:05:21 -0700529 switch(eventType) {
Hui Yu03d12402018-12-06 18:00:37 -0800530 case ACTIVITY_RESUMED:
531 case ACTIVITY_PAUSED:
532 case ACTIVITY_STOPPED:
533 case ACTIVITY_DESTROYED:
534 updateActivity(className, timeStamp, eventType, instanceId);
Hui Yue361a232018-10-04 15:05:21 -0700535 break;
536 case END_OF_DAY:
Hui Yu03d12402018-12-06 18:00:37 -0800537 // END_OF_DAY updates all activities.
538 if (hasForegroundActivity()) {
539 incrementTimeUsed(timeStamp);
540 }
541 if (hasVisibleActivity()) {
542 incrementTimeVisible(timeStamp);
Hui Yue361a232018-10-04 15:05:21 -0700543 }
544 break;
Hui Yue361a232018-10-04 15:05:21 -0700545 case FOREGROUND_SERVICE_START:
Hui Yu03d12402018-12-06 18:00:37 -0800546 case FOREGROUND_SERVICE_STOP:
Hui Yue361a232018-10-04 15:05:21 -0700547 updateForegroundService(className, timeStamp, eventType);
548 break;
549 case ROLLOVER_FOREGROUND_SERVICE:
Hui Yu03d12402018-12-06 18:00:37 -0800550 // ROLLOVER_FOREGROUND_SERVICE updates all foreground services.
551 if (anyForegroundServiceStarted()) {
552 incrementServiceTimeUsed(timeStamp);
Hui Yue361a232018-10-04 15:05:21 -0700553 }
554 break;
555 case CONTINUING_FOREGROUND_SERVICE:
556 mLastTimeForegroundServiceUsed = timeStamp;
Hui Yu03d12402018-12-06 18:00:37 -0800557 mForegroundServices.put(className, eventType);
558 break;
Hui Yub1d243a2018-12-13 12:02:00 -0800559 case DEVICE_SHUTDOWN:
Hui Yu03d12402018-12-06 18:00:37 -0800560 case FLUSH_TO_DISK:
561 // update usage of all active activities/services.
562 if (hasForegroundActivity()) {
563 incrementTimeUsed(timeStamp);
564 }
565 if (hasVisibleActivity()) {
566 incrementTimeVisible(timeStamp);
567 }
568 if (anyForegroundServiceStarted()) {
569 incrementServiceTimeUsed(timeStamp);
570 }
Hui Yue361a232018-10-04 15:05:21 -0700571 break;
572 default:
573 break;
574 }
575 mEndTimeStamp = timeStamp;
576
Hui Yu03d12402018-12-06 18:00:37 -0800577 if (eventType == ACTIVITY_RESUMED) {
Hui Yue361a232018-10-04 15:05:21 -0700578 mLaunchCount += 1;
579 }
580 }
581
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700582 @Override
583 public int describeContents() {
584 return 0;
585 }
586
587 @Override
588 public void writeToParcel(Parcel dest, int flags) {
Adam Lesinski35168002014-07-21 15:25:30 -0700589 dest.writeString(mPackageName);
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700590 dest.writeLong(mBeginTimeStamp);
591 dest.writeLong(mEndTimeStamp);
Adam Lesinski35168002014-07-21 15:25:30 -0700592 dest.writeLong(mLastTimeUsed);
Hui Yu03d12402018-12-06 18:00:37 -0800593 dest.writeLong(mLastTimeVisible);
Hui Yue361a232018-10-04 15:05:21 -0700594 dest.writeLong(mLastTimeForegroundServiceUsed);
Adam Lesinski35168002014-07-21 15:25:30 -0700595 dest.writeLong(mTotalTimeInForeground);
Hui Yu03d12402018-12-06 18:00:37 -0800596 dest.writeLong(mTotalTimeVisible);
Hui Yue361a232018-10-04 15:05:21 -0700597 dest.writeLong(mTotalTimeForegroundServiceUsed);
Adam Lesinski35168002014-07-21 15:25:30 -0700598 dest.writeInt(mLaunchCount);
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700599 dest.writeInt(mAppLaunchCount);
Adam Lesinski35168002014-07-21 15:25:30 -0700600 dest.writeInt(mLastEvent);
Kang Li53b43142016-11-14 14:38:25 -0800601 Bundle allCounts = new Bundle();
602 if (mChooserCounts != null) {
603 final int chooserCountSize = mChooserCounts.size();
604 for (int i = 0; i < chooserCountSize; i++) {
605 String action = mChooserCounts.keyAt(i);
606 ArrayMap<String, Integer> counts = mChooserCounts.valueAt(i);
607 Bundle currentCounts = new Bundle();
608 final int annotationSize = counts.size();
609 for (int j = 0; j < annotationSize; j++) {
610 currentCounts.putInt(counts.keyAt(j), counts.valueAt(j));
611 }
612 allCounts.putBundle(action, currentCounts);
613 }
614 }
615 dest.writeBundle(allCounts);
Hui Yue361a232018-10-04 15:05:21 -0700616
Hui Yu03d12402018-12-06 18:00:37 -0800617 writeSparseIntArray(dest, mActivities);
618 dest.writeBundle(eventMapToBundle(mForegroundServices));
619 }
Hui Yue361a232018-10-04 15:05:21 -0700620
Hui Yu03d12402018-12-06 18:00:37 -0800621 private void writeSparseIntArray(Parcel dest, SparseIntArray arr) {
622 final int size = arr.size();
623 dest.writeInt(size);
624 for (int i = 0; i < size; i++) {
625 dest.writeInt(arr.keyAt(i));
626 dest.writeInt(arr.valueAt(i));
Hui Yue361a232018-10-04 15:05:21 -0700627 }
Hui Yu03d12402018-12-06 18:00:37 -0800628 }
629
630 private Bundle eventMapToBundle(ArrayMap<String, Integer> eventMap) {
631 final Bundle bundle = new Bundle();
632 final int size = eventMap.size();
633 for (int i = 0; i < size; i++) {
634 bundle.putInt(eventMap.keyAt(i), eventMap.valueAt(i));
635 }
636 return bundle;
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700637 }
638
639 public static final Creator<UsageStats> CREATOR = new Creator<UsageStats>() {
640 @Override
641 public UsageStats createFromParcel(Parcel in) {
642 UsageStats stats = new UsageStats();
Adam Lesinski35168002014-07-21 15:25:30 -0700643 stats.mPackageName = in.readString();
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700644 stats.mBeginTimeStamp = in.readLong();
645 stats.mEndTimeStamp = in.readLong();
Adam Lesinski35168002014-07-21 15:25:30 -0700646 stats.mLastTimeUsed = in.readLong();
Hui Yu03d12402018-12-06 18:00:37 -0800647 stats.mLastTimeVisible = in.readLong();
Hui Yue361a232018-10-04 15:05:21 -0700648 stats.mLastTimeForegroundServiceUsed = in.readLong();
Adam Lesinski35168002014-07-21 15:25:30 -0700649 stats.mTotalTimeInForeground = in.readLong();
Hui Yu03d12402018-12-06 18:00:37 -0800650 stats.mTotalTimeVisible = in.readLong();
Hui Yue361a232018-10-04 15:05:21 -0700651 stats.mTotalTimeForegroundServiceUsed = in.readLong();
Adam Lesinski35168002014-07-21 15:25:30 -0700652 stats.mLaunchCount = in.readInt();
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700653 stats.mAppLaunchCount = in.readInt();
Adam Lesinski35168002014-07-21 15:25:30 -0700654 stats.mLastEvent = in.readInt();
Kang Li53b43142016-11-14 14:38:25 -0800655 Bundle allCounts = in.readBundle();
656 if (allCounts != null) {
657 stats.mChooserCounts = new ArrayMap<>();
658 for (String action : allCounts.keySet()) {
659 if (!stats.mChooserCounts.containsKey(action)) {
660 ArrayMap<String, Integer> newCounts = new ArrayMap<>();
661 stats.mChooserCounts.put(action, newCounts);
662 }
663 Bundle currentCounts = allCounts.getBundle(action);
664 if (currentCounts != null) {
665 for (String key : currentCounts.keySet()) {
666 int value = currentCounts.getInt(key);
667 if (value > 0) {
668 stats.mChooserCounts.get(action).put(key, value);
669 }
670 }
671 }
672 }
673 }
Hui Yu03d12402018-12-06 18:00:37 -0800674 readSparseIntArray(in, stats.mActivities);
675 readBundleToEventMap(in.readBundle(), stats.mForegroundServices);
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700676 return stats;
677 }
678
Hui Yu03d12402018-12-06 18:00:37 -0800679 private void readSparseIntArray(Parcel in, SparseIntArray arr) {
680 final int size = in.readInt();
681 for (int i = 0; i < size; i++) {
682 final int key = in.readInt();
683 final int value = in.readInt();
684 arr.put(key, value);
685 }
686 }
687
688 private void readBundleToEventMap(Bundle bundle, ArrayMap<String, Integer> eventMap) {
Hui Yue361a232018-10-04 15:05:21 -0700689 if (bundle != null) {
690 for (String className : bundle.keySet()) {
691 final int event = bundle.getInt(className);
692 eventMap.put(className, event);
693 }
694 }
695 }
696
Adam Lesinski0debc9a2014-07-16 19:09:13 -0700697 @Override
698 public UsageStats[] newArray(int size) {
699 return new UsageStats[size];
700 }
701 };
702}