blob: 4d711128da76927cf5e4c5d34ef5be1d91fdd9aa [file] [log] [blame]
Adam Lesinski35168002014-07-21 15:25:30 -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
Adam Lesinski3c153512014-07-23 17:34:34 -070017package com.android.server.usage;
18
Hui Yub1d243a2018-12-13 12:02:00 -080019import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN;
Hui Yu80a8b462019-03-05 15:22:13 -080020import static android.app.usage.UsageEvents.Event.DEVICE_STARTUP;
Hui Yu03d12402018-12-06 18:00:37 -080021import static android.app.usage.UsageStatsManager.INTERVAL_BEST;
22import static android.app.usage.UsageStatsManager.INTERVAL_COUNT;
23import static android.app.usage.UsageStatsManager.INTERVAL_DAILY;
24import static android.app.usage.UsageStatsManager.INTERVAL_MONTHLY;
25import static android.app.usage.UsageStatsManager.INTERVAL_WEEKLY;
26import static android.app.usage.UsageStatsManager.INTERVAL_YEARLY;
27
Adam Lesinski7f61e962014-09-02 16:43:52 -070028import android.app.usage.ConfigurationStats;
Suprabh Shukla60aa35b2018-04-24 18:52:46 -070029import android.app.usage.EventList;
Dianne Hackbornced54392018-02-26 13:07:42 -080030import android.app.usage.EventStats;
Varun Shah5bef1be2019-05-07 22:35:22 -070031import android.app.usage.TimeSparseArray;
Adam Lesinski35168002014-07-21 15:25:30 -070032import android.app.usage.UsageEvents;
Hui Yu03d12402018-12-06 18:00:37 -080033import android.app.usage.UsageEvents.Event;
Adam Lesinski3c153512014-07-23 17:34:34 -070034import android.app.usage.UsageStats;
35import android.app.usage.UsageStatsManager;
Hui Yue361a232018-10-04 15:05:21 -070036import android.content.Context;
Adam Lesinski7f61e962014-09-02 16:43:52 -070037import android.content.res.Configuration;
Adam Lesinski66143fa2014-09-11 08:31:05 -070038import android.os.SystemClock;
Adam Lesinski1bb18c42014-08-18 12:21:34 -070039import android.text.format.DateUtils;
40import android.util.ArrayMap;
Adam Lesinski3c153512014-07-23 17:34:34 -070041import android.util.ArraySet;
Varun Shah5bef1be2019-05-07 22:35:22 -070042import android.util.AtomicFile;
Adam Lesinski3c153512014-07-23 17:34:34 -070043import android.util.Slog;
Hui Yu03d12402018-12-06 18:00:37 -080044import android.util.SparseIntArray;
Adam Lesinski3c153512014-07-23 17:34:34 -070045
Varun Shah2c0b9f52019-11-26 16:41:13 -080046import com.android.internal.util.ArrayUtils;
Adam Lesinski1bb18c42014-08-18 12:21:34 -070047import com.android.internal.util.IndentingPrintWriter;
Adam Lesinski7f61e962014-09-02 16:43:52 -070048import com.android.server.usage.UsageStatsDatabase.StatCombiner;
49
Adam Lesinski3c153512014-07-23 17:34:34 -070050import java.io.File;
51import java.io.IOException;
52import java.text.SimpleDateFormat;
Adam Lesinski35168002014-07-21 15:25:30 -070053import java.util.ArrayList;
54import java.util.Arrays;
Varun Shah2c0b9f52019-11-26 16:41:13 -080055import java.util.HashMap;
Adam Lesinski35168002014-07-21 15:25:30 -070056import java.util.List;
Adam Lesinski3c153512014-07-23 17:34:34 -070057
58/**
59 * A per-user UsageStatsService. All methods are meant to be called with the main lock held
60 * in UsageStatsService.
61 */
62class UserUsageStatsService {
63 private static final String TAG = "UsageStatsService";
64 private static final boolean DEBUG = UsageStatsService.DEBUG;
Michael Wachenschwanz1088cbb2018-03-01 12:45:16 -080065 private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Adam Lesinski1bb18c42014-08-18 12:21:34 -070066 private static final int sDateFormatFlags =
67 DateUtils.FORMAT_SHOW_DATE
68 | DateUtils.FORMAT_SHOW_TIME
69 | DateUtils.FORMAT_SHOW_YEAR
70 | DateUtils.FORMAT_NUMERIC_DATE;
Adam Lesinski3c153512014-07-23 17:34:34 -070071
Adam Lesinski1bb18c42014-08-18 12:21:34 -070072 private final Context mContext;
Adam Lesinski3c153512014-07-23 17:34:34 -070073 private final UsageStatsDatabase mDatabase;
Adam Lesinski35168002014-07-21 15:25:30 -070074 private final IntervalStats[] mCurrentStats;
Adam Lesinski3c153512014-07-23 17:34:34 -070075 private boolean mStatsChanged = false;
Adam Lesinskid26bea32014-09-03 16:49:59 -070076 private final UnixCalendar mDailyExpiryDate;
Adam Lesinski3c153512014-07-23 17:34:34 -070077 private final StatsUpdatedListener mListener;
78 private final String mLogPrefix;
Amith Yamasanibc813eb2018-03-20 19:37:46 -070079 private String mLastBackgroundedPackage;
Amith Yamasani55717a62015-04-03 17:22:36 -070080 private final int mUserId;
Varun Shah5e1613e2019-09-05 11:50:18 -070081 private long mRealTimeSnapshot;
82 private long mSystemTimeSnapshot;
Adam Lesinski3c153512014-07-23 17:34:34 -070083
Adam Lesinski7cba1d42015-08-04 16:17:37 -070084 private static final long[] INTERVAL_LENGTH = new long[] {
85 UnixCalendar.DAY_IN_MILLIS, UnixCalendar.WEEK_IN_MILLIS,
86 UnixCalendar.MONTH_IN_MILLIS, UnixCalendar.YEAR_IN_MILLIS
87 };
88
Adam Lesinski3c153512014-07-23 17:34:34 -070089 interface StatsUpdatedListener {
90 void onStatsUpdated();
Adam Lesinskib2d3ffa2016-01-26 18:18:19 -080091 void onStatsReloaded();
Amith Yamasania93542f2016-02-03 18:02:06 -080092 /**
93 * Callback that a system update was detected
94 * @param mUserId user that needs to be initialized
95 */
96 void onNewUpdate(int mUserId);
Adam Lesinski3c153512014-07-23 17:34:34 -070097 }
98
Amith Yamasanib0ff3222015-03-04 09:56:14 -080099 UserUsageStatsService(Context context, int userId, File usageStatsDir,
100 StatsUpdatedListener listener) {
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700101 mContext = context;
Adam Lesinskid26bea32014-09-03 16:49:59 -0700102 mDailyExpiryDate = new UnixCalendar(0);
Adam Lesinski3c153512014-07-23 17:34:34 -0700103 mDatabase = new UsageStatsDatabase(usageStatsDir);
Hui Yu03d12402018-12-06 18:00:37 -0800104 mCurrentStats = new IntervalStats[INTERVAL_COUNT];
Adam Lesinski3c153512014-07-23 17:34:34 -0700105 mListener = listener;
106 mLogPrefix = "User[" + Integer.toString(userId) + "] ";
Amith Yamasani55717a62015-04-03 17:22:36 -0700107 mUserId = userId;
Varun Shah5e1613e2019-09-05 11:50:18 -0700108 mRealTimeSnapshot = SystemClock.elapsedRealtime();
109 mSystemTimeSnapshot = System.currentTimeMillis();
Adam Lesinski3c153512014-07-23 17:34:34 -0700110 }
111
Varun Shah2c0b9f52019-11-26 16:41:13 -0800112 void init(final long currentTimeMillis, HashMap<String, Long> installedPackages) {
113 readPackageMappingsLocked(installedPackages);
Adam Lesinski66143fa2014-09-11 08:31:05 -0700114 mDatabase.init(currentTimeMillis);
Varun Shah2c0b9f52019-11-26 16:41:13 -0800115 if (mDatabase.wasUpgradePerformed()) {
116 mDatabase.prunePackagesDataOnUpgrade(installedPackages);
117 }
Adam Lesinski3c153512014-07-23 17:34:34 -0700118
119 int nullCount = 0;
120 for (int i = 0; i < mCurrentStats.length; i++) {
121 mCurrentStats[i] = mDatabase.getLatestUsageStats(i);
122 if (mCurrentStats[i] == null) {
Adam Lesinski35168002014-07-21 15:25:30 -0700123 // Find out how many intervals we don't have data for.
124 // Ideally it should be all or none.
Adam Lesinski3c153512014-07-23 17:34:34 -0700125 nullCount++;
126 }
127 }
128
129 if (nullCount > 0) {
130 if (nullCount != mCurrentStats.length) {
131 // This is weird, but we shouldn't fail if something like this
132 // happens.
133 Slog.w(TAG, mLogPrefix + "Some stats have no latest available");
134 } else {
135 // This must be first boot.
136 }
137
138 // By calling loadActiveStats, we will
139 // generate new stats for each bucket.
Amith Yamasania93542f2016-02-03 18:02:06 -0800140 loadActiveStats(currentTimeMillis);
Adam Lesinski3c153512014-07-23 17:34:34 -0700141 } else {
142 // Set up the expiry date to be one day from the latest daily stat.
143 // This may actually be today and we will rollover on the first event
144 // that is reported.
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700145 updateRolloverDeadline();
Adam Lesinski3c153512014-07-23 17:34:34 -0700146 }
147
Hui Yub1d243a2018-12-13 12:02:00 -0800148 // During system reboot, add a DEVICE_SHUTDOWN event to the end of event list, the timestamp
Hui Yuf7ca8892019-09-03 17:45:49 -0700149 // is last time UsageStatsDatabase is persisted to disk or the last event's time whichever
150 // is higher (because the file system timestamp is round down to integral seconds).
Hui Yu80a8b462019-03-05 15:22:13 -0800151 // Also add a DEVICE_STARTUP event with current system timestamp.
Hui Yub1d243a2018-12-13 12:02:00 -0800152 final IntervalStats currentDailyStats = mCurrentStats[INTERVAL_DAILY];
153 if (currentDailyStats != null) {
Hui Yuf7ca8892019-09-03 17:45:49 -0700154 final Event shutdownEvent = new Event(DEVICE_SHUTDOWN,
155 Math.max(currentDailyStats.lastTimeSaved, currentDailyStats.endTime));
Hui Yu80a8b462019-03-05 15:22:13 -0800156 shutdownEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
157 currentDailyStats.addEvent(shutdownEvent);
Hui Yuf7ca8892019-09-03 17:45:49 -0700158 final Event startupEvent = new Event(DEVICE_STARTUP, System.currentTimeMillis());
Hui Yu80a8b462019-03-05 15:22:13 -0800159 startupEvent.mPackage = Event.DEVICE_EVENT_PACKAGE_NAME;
160 currentDailyStats.addEvent(startupEvent);
Hui Yub1d243a2018-12-13 12:02:00 -0800161 }
162
Amith Yamasani55717a62015-04-03 17:22:36 -0700163 if (mDatabase.isNewUpdate()) {
Amith Yamasania93542f2016-02-03 18:02:06 -0800164 notifyNewUpdate();
Amith Yamasani55717a62015-04-03 17:22:36 -0700165 }
166 }
167
Varun Shah3a315202019-07-24 16:33:42 -0700168 void userStopped() {
169 // Flush events to disk immediately to guarantee persistence.
170 persistActiveStats();
171 }
172
Varun Shah2c0b9f52019-11-26 16:41:13 -0800173 int onPackageRemoved(String packageName, long timeRemoved) {
174 return mDatabase.onPackageRemoved(packageName, timeRemoved);
Varun Shah23033b02019-10-07 14:41:12 -0700175 }
176
Varun Shah2c0b9f52019-11-26 16:41:13 -0800177 private void readPackageMappingsLocked(HashMap<String, Long> installedPackages) {
Varun Shah23033b02019-10-07 14:41:12 -0700178 mDatabase.readMappingsLocked();
Varun Shah2c0b9f52019-11-26 16:41:13 -0800179 updatePackageMappingsLocked(installedPackages);
Varun Shah23033b02019-10-07 14:41:12 -0700180 }
181
182 /**
Varun Shah2c0b9f52019-11-26 16:41:13 -0800183 * Queries Job Scheduler for any pending data prune jobs and if any exist, it updates the
184 * package mappings in memory by removing those tokens.
Varun Shah23033b02019-10-07 14:41:12 -0700185 * This will only happen once per device boot, when the user is unlocked for the first time.
Varun Shah2c0b9f52019-11-26 16:41:13 -0800186 *
187 * @param installedPackages map of installed packages (package_name:package_install_time)
Varun Shah23033b02019-10-07 14:41:12 -0700188 */
Varun Shah2c0b9f52019-11-26 16:41:13 -0800189 private void updatePackageMappingsLocked(HashMap<String, Long> installedPackages) {
190 if (ArrayUtils.isEmpty(installedPackages)) {
Varun Shah23033b02019-10-07 14:41:12 -0700191 return;
192 }
Varun Shah2c0b9f52019-11-26 16:41:13 -0800193
194 final long timeNow = System.currentTimeMillis();
195 final ArrayList<String> removedPackages = new ArrayList<>();
Varun Shah23033b02019-10-07 14:41:12 -0700196 // populate list of packages that are found in the mappings but not in the installed list
197 for (int i = mDatabase.mPackagesTokenData.packagesToTokensMap.size() - 1; i >= 0; i--) {
Varun Shah2c0b9f52019-11-26 16:41:13 -0800198 final String packageName = mDatabase.mPackagesTokenData.packagesToTokensMap.keyAt(i);
199 if (!installedPackages.containsKey(packageName)) {
200 removedPackages.add(packageName);
Varun Shah23033b02019-10-07 14:41:12 -0700201 }
202 }
Varun Shah2c0b9f52019-11-26 16:41:13 -0800203 if (removedPackages.isEmpty()) {
204 return;
205 }
Varun Shah23033b02019-10-07 14:41:12 -0700206
Varun Shah2c0b9f52019-11-26 16:41:13 -0800207 // remove packages in the mappings that are no longer installed and persist to disk
Varun Shah23033b02019-10-07 14:41:12 -0700208 for (int i = removedPackages.size() - 1; i >= 0; i--) {
209 mDatabase.mPackagesTokenData.removePackage(removedPackages.get(i), timeNow);
210 }
Varun Shah2c0b9f52019-11-26 16:41:13 -0800211 try {
212 mDatabase.writeMappingsLocked();
213 } catch (Exception e) {
214 Slog.w(TAG, "Unable to write updated package mappings file on service initialization.");
215 }
216 }
217
218 boolean pruneUninstalledPackagesData() {
219 return mDatabase.pruneUninstalledPackagesData();
Varun Shah23033b02019-10-07 14:41:12 -0700220 }
221
Varun Shah5e1613e2019-09-05 11:50:18 -0700222 private void onTimeChanged(long oldTime, long newTime) {
Adam Lesinski66143fa2014-09-11 08:31:05 -0700223 persistActiveStats();
224 mDatabase.onTimeChanged(newTime - oldTime);
Amith Yamasania93542f2016-02-03 18:02:06 -0800225 loadActiveStats(newTime);
Adam Lesinski66143fa2014-09-11 08:31:05 -0700226 }
227
Varun Shah5e1613e2019-09-05 11:50:18 -0700228 /**
229 * This should be the only way to get the time from the system.
230 */
231 private long checkAndGetTimeLocked() {
232 final long actualSystemTime = System.currentTimeMillis();
233 if (!UsageStatsService.ENABLE_TIME_CHANGE_CORRECTION) {
234 return actualSystemTime;
235 }
236 final long actualRealtime = SystemClock.elapsedRealtime();
237 final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot;
238 final long diffSystemTime = actualSystemTime - expectedSystemTime;
239 if (Math.abs(diffSystemTime) > UsageStatsService.TIME_CHANGE_THRESHOLD_MILLIS) {
240 // The time has changed.
241 Slog.i(TAG, mLogPrefix + "Time changed in by " + (diffSystemTime / 1000) + " seconds");
242 onTimeChanged(expectedSystemTime, actualSystemTime);
243 mRealTimeSnapshot = actualRealtime;
244 mSystemTimeSnapshot = actualSystemTime;
245 }
246 return actualSystemTime;
247 }
248
249 /**
250 * Assuming the event's timestamp is measured in milliseconds since boot,
251 * convert it to a system wall time.
252 */
253 private void convertToSystemTimeLocked(Event event) {
254 event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot;
255 }
256
Hui Yu03d12402018-12-06 18:00:37 -0800257 void reportEvent(Event event) {
Adam Lesinski3c153512014-07-23 17:34:34 -0700258 if (DEBUG) {
Adam Lesinski9d960752014-08-25 14:48:12 -0700259 Slog.d(TAG, mLogPrefix + "Got usage event for " + event.mPackage
Adam Lesinski7f61e962014-09-02 16:43:52 -0700260 + "[" + event.mTimeStamp + "]: "
261 + eventToString(event.mEventType));
Adam Lesinski3c153512014-07-23 17:34:34 -0700262 }
263
Varun Shah5e1613e2019-09-05 11:50:18 -0700264 checkAndGetTimeLocked();
265 convertToSystemTimeLocked(event);
266
Adam Lesinski7f61e962014-09-02 16:43:52 -0700267 if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) {
Adam Lesinski3c153512014-07-23 17:34:34 -0700268 // Need to rollover
Amith Yamasania93542f2016-02-03 18:02:06 -0800269 rolloverStats(event.mTimeStamp);
Adam Lesinski3c153512014-07-23 17:34:34 -0700270 }
271
Hui Yu03d12402018-12-06 18:00:37 -0800272 final IntervalStats currentDailyStats = mCurrentStats[INTERVAL_DAILY];
Adam Lesinski7f61e962014-09-02 16:43:52 -0700273
274 final Configuration newFullConfig = event.mConfiguration;
Hui Yu03d12402018-12-06 18:00:37 -0800275 if (event.mEventType == Event.CONFIGURATION_CHANGE
276 && currentDailyStats.activeConfiguration != null) {
Adam Lesinski7f61e962014-09-02 16:43:52 -0700277 // Make the event configuration a delta.
278 event.mConfiguration = Configuration.generateDelta(
279 currentDailyStats.activeConfiguration, newFullConfig);
Adam Lesinski35168002014-07-21 15:25:30 -0700280 }
Adam Lesinski7f61e962014-09-02 16:43:52 -0700281
Hui Yu03d12402018-12-06 18:00:37 -0800282 if (event.mEventType != Event.SYSTEM_INTERACTION
283 // ACTIVITY_DESTROYED is a private event. If there is preceding ACTIVITY_STOPPED
284 // ACTIVITY_DESTROYED will be dropped. Otherwise it will be converted to
285 // ACTIVITY_STOPPED.
286 && event.mEventType != Event.ACTIVITY_DESTROYED
287 // FLUSH_TO_DISK is a private event.
Hui Yub1d243a2018-12-13 12:02:00 -0800288 && event.mEventType != Event.FLUSH_TO_DISK
289 // DEVICE_SHUTDOWN is added to event list after reboot.
290 && event.mEventType != Event.DEVICE_SHUTDOWN) {
Michael Wachenschwanzc90bc152018-09-10 15:17:57 -0700291 currentDailyStats.addEvent(event);
Amith Yamasanib0ff3222015-03-04 09:56:14 -0800292 }
Adam Lesinski35168002014-07-21 15:25:30 -0700293
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700294 boolean incrementAppLaunch = false;
Hui Yu03d12402018-12-06 18:00:37 -0800295 if (event.mEventType == Event.ACTIVITY_RESUMED) {
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700296 if (event.mPackage != null && !event.mPackage.equals(mLastBackgroundedPackage)) {
297 incrementAppLaunch = true;
298 }
Hui Yu03d12402018-12-06 18:00:37 -0800299 } else if (event.mEventType == Event.ACTIVITY_PAUSED) {
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700300 if (event.mPackage != null) {
301 mLastBackgroundedPackage = event.mPackage;
302 }
303 }
304
Adam Lesinski35168002014-07-21 15:25:30 -0700305 for (IntervalStats stats : mCurrentStats) {
Dianne Hackbornced54392018-02-26 13:07:42 -0800306 switch (event.mEventType) {
Hui Yu03d12402018-12-06 18:00:37 -0800307 case Event.CONFIGURATION_CHANGE: {
Dianne Hackbornced54392018-02-26 13:07:42 -0800308 stats.updateConfigurationStats(newFullConfig, event.mTimeStamp);
309 } break;
Hui Yu03d12402018-12-06 18:00:37 -0800310 case Event.CHOOSER_ACTION: {
Dianne Hackbornced54392018-02-26 13:07:42 -0800311 stats.updateChooserCounts(event.mPackage, event.mContentType, event.mAction);
312 String[] annotations = event.mContentAnnotations;
313 if (annotations != null) {
314 for (String annotation : annotations) {
315 stats.updateChooserCounts(event.mPackage, annotation, event.mAction);
316 }
Kang Li53b43142016-11-14 14:38:25 -0800317 }
Dianne Hackbornced54392018-02-26 13:07:42 -0800318 } break;
Hui Yu03d12402018-12-06 18:00:37 -0800319 case Event.SCREEN_INTERACTIVE: {
Dianne Hackbornced54392018-02-26 13:07:42 -0800320 stats.updateScreenInteractive(event.mTimeStamp);
321 } break;
Hui Yu03d12402018-12-06 18:00:37 -0800322 case Event.SCREEN_NON_INTERACTIVE: {
Dianne Hackbornced54392018-02-26 13:07:42 -0800323 stats.updateScreenNonInteractive(event.mTimeStamp);
324 } break;
Hui Yu03d12402018-12-06 18:00:37 -0800325 case Event.KEYGUARD_SHOWN: {
Dianne Hackborn3378aa92018-03-30 17:43:49 -0700326 stats.updateKeyguardShown(event.mTimeStamp);
327 } break;
Hui Yu03d12402018-12-06 18:00:37 -0800328 case Event.KEYGUARD_HIDDEN: {
Dianne Hackborn3378aa92018-03-30 17:43:49 -0700329 stats.updateKeyguardHidden(event.mTimeStamp);
330 } break;
Dianne Hackbornced54392018-02-26 13:07:42 -0800331 default: {
Hui Yue361a232018-10-04 15:05:21 -0700332 stats.update(event.mPackage, event.getClassName(),
Hui Yu03d12402018-12-06 18:00:37 -0800333 event.mTimeStamp, event.mEventType, event.mInstanceId);
Dianne Hackbornced54392018-02-26 13:07:42 -0800334 if (incrementAppLaunch) {
335 stats.incrementAppLaunchCount(event.mPackage);
336 }
337 } break;
Adam Lesinski7f61e962014-09-02 16:43:52 -0700338 }
Adam Lesinski3c153512014-07-23 17:34:34 -0700339 }
340
Amith Yamasanicf768722015-04-23 20:36:41 -0700341 notifyStatsChanged();
342 }
343
Adam Lesinski7f61e962014-09-02 16:43:52 -0700344 private static final StatCombiner<UsageStats> sUsageStatsCombiner =
345 new StatCombiner<UsageStats>() {
346 @Override
347 public void combine(IntervalStats stats, boolean mutable,
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700348 List<UsageStats> accResult) {
Adam Lesinski7f61e962014-09-02 16:43:52 -0700349 if (!mutable) {
Adam Lesinski37a46b42014-09-05 15:38:05 -0700350 accResult.addAll(stats.packageStats.values());
Adam Lesinski7f61e962014-09-02 16:43:52 -0700351 return;
352 }
353
Adam Lesinski37a46b42014-09-05 15:38:05 -0700354 final int statCount = stats.packageStats.size();
Adam Lesinski7f61e962014-09-02 16:43:52 -0700355 for (int i = 0; i < statCount; i++) {
Adam Lesinski37a46b42014-09-05 15:38:05 -0700356 accResult.add(new UsageStats(stats.packageStats.valueAt(i)));
Adam Lesinski7f61e962014-09-02 16:43:52 -0700357 }
358 }
359 };
360
361 private static final StatCombiner<ConfigurationStats> sConfigStatsCombiner =
362 new StatCombiner<ConfigurationStats>() {
363 @Override
364 public void combine(IntervalStats stats, boolean mutable,
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700365 List<ConfigurationStats> accResult) {
Adam Lesinski7f61e962014-09-02 16:43:52 -0700366 if (!mutable) {
367 accResult.addAll(stats.configurations.values());
368 return;
369 }
370
371 final int configCount = stats.configurations.size();
372 for (int i = 0; i < configCount; i++) {
373 accResult.add(new ConfigurationStats(stats.configurations.valueAt(i)));
374 }
375 }
376 };
377
Dianne Hackbornced54392018-02-26 13:07:42 -0800378 private static final StatCombiner<EventStats> sEventStatsCombiner =
379 new StatCombiner<EventStats>() {
380 @Override
381 public void combine(IntervalStats stats, boolean mutable,
382 List<EventStats> accResult) {
383 stats.addEventStatsTo(accResult);
384 }
385 };
386
Varun Shah5e1613e2019-09-05 11:50:18 -0700387 private static boolean validRange(long currentTime, long beginTime, long endTime) {
388 return beginTime <= currentTime && beginTime < endTime;
389 }
390
Adam Lesinski7f61e962014-09-02 16:43:52 -0700391 /**
392 * Generic query method that selects the appropriate IntervalStats for the specified time range
393 * and bucket, then calls the {@link com.android.server.usage.UsageStatsDatabase.StatCombiner}
394 * provided to select the stats to use from the IntervalStats object.
395 */
Adam Lesinskid26bea32014-09-03 16:49:59 -0700396 private <T> List<T> queryStats(int intervalType, final long beginTime, final long endTime,
Adam Lesinski7f61e962014-09-02 16:43:52 -0700397 StatCombiner<T> combiner) {
Hui Yu03d12402018-12-06 18:00:37 -0800398 if (intervalType == INTERVAL_BEST) {
Adam Lesinskid26bea32014-09-03 16:49:59 -0700399 intervalType = mDatabase.findBestFitBucket(beginTime, endTime);
400 if (intervalType < 0) {
401 // Nothing saved to disk yet, so every stat is just as equal (no rollover has
402 // occurred.
Hui Yu03d12402018-12-06 18:00:37 -0800403 intervalType = INTERVAL_DAILY;
Adam Lesinskid26bea32014-09-03 16:49:59 -0700404 }
Adam Lesinski35168002014-07-21 15:25:30 -0700405 }
406
Adam Lesinskid26bea32014-09-03 16:49:59 -0700407 if (intervalType < 0 || intervalType >= mCurrentStats.length) {
Adam Lesinski35168002014-07-21 15:25:30 -0700408 if (DEBUG) {
Adam Lesinskid26bea32014-09-03 16:49:59 -0700409 Slog.d(TAG, mLogPrefix + "Bad intervalType used " + intervalType);
Adam Lesinski35168002014-07-21 15:25:30 -0700410 }
411 return null;
412 }
413
Adam Lesinskid26bea32014-09-03 16:49:59 -0700414 final IntervalStats currentStats = mCurrentStats[intervalType];
Adam Lesinski35168002014-07-21 15:25:30 -0700415
Adam Lesinski3c153512014-07-23 17:34:34 -0700416 if (DEBUG) {
Adam Lesinskid26bea32014-09-03 16:49:59 -0700417 Slog.d(TAG, mLogPrefix + "SELECT * FROM " + intervalType + " WHERE beginTime >= "
Adam Lesinski35168002014-07-21 15:25:30 -0700418 + beginTime + " AND endTime < " + endTime);
Adam Lesinski3c153512014-07-23 17:34:34 -0700419 }
420
Adam Lesinskid26bea32014-09-03 16:49:59 -0700421 if (beginTime >= currentStats.endTime) {
422 if (DEBUG) {
423 Slog.d(TAG, mLogPrefix + "Requesting stats after " + beginTime + " but latest is "
424 + currentStats.endTime);
425 }
426 // Nothing newer available.
427 return null;
428 }
429
430 // Truncate the endTime to just before the in-memory stats. Then, we'll append the
431 // in-memory stats to the results (if necessary) so as to avoid writing to disk too
432 // often.
433 final long truncatedEndTime = Math.min(currentStats.beginTime, endTime);
434
435 // Get the stats from disk.
436 List<T> results = mDatabase.queryUsageStats(intervalType, beginTime,
437 truncatedEndTime, combiner);
Adam Lesinski3c153512014-07-23 17:34:34 -0700438 if (DEBUG) {
Adam Lesinskid26bea32014-09-03 16:49:59 -0700439 Slog.d(TAG, "Got " + (results != null ? results.size() : 0) + " results from disk");
440 Slog.d(TAG, "Current stats beginTime=" + currentStats.beginTime +
441 " endTime=" + currentStats.endTime);
442 }
443
444 // Now check if the in-memory stats match the range and add them if they do.
445 if (beginTime < currentStats.endTime && endTime > currentStats.beginTime) {
446 if (DEBUG) {
447 Slog.d(TAG, mLogPrefix + "Returning in-memory stats");
448 }
449
450 if (results == null) {
451 results = new ArrayList<>();
452 }
Varun Shah23033b02019-10-07 14:41:12 -0700453 mDatabase.filterStats(currentStats);
Adam Lesinskid26bea32014-09-03 16:49:59 -0700454 combiner.combine(currentStats, true, results);
455 }
456
457 if (DEBUG) {
458 Slog.d(TAG, mLogPrefix + "Results: " + (results != null ? results.size() : 0));
Adam Lesinski3c153512014-07-23 17:34:34 -0700459 }
460 return results;
461 }
462
Adam Lesinski7f61e962014-09-02 16:43:52 -0700463 List<UsageStats> queryUsageStats(int bucketType, long beginTime, long endTime) {
Varun Shah5e1613e2019-09-05 11:50:18 -0700464 if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) {
465 return null;
466 }
Adam Lesinski7f61e962014-09-02 16:43:52 -0700467 return queryStats(bucketType, beginTime, endTime, sUsageStatsCombiner);
468 }
469
470 List<ConfigurationStats> queryConfigurationStats(int bucketType, long beginTime, long endTime) {
Varun Shah5e1613e2019-09-05 11:50:18 -0700471 if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) {
472 return null;
473 }
Adam Lesinski7f61e962014-09-02 16:43:52 -0700474 return queryStats(bucketType, beginTime, endTime, sConfigStatsCombiner);
475 }
476
Dianne Hackbornced54392018-02-26 13:07:42 -0800477 List<EventStats> queryEventStats(int bucketType, long beginTime, long endTime) {
Varun Shah5e1613e2019-09-05 11:50:18 -0700478 if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) {
479 return null;
480 }
Dianne Hackbornced54392018-02-26 13:07:42 -0800481 return queryStats(bucketType, beginTime, endTime, sEventStatsCombiner);
482 }
483
Makoto Onukiad623012017-05-15 09:29:34 -0700484 UsageEvents queryEvents(final long beginTime, final long endTime,
Varun Shah01f6f262020-01-07 16:33:22 -0800485 boolean obfuscateInstantApps, boolean hideShortcutInvocationEvents) {
Varun Shah5e1613e2019-09-05 11:50:18 -0700486 if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) {
487 return null;
488 }
Adam Lesinskid26bea32014-09-03 16:49:59 -0700489 final ArraySet<String> names = new ArraySet<>();
Hui Yu03d12402018-12-06 18:00:37 -0800490 List<Event> results = queryStats(INTERVAL_DAILY,
491 beginTime, endTime, new StatCombiner<Event>() {
Adam Lesinskid26bea32014-09-03 16:49:59 -0700492 @Override
493 public void combine(IntervalStats stats, boolean mutable,
Hui Yu03d12402018-12-06 18:00:37 -0800494 List<Event> accumulatedResult) {
Suprabh Shukla60aa35b2018-04-24 18:52:46 -0700495 final int startIndex = stats.events.firstIndexOnOrAfter(beginTime);
Adam Lesinskid26bea32014-09-03 16:49:59 -0700496 final int size = stats.events.size();
497 for (int i = startIndex; i < size; i++) {
Suprabh Shukla60aa35b2018-04-24 18:52:46 -0700498 if (stats.events.get(i).mTimeStamp >= endTime) {
Adam Lesinskid26bea32014-09-03 16:49:59 -0700499 return;
500 }
Adam Lesinski35168002014-07-21 15:25:30 -0700501
Hui Yu03d12402018-12-06 18:00:37 -0800502 Event event = stats.events.get(i);
Varun Shah01f6f262020-01-07 16:33:22 -0800503 if (hideShortcutInvocationEvents
504 && event.mEventType == Event.SHORTCUT_INVOCATION) {
505 continue;
506 }
Makoto Onukiad623012017-05-15 09:29:34 -0700507 if (obfuscateInstantApps) {
508 event = event.getObfuscatedIfInstantApp();
509 }
Hui Yu03d12402018-12-06 18:00:37 -0800510 if (event.mPackage != null) {
511 names.add(event.mPackage);
512 }
Adam Lesinskid26bea32014-09-03 16:49:59 -0700513 if (event.mClass != null) {
514 names.add(event.mClass);
515 }
Michael Wachenschwanz0b4ab1f2019-01-07 13:59:10 -0800516 if (event.mTaskRootPackage != null) {
517 names.add(event.mTaskRootPackage);
518 }
519 if (event.mTaskRootClass != null) {
520 names.add(event.mTaskRootClass);
521 }
Adam Lesinskid26bea32014-09-03 16:49:59 -0700522 accumulatedResult.add(event);
523 }
524 }
525 });
526
527 if (results == null || results.isEmpty()) {
528 return null;
Adam Lesinski35168002014-07-21 15:25:30 -0700529 }
530
Adam Lesinskid26bea32014-09-03 16:49:59 -0700531 String[] table = names.toArray(new String[names.size()]);
532 Arrays.sort(table);
Michael Wachenschwanz0b4ab1f2019-01-07 13:59:10 -0800533 return new UsageEvents(results, table, true);
Adam Lesinski35168002014-07-21 15:25:30 -0700534 }
535
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800536 UsageEvents queryEventsForPackage(final long beginTime, final long endTime,
Michael Wachenschwanz0b4ab1f2019-01-07 13:59:10 -0800537 final String packageName, boolean includeTaskRoot) {
Varun Shah5e1613e2019-09-05 11:50:18 -0700538 if (!validRange(checkAndGetTimeLocked(), beginTime, endTime)) {
539 return null;
540 }
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800541 final ArraySet<String> names = new ArraySet<>();
542 names.add(packageName);
Hui Yu03d12402018-12-06 18:00:37 -0800543 final List<Event> results = queryStats(INTERVAL_DAILY,
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800544 beginTime, endTime, (stats, mutable, accumulatedResult) -> {
Suprabh Shukla60aa35b2018-04-24 18:52:46 -0700545 final int startIndex = stats.events.firstIndexOnOrAfter(beginTime);
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800546 final int size = stats.events.size();
547 for (int i = startIndex; i < size; i++) {
Suprabh Shukla60aa35b2018-04-24 18:52:46 -0700548 if (stats.events.get(i).mTimeStamp >= endTime) {
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800549 return;
550 }
551
Hui Yu03d12402018-12-06 18:00:37 -0800552 final Event event = stats.events.get(i);
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800553 if (!packageName.equals(event.mPackage)) {
554 continue;
555 }
556 if (event.mClass != null) {
557 names.add(event.mClass);
558 }
Michael Wachenschwanz0b4ab1f2019-01-07 13:59:10 -0800559 if (includeTaskRoot && event.mTaskRootPackage != null) {
560 names.add(event.mTaskRootPackage);
561 }
562 if (includeTaskRoot && event.mTaskRootClass != null) {
563 names.add(event.mTaskRootClass);
564 }
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800565 accumulatedResult.add(event);
566 }
567 });
568
569 if (results == null || results.isEmpty()) {
570 return null;
571 }
572
573 final String[] table = names.toArray(new String[names.size()]);
574 Arrays.sort(table);
Michael Wachenschwanz0b4ab1f2019-01-07 13:59:10 -0800575 return new UsageEvents(results, table, includeTaskRoot);
Suprabh Shukla217ccda2018-02-23 17:57:12 -0800576 }
577
Adam Lesinski3c153512014-07-23 17:34:34 -0700578 void persistActiveStats() {
579 if (mStatsChanged) {
580 Slog.i(TAG, mLogPrefix + "Flushing usage stats to disk");
581 try {
Varun Shahe1ba9cd2019-08-27 17:11:25 -0700582 mDatabase.obfuscateCurrentStats(mCurrentStats);
583 mDatabase.writeMappingsLocked();
Adam Lesinski3c153512014-07-23 17:34:34 -0700584 for (int i = 0; i < mCurrentStats.length; i++) {
585 mDatabase.putUsageStats(i, mCurrentStats[i]);
586 }
587 mStatsChanged = false;
588 } catch (IOException e) {
589 Slog.e(TAG, mLogPrefix + "Failed to persist active stats", e);
590 }
591 }
592 }
593
Amith Yamasania93542f2016-02-03 18:02:06 -0800594 private void rolloverStats(final long currentTimeMillis) {
Adam Lesinski66143fa2014-09-11 08:31:05 -0700595 final long startTime = SystemClock.elapsedRealtime();
Adam Lesinski3c153512014-07-23 17:34:34 -0700596 Slog.i(TAG, mLogPrefix + "Rolling over usage stats");
597
Hui Yue361a232018-10-04 15:05:21 -0700598 // Finish any ongoing events with an END_OF_DAY or ROLLOVER_FOREGROUND_SERVICE event.
599 // Make a note of which components need a new CONTINUE_PREVIOUS_DAY or
600 // CONTINUING_FOREGROUND_SERVICE entry.
Adam Lesinski7f61e962014-09-02 16:43:52 -0700601 final Configuration previousConfig =
Hui Yu03d12402018-12-06 18:00:37 -0800602 mCurrentStats[INTERVAL_DAILY].activeConfiguration;
603 ArraySet<String> continuePkgs = new ArraySet<>();
604 ArrayMap<String, SparseIntArray> continueActivity =
Hui Yue361a232018-10-04 15:05:21 -0700605 new ArrayMap<>();
Hui Yu03d12402018-12-06 18:00:37 -0800606 ArrayMap<String, ArrayMap<String, Integer>> continueForegroundService =
Hui Yue361a232018-10-04 15:05:21 -0700607 new ArrayMap<>();
Adam Lesinski35168002014-07-21 15:25:30 -0700608 for (IntervalStats stat : mCurrentStats) {
Adam Lesinski37a46b42014-09-05 15:38:05 -0700609 final int pkgCount = stat.packageStats.size();
Adam Lesinski3c153512014-07-23 17:34:34 -0700610 for (int i = 0; i < pkgCount; i++) {
Hui Yue361a232018-10-04 15:05:21 -0700611 final UsageStats pkgStats = stat.packageStats.valueAt(i);
Hui Yu03d12402018-12-06 18:00:37 -0800612 if (pkgStats.mActivities.size() > 0
613 || !pkgStats.mForegroundServices.isEmpty()) {
614 if (pkgStats.mActivities.size() > 0) {
615 continueActivity.put(pkgStats.mPackageName,
616 pkgStats.mActivities);
Hui Yue361a232018-10-04 15:05:21 -0700617 stat.update(pkgStats.mPackageName, null,
618 mDailyExpiryDate.getTimeInMillis() - 1,
Hui Yu03d12402018-12-06 18:00:37 -0800619 Event.END_OF_DAY, 0);
Hui Yue361a232018-10-04 15:05:21 -0700620 }
Hui Yu03d12402018-12-06 18:00:37 -0800621 if (!pkgStats.mForegroundServices.isEmpty()) {
622 continueForegroundService.put(pkgStats.mPackageName,
623 pkgStats.mForegroundServices);
Hui Yue361a232018-10-04 15:05:21 -0700624 stat.update(pkgStats.mPackageName, null,
625 mDailyExpiryDate.getTimeInMillis() - 1,
Hui Yu03d12402018-12-06 18:00:37 -0800626 Event.ROLLOVER_FOREGROUND_SERVICE, 0);
Hui Yue361a232018-10-04 15:05:21 -0700627 }
Hui Yu03d12402018-12-06 18:00:37 -0800628 continuePkgs.add(pkgStats.mPackageName);
Adam Lesinski66143fa2014-09-11 08:31:05 -0700629 notifyStatsChanged();
Adam Lesinski3c153512014-07-23 17:34:34 -0700630 }
631 }
Adam Lesinski7f61e962014-09-02 16:43:52 -0700632
Hui Yue361a232018-10-04 15:05:21 -0700633 stat.updateConfigurationStats(null,
634 mDailyExpiryDate.getTimeInMillis() - 1);
Dianne Hackbornced54392018-02-26 13:07:42 -0800635 stat.commitTime(mDailyExpiryDate.getTimeInMillis() - 1);
Adam Lesinski3c153512014-07-23 17:34:34 -0700636 }
637
638 persistActiveStats();
Adam Lesinski66143fa2014-09-11 08:31:05 -0700639 mDatabase.prune(currentTimeMillis);
Amith Yamasania93542f2016-02-03 18:02:06 -0800640 loadActiveStats(currentTimeMillis);
Adam Lesinski3c153512014-07-23 17:34:34 -0700641
Hui Yu03d12402018-12-06 18:00:37 -0800642 final int continueCount = continuePkgs.size();
Adam Lesinski3c153512014-07-23 17:34:34 -0700643 for (int i = 0; i < continueCount; i++) {
Hui Yu03d12402018-12-06 18:00:37 -0800644 String pkgName = continuePkgs.valueAt(i);
645 final long beginTime = mCurrentStats[INTERVAL_DAILY].beginTime;
Adam Lesinski35168002014-07-21 15:25:30 -0700646 for (IntervalStats stat : mCurrentStats) {
Hui Yu03d12402018-12-06 18:00:37 -0800647 if (continueActivity.containsKey(pkgName)) {
648 final SparseIntArray eventMap =
649 continueActivity.get(pkgName);
650 final int size = eventMap.size();
Hui Yue361a232018-10-04 15:05:21 -0700651 for (int j = 0; j < size; j++) {
Hui Yu03d12402018-12-06 18:00:37 -0800652 stat.update(pkgName, null, beginTime,
653 eventMap.valueAt(j), eventMap.keyAt(j));
Hui Yue361a232018-10-04 15:05:21 -0700654 }
655 }
Hui Yu03d12402018-12-06 18:00:37 -0800656 if (continueForegroundService.containsKey(pkgName)) {
657 final ArrayMap<String, Integer> eventMap =
658 continueForegroundService.get(pkgName);
659 final int size = eventMap.size();
Hui Yue361a232018-10-04 15:05:21 -0700660 for (int j = 0; j < size; j++) {
Hui Yu03d12402018-12-06 18:00:37 -0800661 stat.update(pkgName, eventMap.keyAt(j), beginTime,
662 eventMap.valueAt(j), 0);
Hui Yue361a232018-10-04 15:05:21 -0700663 }
664 }
Adam Lesinski7f61e962014-09-02 16:43:52 -0700665 stat.updateConfigurationStats(previousConfig, beginTime);
Adam Lesinski66143fa2014-09-11 08:31:05 -0700666 notifyStatsChanged();
Adam Lesinski3c153512014-07-23 17:34:34 -0700667 }
668 }
669 persistActiveStats();
670
Adam Lesinski66143fa2014-09-11 08:31:05 -0700671 final long totalTime = SystemClock.elapsedRealtime() - startTime;
Adam Lesinski3c153512014-07-23 17:34:34 -0700672 Slog.i(TAG, mLogPrefix + "Rolling over usage stats complete. Took " + totalTime
673 + " milliseconds");
674 }
675
676 private void notifyStatsChanged() {
677 if (!mStatsChanged) {
678 mStatsChanged = true;
679 mListener.onStatsUpdated();
680 }
681 }
682
Amith Yamasania93542f2016-02-03 18:02:06 -0800683 private void notifyNewUpdate() {
684 mListener.onNewUpdate(mUserId);
685 }
686
687 private void loadActiveStats(final long currentTimeMillis) {
Adam Lesinskid26bea32014-09-03 16:49:59 -0700688 for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) {
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700689 final IntervalStats stats = mDatabase.getLatestUsageStats(intervalType);
Hui Yub21d59f2019-01-28 16:33:32 -0800690 if (stats != null
691 && currentTimeMillis < stats.beginTime + INTERVAL_LENGTH[intervalType]) {
Adam Lesinski35168002014-07-21 15:25:30 -0700692 if (DEBUG) {
Adam Lesinskid26bea32014-09-03 16:49:59 -0700693 Slog.d(TAG, mLogPrefix + "Loading existing stats @ " +
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700694 sDateFormat.format(stats.beginTime) + "(" + stats.beginTime +
Adam Lesinskid26bea32014-09-03 16:49:59 -0700695 ") for interval " + intervalType);
Adam Lesinski35168002014-07-21 15:25:30 -0700696 }
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700697 mCurrentStats[intervalType] = stats;
Adam Lesinski3c153512014-07-23 17:34:34 -0700698 } else {
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700699 // No good fit remains.
Adam Lesinski35168002014-07-21 15:25:30 -0700700 if (DEBUG) {
Adam Lesinskid26bea32014-09-03 16:49:59 -0700701 Slog.d(TAG, "Creating new stats @ " +
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700702 sDateFormat.format(currentTimeMillis) + "(" +
703 currentTimeMillis + ") for interval " + intervalType);
Adam Lesinski35168002014-07-21 15:25:30 -0700704 }
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700705
Adam Lesinskid26bea32014-09-03 16:49:59 -0700706 mCurrentStats[intervalType] = new IntervalStats();
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700707 mCurrentStats[intervalType].beginTime = currentTimeMillis;
708 mCurrentStats[intervalType].endTime = currentTimeMillis + 1;
Adam Lesinski3c153512014-07-23 17:34:34 -0700709 }
710 }
Adam Lesinskida4a3772016-01-07 18:24:53 -0800711
Adam Lesinski3c153512014-07-23 17:34:34 -0700712 mStatsChanged = false;
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700713 updateRolloverDeadline();
Adam Lesinskib2d3ffa2016-01-26 18:18:19 -0800714
715 // Tell the listener that the stats reloaded, which may have changed idle states.
716 mListener.onStatsReloaded();
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700717 }
718
719 private void updateRolloverDeadline() {
720 mDailyExpiryDate.setTimeInMillis(
Hui Yu03d12402018-12-06 18:00:37 -0800721 mCurrentStats[INTERVAL_DAILY].beginTime);
Adam Lesinskid26bea32014-09-03 16:49:59 -0700722 mDailyExpiryDate.addDays(1);
Adam Lesinskid26bea32014-09-03 16:49:59 -0700723 Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " +
724 sDateFormat.format(mDailyExpiryDate.getTimeInMillis()) + "(" +
Adam Lesinski7cba1d42015-08-04 16:17:37 -0700725 mDailyExpiryDate.getTimeInMillis() + ")");
Adam Lesinski3c153512014-07-23 17:34:34 -0700726 }
727
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700728 //
729 // -- DUMP related methods --
730 //
731
Amith Yamasania93542f2016-02-03 18:02:06 -0800732 void checkin(final IndentingPrintWriter pw) {
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700733 mDatabase.checkinDailyFiles(new UsageStatsDatabase.CheckinAction() {
734 @Override
735 public boolean checkin(IntervalStats stats) {
Michael Wachenschwanz1088cbb2018-03-01 12:45:16 -0800736 printIntervalStats(pw, stats, false, false, null);
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700737 return true;
738 }
739 });
740 }
741
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700742 void dump(IndentingPrintWriter pw, String pkg) {
Michael Wachenschwanz1088cbb2018-03-01 12:45:16 -0800743 dump(pw, pkg, false);
744 }
745 void dump(IndentingPrintWriter pw, String pkg, boolean compact) {
746 printLast24HrEvents(pw, !compact, pkg);
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700747 for (int interval = 0; interval < mCurrentStats.length; interval++) {
748 pw.print("In-memory ");
749 pw.print(intervalToString(interval));
750 pw.println(" stats");
Michael Wachenschwanz1088cbb2018-03-01 12:45:16 -0800751 printIntervalStats(pw, mCurrentStats[interval], !compact, true, pkg);
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700752 }
Hui Yu0818df02019-02-21 13:55:00 -0800753 mDatabase.dump(pw, compact);
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700754 }
755
Varun Shah5bef1be2019-05-07 22:35:22 -0700756 void dumpDatabaseInfo(IndentingPrintWriter ipw) {
757 mDatabase.dump(ipw, false);
758 }
759
Varun Shahe1ba9cd2019-08-27 17:11:25 -0700760 void dumpMappings(IndentingPrintWriter ipw) {
761 mDatabase.dumpMappings(ipw);
762 }
763
Varun Shah5bef1be2019-05-07 22:35:22 -0700764 void dumpFile(IndentingPrintWriter ipw, String[] args) {
765 if (args == null || args.length == 0) {
766 // dump all files for every interval for specified user
767 final int numIntervals = mDatabase.mSortedStatFiles.length;
768 for (int interval = 0; interval < numIntervals; interval++) {
769 ipw.println("interval=" + intervalToString(interval));
770 ipw.increaseIndent();
771 dumpFileDetailsForInterval(ipw, interval);
772 ipw.decreaseIndent();
773 }
774 } else {
775 final int interval;
776 try {
777 final int intervalValue = stringToInterval(args[0]);
778 if (intervalValue == -1) {
779 interval = Integer.valueOf(args[0]);
780 } else {
781 interval = intervalValue;
782 }
783 } catch (NumberFormatException nfe) {
784 ipw.println("invalid interval specified.");
785 return;
786 }
787 if (interval < 0 || interval >= mDatabase.mSortedStatFiles.length) {
788 ipw.println("the specified interval does not exist.");
789 return;
790 }
791 if (args.length == 1) {
792 // dump all files in the specified interval
793 dumpFileDetailsForInterval(ipw, interval);
794 } else {
795 // dump details only for the specified filename
796 final long filename;
797 try {
798 filename = Long.valueOf(args[1]);
799 } catch (NumberFormatException nfe) {
800 ipw.println("invalid filename specified.");
801 return;
802 }
803 final IntervalStats stats = mDatabase.readIntervalStatsForFile(interval, filename);
804 if (stats == null) {
805 ipw.println("the specified filename does not exist.");
806 return;
807 }
808 dumpFileDetails(ipw, stats, Long.valueOf(args[1]));
809 }
810 }
811 }
812
813 private void dumpFileDetailsForInterval(IndentingPrintWriter ipw, int interval) {
814 final TimeSparseArray<AtomicFile> files = mDatabase.mSortedStatFiles[interval];
815 final int numFiles = files.size();
816 for (int i = 0; i < numFiles; i++) {
817 final long filename = files.keyAt(i);
818 final IntervalStats stats = mDatabase.readIntervalStatsForFile(interval, filename);
819 dumpFileDetails(ipw, stats, filename);
820 ipw.println();
821 }
822 }
823
824 private void dumpFileDetails(IndentingPrintWriter ipw, IntervalStats stats, long filename) {
825 ipw.println("file=" + filename);
826 ipw.increaseIndent();
827 printIntervalStats(ipw, stats, false, false, null);
828 ipw.decreaseIndent();
829 }
830
Hui Yu0818df02019-02-21 13:55:00 -0800831 static String formatDateTime(long dateTime, boolean pretty) {
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700832 if (pretty) {
Michael Wachenschwanz1088cbb2018-03-01 12:45:16 -0800833 return "\"" + sDateFormat.format(dateTime)+ "\"";
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700834 }
835 return Long.toString(dateTime);
836 }
837
838 private String formatElapsedTime(long elapsedTime, boolean pretty) {
839 if (pretty) {
840 return "\"" + DateUtils.formatElapsedTime(elapsedTime / 1000) + "\"";
841 }
842 return Long.toString(elapsedTime);
843 }
844
Michael Wachenschwanz06e49402018-02-20 23:39:09 -0800845
Hui Yu03d12402018-12-06 18:00:37 -0800846 void printEvent(IndentingPrintWriter pw, Event event, boolean prettyDates) {
Michael Wachenschwanz06e49402018-02-20 23:39:09 -0800847 pw.printPair("time", formatDateTime(event.mTimeStamp, prettyDates));
848 pw.printPair("type", eventToString(event.mEventType));
849 pw.printPair("package", event.mPackage);
850 if (event.mClass != null) {
851 pw.printPair("class", event.mClass);
852 }
853 if (event.mConfiguration != null) {
854 pw.printPair("config", Configuration.resourceQualifierString(event.mConfiguration));
855 }
856 if (event.mShortcutId != null) {
857 pw.printPair("shortcutId", event.mShortcutId);
858 }
Hui Yu03d12402018-12-06 18:00:37 -0800859 if (event.mEventType == Event.STANDBY_BUCKET_CHANGED) {
Amith Yamasani119be9a2018-02-18 22:23:00 -0800860 pw.printPair("standbyBucket", event.getStandbyBucket());
861 pw.printPair("reason", UsageStatsManager.reasonToString(event.getStandbyReason()));
Hui Yu03d12402018-12-06 18:00:37 -0800862 } else if (event.mEventType == Event.ACTIVITY_RESUMED
863 || event.mEventType == Event.ACTIVITY_PAUSED
864 || event.mEventType == Event.ACTIVITY_STOPPED) {
865 pw.printPair("instanceId", event.getInstanceId());
Michael Wachenschwanz06e49402018-02-20 23:39:09 -0800866 }
Hui Yu03d12402018-12-06 18:00:37 -0800867
Michael Wachenschwanz0b4ab1f2019-01-07 13:59:10 -0800868 if (event.getTaskRootPackageName() != null) {
869 pw.printPair("taskRootPackage", event.getTaskRootPackageName());
870 }
871
872 if (event.getTaskRootClassName() != null) {
873 pw.printPair("taskRootClass", event.getTaskRootClassName());
874 }
875
Julia Reynolds5dc1edf2018-06-12 10:19:02 -0400876 if (event.mNotificationChannelId != null) {
877 pw.printPair("channelId", event.mNotificationChannelId);
878 }
Michael Wachenschwanz06e49402018-02-20 23:39:09 -0800879 pw.printHexPair("flags", event.mFlags);
880 pw.println();
881 }
882
883 void printLast24HrEvents(IndentingPrintWriter pw, boolean prettyDates, final String pkg) {
884 final long endTime = System.currentTimeMillis();
885 UnixCalendar yesterday = new UnixCalendar(endTime);
886 yesterday.addDays(-1);
887
888 final long beginTime = yesterday.getTimeInMillis();
889
Hui Yu03d12402018-12-06 18:00:37 -0800890 List<Event> events = queryStats(INTERVAL_DAILY,
891 beginTime, endTime, new StatCombiner<Event>() {
Michael Wachenschwanz06e49402018-02-20 23:39:09 -0800892 @Override
893 public void combine(IntervalStats stats, boolean mutable,
Hui Yu03d12402018-12-06 18:00:37 -0800894 List<Event> accumulatedResult) {
Suprabh Shukla60aa35b2018-04-24 18:52:46 -0700895 final int startIndex = stats.events.firstIndexOnOrAfter(beginTime);
Michael Wachenschwanz06e49402018-02-20 23:39:09 -0800896 final int size = stats.events.size();
897 for (int i = startIndex; i < size; i++) {
Suprabh Shukla60aa35b2018-04-24 18:52:46 -0700898 if (stats.events.get(i).mTimeStamp >= endTime) {
Michael Wachenschwanz06e49402018-02-20 23:39:09 -0800899 return;
900 }
901
Hui Yu03d12402018-12-06 18:00:37 -0800902 Event event = stats.events.get(i);
Michael Wachenschwanz06e49402018-02-20 23:39:09 -0800903 if (pkg != null && !pkg.equals(event.mPackage)) {
904 continue;
905 }
906 accumulatedResult.add(event);
907 }
908 }
909 });
910
911 pw.print("Last 24 hour events (");
912 if (prettyDates) {
913 pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext,
914 beginTime, endTime, sDateFormatFlags) + "\"");
915 } else {
916 pw.printPair("beginTime", beginTime);
917 pw.printPair("endTime", endTime);
918 }
919 pw.println(")");
Michael Wachenschwanz78646e52018-02-27 15:54:27 -0800920 if (events != null) {
921 pw.increaseIndent();
Hui Yu03d12402018-12-06 18:00:37 -0800922 for (Event event : events) {
Michael Wachenschwanz78646e52018-02-27 15:54:27 -0800923 printEvent(pw, event, prettyDates);
924 }
925 pw.decreaseIndent();
Michael Wachenschwanz06e49402018-02-20 23:39:09 -0800926 }
Michael Wachenschwanz06e49402018-02-20 23:39:09 -0800927 }
928
Dianne Hackborn3378aa92018-03-30 17:43:49 -0700929 void printEventAggregation(IndentingPrintWriter pw, String label,
930 IntervalStats.EventTracker tracker, boolean prettyDates) {
931 if (tracker.count != 0 || tracker.duration != 0) {
Dianne Hackbornced54392018-02-26 13:07:42 -0800932 pw.print(label);
933 pw.print(": ");
Dianne Hackborn3378aa92018-03-30 17:43:49 -0700934 pw.print(tracker.count);
Dianne Hackbornced54392018-02-26 13:07:42 -0800935 pw.print("x for ");
Dianne Hackborn3378aa92018-03-30 17:43:49 -0700936 pw.print(formatElapsedTime(tracker.duration, prettyDates));
937 if (tracker.curStartTime != 0) {
938 pw.print(" (now running, started at ");
939 formatDateTime(tracker.curStartTime, prettyDates);
940 pw.print(")");
941 }
Dianne Hackbornced54392018-02-26 13:07:42 -0800942 pw.println();
943 }
944 }
945
Amith Yamasania93542f2016-02-03 18:02:06 -0800946 void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats,
Michael Wachenschwanz1088cbb2018-03-01 12:45:16 -0800947 boolean prettyDates, boolean skipEvents, String pkg) {
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700948 if (prettyDates) {
949 pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext,
950 stats.beginTime, stats.endTime, sDateFormatFlags) + "\"");
951 } else {
952 pw.printPair("beginTime", stats.beginTime);
953 pw.printPair("endTime", stats.endTime);
954 }
955 pw.println();
956 pw.increaseIndent();
957 pw.println("packages");
958 pw.increaseIndent();
959 final ArrayMap<String, UsageStats> pkgStats = stats.packageStats;
960 final int pkgCount = pkgStats.size();
961 for (int i = 0; i < pkgCount; i++) {
962 final UsageStats usageStats = pkgStats.valueAt(i);
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700963 if (pkg != null && !pkg.equals(usageStats.mPackageName)) {
964 continue;
965 }
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700966 pw.printPair("package", usageStats.mPackageName);
Hui Yu03d12402018-12-06 18:00:37 -0800967 pw.printPair("totalTimeUsed",
Adam Lesinskic8e87292015-06-10 15:33:45 -0700968 formatElapsedTime(usageStats.mTotalTimeInForeground, prettyDates));
Hui Yu03d12402018-12-06 18:00:37 -0800969 pw.printPair("lastTimeUsed", formatDateTime(usageStats.mLastTimeUsed, prettyDates));
970 pw.printPair("totalTimeVisible",
971 formatElapsedTime(usageStats.mTotalTimeVisible, prettyDates));
972 pw.printPair("lastTimeVisible",
973 formatDateTime(usageStats.mLastTimeVisible, prettyDates));
974 pw.printPair("totalTimeFS",
975 formatElapsedTime(usageStats.mTotalTimeForegroundServiceUsed, prettyDates));
976 pw.printPair("lastTimeFS",
977 formatDateTime(usageStats.mLastTimeForegroundServiceUsed, prettyDates));
Amith Yamasanibc813eb2018-03-20 19:37:46 -0700978 pw.printPair("appLaunchCount", usageStats.mAppLaunchCount);
Adam Lesinski1bb18c42014-08-18 12:21:34 -0700979 pw.println();
980 }
981 pw.decreaseIndent();
982
Kang Li53b43142016-11-14 14:38:25 -0800983 pw.println();
Kang Li53b43142016-11-14 14:38:25 -0800984 pw.println("ChooserCounts");
985 pw.increaseIndent();
986 for (UsageStats usageStats : pkgStats.values()) {
Dianne Hackbornc81983a2017-10-20 16:16:32 -0700987 if (pkg != null && !pkg.equals(usageStats.mPackageName)) {
988 continue;
989 }
Kang Li53b43142016-11-14 14:38:25 -0800990 pw.printPair("package", usageStats.mPackageName);
991 if (usageStats.mChooserCounts != null) {
992 final int chooserCountSize = usageStats.mChooserCounts.size();
993 for (int i = 0; i < chooserCountSize; i++) {
994 final String action = usageStats.mChooserCounts.keyAt(i);
995 final ArrayMap<String, Integer> counts = usageStats.mChooserCounts.valueAt(i);
996 final int annotationSize = counts.size();
997 for (int j = 0; j < annotationSize; j++) {
998 final String key = counts.keyAt(j);
999 final int count = counts.valueAt(j);
1000 if (count != 0) {
1001 pw.printPair("ChooserCounts", action + ":" + key + " is " +
1002 Integer.toString(count));
1003 pw.println();
1004 }
1005 }
1006 }
1007 }
1008 pw.println();
1009 }
Amith Yamasani61d5fd72017-02-24 11:02:07 -08001010 pw.decreaseIndent();
Kang Li53b43142016-11-14 14:38:25 -08001011
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001012 if (pkg == null) {
1013 pw.println("configurations");
1014 pw.increaseIndent();
1015 final ArrayMap<Configuration, ConfigurationStats> configStats = stats.configurations;
1016 final int configCount = configStats.size();
1017 for (int i = 0; i < configCount; i++) {
1018 final ConfigurationStats config = configStats.valueAt(i);
1019 pw.printPair("config", Configuration.resourceQualifierString(
1020 config.mConfiguration));
1021 pw.printPair("totalTime", formatElapsedTime(config.mTotalTimeActive, prettyDates));
1022 pw.printPair("lastTime", formatDateTime(config.mLastTimeActive, prettyDates));
1023 pw.printPair("count", config.mActivationCount);
1024 pw.println();
1025 }
1026 pw.decreaseIndent();
Dianne Hackbornced54392018-02-26 13:07:42 -08001027 pw.println("event aggregations");
1028 pw.increaseIndent();
Dianne Hackborn3378aa92018-03-30 17:43:49 -07001029 printEventAggregation(pw, "screen-interactive", stats.interactiveTracker,
1030 prettyDates);
1031 printEventAggregation(pw, "screen-non-interactive", stats.nonInteractiveTracker,
1032 prettyDates);
1033 printEventAggregation(pw, "keyguard-shown", stats.keyguardShownTracker,
1034 prettyDates);
1035 printEventAggregation(pw, "keyguard-hidden", stats.keyguardHiddenTracker,
1036 prettyDates);
Dianne Hackbornced54392018-02-26 13:07:42 -08001037 pw.decreaseIndent();
Adam Lesinski1bb18c42014-08-18 12:21:34 -07001038 }
Adam Lesinski1bb18c42014-08-18 12:21:34 -07001039
Michael Wachenschwanz06e49402018-02-20 23:39:09 -08001040 // The last 24 hours of events is already printed in the non checkin dump
1041 // No need to repeat here.
Michael Wachenschwanz1088cbb2018-03-01 12:45:16 -08001042 if (!skipEvents) {
Michael Wachenschwanz06e49402018-02-20 23:39:09 -08001043 pw.println("events");
1044 pw.increaseIndent();
Suprabh Shukla60aa35b2018-04-24 18:52:46 -07001045 final EventList events = stats.events;
Michael Wachenschwanz06e49402018-02-20 23:39:09 -08001046 final int eventCount = events != null ? events.size() : 0;
1047 for (int i = 0; i < eventCount; i++) {
Hui Yu03d12402018-12-06 18:00:37 -08001048 final Event event = events.get(i);
Michael Wachenschwanz06e49402018-02-20 23:39:09 -08001049 if (pkg != null && !pkg.equals(event.mPackage)) {
1050 continue;
1051 }
1052 printEvent(pw, event, prettyDates);
Dianne Hackbornc81983a2017-10-20 16:16:32 -07001053 }
Michael Wachenschwanz06e49402018-02-20 23:39:09 -08001054 pw.decreaseIndent();
Adam Lesinski1bb18c42014-08-18 12:21:34 -07001055 }
1056 pw.decreaseIndent();
Adam Lesinski1bb18c42014-08-18 12:21:34 -07001057 }
1058
Hui Yu0818df02019-02-21 13:55:00 -08001059 public static String intervalToString(int interval) {
Adam Lesinski1bb18c42014-08-18 12:21:34 -07001060 switch (interval) {
Hui Yu03d12402018-12-06 18:00:37 -08001061 case INTERVAL_DAILY:
Adam Lesinski1bb18c42014-08-18 12:21:34 -07001062 return "daily";
Hui Yu03d12402018-12-06 18:00:37 -08001063 case INTERVAL_WEEKLY:
Adam Lesinski1bb18c42014-08-18 12:21:34 -07001064 return "weekly";
Hui Yu03d12402018-12-06 18:00:37 -08001065 case INTERVAL_MONTHLY:
Adam Lesinski1bb18c42014-08-18 12:21:34 -07001066 return "monthly";
Hui Yu03d12402018-12-06 18:00:37 -08001067 case INTERVAL_YEARLY:
Adam Lesinski1bb18c42014-08-18 12:21:34 -07001068 return "yearly";
1069 default:
1070 return "?";
1071 }
1072 }
Adam Lesinski3c153512014-07-23 17:34:34 -07001073
Varun Shah5bef1be2019-05-07 22:35:22 -07001074 private static int stringToInterval(String interval) {
1075 switch (interval.toLowerCase()) {
1076 case "daily":
1077 return INTERVAL_DAILY;
1078 case "weekly":
1079 return INTERVAL_WEEKLY;
1080 case "monthly":
1081 return INTERVAL_MONTHLY;
1082 case "yearly":
1083 return INTERVAL_YEARLY;
1084 default:
1085 return -1;
1086 }
1087 }
1088
Adam Lesinski3c153512014-07-23 17:34:34 -07001089 private static String eventToString(int eventType) {
1090 switch (eventType) {
Hui Yu03d12402018-12-06 18:00:37 -08001091 case Event.NONE:
Adam Lesinski3c153512014-07-23 17:34:34 -07001092 return "NONE";
Hui Yu03d12402018-12-06 18:00:37 -08001093 case Event.ACTIVITY_PAUSED:
1094 return "ACTIVITY_PAUSED";
1095 case Event.ACTIVITY_RESUMED:
1096 return "ACTIVITY_RESUMED";
1097 case Event.FOREGROUND_SERVICE_START:
Hui Yue361a232018-10-04 15:05:21 -07001098 return "FOREGROUND_SERVICE_START";
Hui Yu03d12402018-12-06 18:00:37 -08001099 case Event.FOREGROUND_SERVICE_STOP:
Hui Yue361a232018-10-04 15:05:21 -07001100 return "FOREGROUND_SERVICE_STOP";
Hui Yu03d12402018-12-06 18:00:37 -08001101 case Event.ACTIVITY_STOPPED:
1102 return "ACTIVITY_STOPPED";
1103 case Event.END_OF_DAY:
Adam Lesinski3c153512014-07-23 17:34:34 -07001104 return "END_OF_DAY";
Hui Yu03d12402018-12-06 18:00:37 -08001105 case Event.ROLLOVER_FOREGROUND_SERVICE:
Hui Yue361a232018-10-04 15:05:21 -07001106 return "ROLLOVER_FOREGROUND_SERVICE";
Hui Yu03d12402018-12-06 18:00:37 -08001107 case Event.CONTINUE_PREVIOUS_DAY:
Adam Lesinski3c153512014-07-23 17:34:34 -07001108 return "CONTINUE_PREVIOUS_DAY";
Hui Yu03d12402018-12-06 18:00:37 -08001109 case Event.CONTINUING_FOREGROUND_SERVICE:
Hui Yue361a232018-10-04 15:05:21 -07001110 return "CONTINUING_FOREGROUND_SERVICE";
Hui Yu03d12402018-12-06 18:00:37 -08001111 case Event.CONFIGURATION_CHANGE:
Adam Lesinski7f61e962014-09-02 16:43:52 -07001112 return "CONFIGURATION_CHANGE";
Hui Yu03d12402018-12-06 18:00:37 -08001113 case Event.SYSTEM_INTERACTION:
Adam Lesinskic8e87292015-06-10 15:33:45 -07001114 return "SYSTEM_INTERACTION";
Hui Yu03d12402018-12-06 18:00:37 -08001115 case Event.USER_INTERACTION:
Adam Lesinskic8e87292015-06-10 15:33:45 -07001116 return "USER_INTERACTION";
Hui Yu03d12402018-12-06 18:00:37 -08001117 case Event.SHORTCUT_INVOCATION:
Makoto Onukiac042502016-05-20 16:39:42 -07001118 return "SHORTCUT_INVOCATION";
Hui Yu03d12402018-12-06 18:00:37 -08001119 case Event.CHOOSER_ACTION:
Kang Li53b43142016-11-14 14:38:25 -08001120 return "CHOOSER_ACTION";
Hui Yu03d12402018-12-06 18:00:37 -08001121 case Event.NOTIFICATION_SEEN:
Amith Yamasani803eab692017-11-09 17:47:04 -08001122 return "NOTIFICATION_SEEN";
Hui Yu03d12402018-12-06 18:00:37 -08001123 case Event.STANDBY_BUCKET_CHANGED:
Amith Yamasanibfc4bf52018-01-19 06:55:08 -08001124 return "STANDBY_BUCKET_CHANGED";
Hui Yu03d12402018-12-06 18:00:37 -08001125 case Event.NOTIFICATION_INTERRUPTION:
Julia Reynolds1fac86e2018-03-07 08:30:37 -05001126 return "NOTIFICATION_INTERRUPTION";
Hui Yu03d12402018-12-06 18:00:37 -08001127 case Event.SLICE_PINNED:
Jason Monk1918ef72018-03-14 09:20:39 -04001128 return "SLICE_PINNED";
Hui Yu03d12402018-12-06 18:00:37 -08001129 case Event.SLICE_PINNED_PRIV:
Jason Monk1918ef72018-03-14 09:20:39 -04001130 return "SLICE_PINNED_PRIV";
Hui Yu03d12402018-12-06 18:00:37 -08001131 case Event.SCREEN_INTERACTIVE:
Dianne Hackbornced54392018-02-26 13:07:42 -08001132 return "SCREEN_INTERACTIVE";
Hui Yu03d12402018-12-06 18:00:37 -08001133 case Event.SCREEN_NON_INTERACTIVE:
Dianne Hackbornced54392018-02-26 13:07:42 -08001134 return "SCREEN_NON_INTERACTIVE";
Hui Yub1d243a2018-12-13 12:02:00 -08001135 case Event.KEYGUARD_SHOWN:
Esteban Talavera917a71d2018-11-13 07:55:08 +00001136 return "KEYGUARD_SHOWN";
Hui Yub1d243a2018-12-13 12:02:00 -08001137 case Event.KEYGUARD_HIDDEN:
Esteban Talavera917a71d2018-11-13 07:55:08 +00001138 return "KEYGUARD_HIDDEN";
Hui Yub1d243a2018-12-13 12:02:00 -08001139 case Event.DEVICE_SHUTDOWN:
1140 return "DEVICE_SHUTDOWN";
Hui Yu80a8b462019-03-05 15:22:13 -08001141 case Event.DEVICE_STARTUP:
1142 return "DEVICE_STARTUP";
Adam Lesinski3c153512014-07-23 17:34:34 -07001143 default:
Esteban Talavera917a71d2018-11-13 07:55:08 +00001144 return "UNKNOWN_TYPE_" + eventType;
Adam Lesinski3c153512014-07-23 17:34:34 -07001145 }
1146 }
Ritesh Reddy8a6ce2c2015-12-17 17:03:54 +00001147
1148 byte[] getBackupPayload(String key){
Varun Shah5e1613e2019-09-05 11:50:18 -07001149 checkAndGetTimeLocked();
Ritesh Reddy8a6ce2c2015-12-17 17:03:54 +00001150 return mDatabase.getBackupPayload(key);
1151 }
1152
1153 void applyRestoredPayload(String key, byte[] payload){
Varun Shah5e1613e2019-09-05 11:50:18 -07001154 checkAndGetTimeLocked();
Ritesh Reddy8a6ce2c2015-12-17 17:03:54 +00001155 mDatabase.applyRestoredPayload(key, payload);
1156 }
Adam Lesinski3c153512014-07-23 17:34:34 -07001157}