10debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski/** 20debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Copyright (C) 2014 The Android Open Source Project 30debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * 40debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); you may not 50debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * use this file except in compliance with the License. You may obtain a copy 60debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * of the License at 70debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * 80debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 90debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * 100debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Unless required by applicable law or agreed to in writing, software 110debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 120debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 130debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * License for the specific language governing permissions and limitations 140debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * under the License. 150debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski */ 160debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 170debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskipackage com.android.server.usage; 180debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1953ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinskiimport android.Manifest; 200debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.app.AppOpsManager; 217f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinskiimport android.app.usage.ConfigurationStats; 220debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.app.usage.IUsageStatsManager; 233516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.app.usage.UsageEvents; 240debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.app.usage.UsageStats; 250debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.app.usage.UsageStatsManagerInternal; 263c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinskiimport android.content.BroadcastReceiver; 270debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.content.ComponentName; 280debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.content.Context; 293c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinskiimport android.content.Intent; 303c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinskiimport android.content.IntentFilter; 3153ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinskiimport android.content.pm.PackageManager; 323516800b611a79339a3c188332d13a26e9086b09Adam Lesinskiimport android.content.pm.ParceledListSlice; 333c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinskiimport android.content.pm.UserInfo; 347f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinskiimport android.content.res.Configuration; 350debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.os.Binder; 360debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.os.Environment; 370debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.os.Handler; 380debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.os.Looper; 390debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.os.Message; 407eb599b267d00cbde891c0a87924f2f5086f4497Jeff Haoimport android.os.Process; 417f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinskiimport android.os.RemoteException; 4237a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinskiimport android.os.SystemClock; 433c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinskiimport android.os.UserHandle; 443c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinskiimport android.os.UserManager; 450debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.util.ArraySet; 460debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport android.util.Slog; 473c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinskiimport android.util.SparseArray; 483c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski 490debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport com.android.internal.os.BackgroundThread; 501bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinskiimport com.android.internal.util.IndentingPrintWriter; 510debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport com.android.server.SystemService; 520debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 530debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinskiimport java.io.File; 541bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinskiimport java.io.FileDescriptor; 551bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinskiimport java.io.PrintWriter; 563c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinskiimport java.util.Arrays; 573c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinskiimport java.util.List; 580debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 593516800b611a79339a3c188332d13a26e9086b09Adam Lesinski/** 603516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * A service that collects, aggregates, and persists application usage data. 613516800b611a79339a3c188332d13a26e9086b09Adam Lesinski * This data can be queried by apps that have been granted permission by AppOps. 623516800b611a79339a3c188332d13a26e9086b09Adam Lesinski */ 633c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinskipublic class UsageStatsService extends SystemService implements 643c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski UserUsageStatsService.StatsUpdatedListener { 650debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski static final String TAG = "UsageStatsService"; 660debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 670debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski static final boolean DEBUG = false; 680debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski private static final long TEN_SECONDS = 10 * 1000; 690debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski private static final long TWENTY_MINUTES = 20 * 60 * 1000; 700debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES; 7166143fa5b34eea7413335111838fb692987b611aAdam Lesinski private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. 720debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 730debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski // Handler message types. 740debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski static final int MSG_REPORT_EVENT = 0; 750debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski static final int MSG_FLUSH_TO_DISK = 1; 763c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski static final int MSG_REMOVE_USER = 2; 770debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 783c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski private final Object mLock = new Object(); 790debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski Handler mHandler; 800debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski AppOpsManager mAppOps; 813c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski UserManager mUserManager; 820debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 833c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>(); 843c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski private File mUsageStatsDir; 8537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski long mRealTimeSnapshot; 8637a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski long mSystemTimeSnapshot; 870debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 880debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski public UsageStatsService(Context context) { 890debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski super(context); 900debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 910debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 920debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski @Override 930debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski public void onStart() { 940debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); 953c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); 960debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski mHandler = new H(BackgroundThread.get().getLooper()); 970debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 980debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski File systemDataDir = new File(Environment.getDataDirectory(), "system"); 993c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski mUsageStatsDir = new File(systemDataDir, "usagestats"); 1003c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski mUsageStatsDir.mkdirs(); 1013c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski if (!mUsageStatsDir.exists()) { 1023c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski throw new IllegalStateException("Usage stats directory does not exist: " 1033c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski + mUsageStatsDir.getAbsolutePath()); 1043c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 1053c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski 1063c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski getContext().registerReceiver(new UserRemovedReceiver(), 1073c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski new IntentFilter(Intent.ACTION_USER_REMOVED)); 1080debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1090debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski synchronized (mLock) { 1103c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski cleanUpRemovedUsersLocked(); 1110debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1120debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 11337a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski mRealTimeSnapshot = SystemClock.elapsedRealtime(); 11437a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski mSystemTimeSnapshot = System.currentTimeMillis(); 11537a46b48dcb7e34ee3669cfb2ed78af08bfca3c7Adam Lesinski 1160debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski publishLocalService(UsageStatsManagerInternal.class, new LocalService()); 1170debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService()); 1180debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1190debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1203c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski private class UserRemovedReceiver extends BroadcastReceiver { 1213c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski 1223c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski @Override 1233c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski public void onReceive(Context context, Intent intent) { 1243c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski if (intent != null && intent.getAction().equals(Intent.ACTION_USER_REMOVED)) { 1253c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 1263c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski if (userId >= 0) { 1273c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski mHandler.obtainMessage(MSG_REMOVE_USER, userId, 0).sendToTarget(); 1283c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 1290debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1300debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1313c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 1320debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1333c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski @Override 1343c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski public void onStatsUpdated() { 1353c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski mHandler.sendEmptyMessageDelayed(MSG_FLUSH_TO_DISK, FLUSH_INTERVAL); 1363c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 1370debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1383c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski private void cleanUpRemovedUsersLocked() { 1393c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski final List<UserInfo> users = mUserManager.getUsers(true); 1403c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski if (users == null || users.size() == 0) { 1413c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski throw new IllegalStateException("There can't be no users"); 1420debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1430debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1443c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski ArraySet<String> toDelete = new ArraySet<>(); 1453c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski String[] fileNames = mUsageStatsDir.list(); 1463c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski if (fileNames == null) { 1473c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski // No users to delete. 1483c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski return; 1490debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1500debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1513c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski toDelete.addAll(Arrays.asList(fileNames)); 1523c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski 1533c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski final int userCount = users.size(); 1543c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski for (int i = 0; i < userCount; i++) { 1553c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski final UserInfo userInfo = users.get(i); 1563c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski toDelete.remove(Integer.toString(userInfo.id)); 1570debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1580debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1593c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski final int deleteCount = toDelete.size(); 1603c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski for (int i = 0; i < deleteCount; i++) { 1613c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski deleteRecursively(new File(mUsageStatsDir, toDelete.valueAt(i))); 1623c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 1633c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 1643c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski 1653c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski private static void deleteRecursively(File f) { 1663c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski File[] files = f.listFiles(); 1673c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski if (files != null) { 1683c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski for (File subFile : files) { 1693c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski deleteRecursively(subFile); 1700debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1710debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1720debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1733c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski if (!f.delete()) { 1743c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski Slog.e(TAG, "Failed to delete " + f); 1753c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 1760debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1770debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 17866143fa5b34eea7413335111838fb692987b611aAdam Lesinski private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId, 17966143fa5b34eea7413335111838fb692987b611aAdam Lesinski long currentTimeMillis) { 1803c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski UserUsageStatsService service = mUserState.get(userId); 1813c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski if (service == null) { 1821bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski service = new UserUsageStatsService(getContext(), userId, 1833c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski new File(mUsageStatsDir, Integer.toString(userId)), this); 18466143fa5b34eea7413335111838fb692987b611aAdam Lesinski service.init(currentTimeMillis); 1853c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski mUserState.put(userId, service); 1860debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1873c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski return service; 1880debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 1890debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 1900debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski /** 19166143fa5b34eea7413335111838fb692987b611aAdam Lesinski * This should be the only way to get the time from the system. 19266143fa5b34eea7413335111838fb692987b611aAdam Lesinski */ 19366143fa5b34eea7413335111838fb692987b611aAdam Lesinski private long checkAndGetTimeLocked() { 19466143fa5b34eea7413335111838fb692987b611aAdam Lesinski final long actualSystemTime = System.currentTimeMillis(); 19566143fa5b34eea7413335111838fb692987b611aAdam Lesinski final long actualRealtime = SystemClock.elapsedRealtime(); 19666143fa5b34eea7413335111838fb692987b611aAdam Lesinski final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; 19766143fa5b34eea7413335111838fb692987b611aAdam Lesinski if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) { 19866143fa5b34eea7413335111838fb692987b611aAdam Lesinski // The time has changed. 19966143fa5b34eea7413335111838fb692987b611aAdam Lesinski final int userCount = mUserState.size(); 20066143fa5b34eea7413335111838fb692987b611aAdam Lesinski for (int i = 0; i < userCount; i++) { 20166143fa5b34eea7413335111838fb692987b611aAdam Lesinski final UserUsageStatsService service = mUserState.valueAt(i); 20266143fa5b34eea7413335111838fb692987b611aAdam Lesinski service.onTimeChanged(expectedSystemTime, actualSystemTime); 20366143fa5b34eea7413335111838fb692987b611aAdam Lesinski } 20466143fa5b34eea7413335111838fb692987b611aAdam Lesinski mRealTimeSnapshot = actualRealtime; 20566143fa5b34eea7413335111838fb692987b611aAdam Lesinski mSystemTimeSnapshot = actualSystemTime; 20666143fa5b34eea7413335111838fb692987b611aAdam Lesinski } 20766143fa5b34eea7413335111838fb692987b611aAdam Lesinski return actualSystemTime; 20866143fa5b34eea7413335111838fb692987b611aAdam Lesinski } 20966143fa5b34eea7413335111838fb692987b611aAdam Lesinski 21066143fa5b34eea7413335111838fb692987b611aAdam Lesinski /** 21166143fa5b34eea7413335111838fb692987b611aAdam Lesinski * Assuming the event's timestamp is measured in milliseconds since boot, 21266143fa5b34eea7413335111838fb692987b611aAdam Lesinski * convert it to a system wall time. 21366143fa5b34eea7413335111838fb692987b611aAdam Lesinski */ 21466143fa5b34eea7413335111838fb692987b611aAdam Lesinski private void convertToSystemTimeLocked(UsageEvents.Event event) { 21566143fa5b34eea7413335111838fb692987b611aAdam Lesinski event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot; 21666143fa5b34eea7413335111838fb692987b611aAdam Lesinski } 21766143fa5b34eea7413335111838fb692987b611aAdam Lesinski 21866143fa5b34eea7413335111838fb692987b611aAdam Lesinski /** 219d26bea3a1498d1b327ae37cc796fb8cd67e9c977Adam Lesinski * Called by the Binder stub 2200debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski */ 2210debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski void shutdown() { 2220debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski synchronized (mLock) { 2230debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski mHandler.removeMessages(MSG_REPORT_EVENT); 2243c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski flushToDiskLocked(); 2250debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 2260debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 2270debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 2283c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski /** 2293c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * Called by the Binder stub. 2303c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski */ 2313516800b611a79339a3c188332d13a26e9086b09Adam Lesinski void reportEvent(UsageEvents.Event event, int userId) { 2323c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski synchronized (mLock) { 23366143fa5b34eea7413335111838fb692987b611aAdam Lesinski final long timeNow = checkAndGetTimeLocked(); 23466143fa5b34eea7413335111838fb692987b611aAdam Lesinski convertToSystemTimeLocked(event); 23566143fa5b34eea7413335111838fb692987b611aAdam Lesinski 23666143fa5b34eea7413335111838fb692987b611aAdam Lesinski final UserUsageStatsService service = 23766143fa5b34eea7413335111838fb692987b611aAdam Lesinski getUserDataAndInitializeIfNeededLocked(userId, timeNow); 2383c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski service.reportEvent(event); 2390debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 2400debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 2410debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 2420debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski /** 2430debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Called by the Binder stub. 2440debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski */ 2453c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski void flushToDisk() { 2460debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski synchronized (mLock) { 2473c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski flushToDiskLocked(); 2483c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 2493c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski } 2500debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 2513c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski /** 2523c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski * Called by the Binder stub. 2533c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski */ 2543c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski void removeUser(int userId) { 2553c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski synchronized (mLock) { 2563c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski Slog.i(TAG, "Removing user " + userId + " and all data."); 2573c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski mUserState.remove(userId); 2583c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski cleanUpRemovedUsersLocked(); 2590debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 2600debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 2610debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 2620debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski /** 2630debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Called by the Binder stub. 2640debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski */ 2653516800b611a79339a3c188332d13a26e9086b09Adam Lesinski List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) { 2660debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski synchronized (mLock) { 26766143fa5b34eea7413335111838fb692987b611aAdam Lesinski final long timeNow = checkAndGetTimeLocked(); 26866143fa5b34eea7413335111838fb692987b611aAdam Lesinski if (!validRange(timeNow, beginTime, endTime)) { 26966143fa5b34eea7413335111838fb692987b611aAdam Lesinski return null; 27066143fa5b34eea7413335111838fb692987b611aAdam Lesinski } 27166143fa5b34eea7413335111838fb692987b611aAdam Lesinski 27266143fa5b34eea7413335111838fb692987b611aAdam Lesinski final UserUsageStatsService service = 27366143fa5b34eea7413335111838fb692987b611aAdam Lesinski getUserDataAndInitializeIfNeededLocked(userId, timeNow); 2743516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return service.queryUsageStats(bucketType, beginTime, endTime); 2750debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 2760debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 2770debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 2780debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski /** 2790debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * Called by the Binder stub. 2800debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski */ 2817f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime, 2827f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski long endTime) { 2837f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski synchronized (mLock) { 28466143fa5b34eea7413335111838fb692987b611aAdam Lesinski final long timeNow = checkAndGetTimeLocked(); 28566143fa5b34eea7413335111838fb692987b611aAdam Lesinski if (!validRange(timeNow, beginTime, endTime)) { 28666143fa5b34eea7413335111838fb692987b611aAdam Lesinski return null; 28766143fa5b34eea7413335111838fb692987b611aAdam Lesinski } 28866143fa5b34eea7413335111838fb692987b611aAdam Lesinski 28966143fa5b34eea7413335111838fb692987b611aAdam Lesinski final UserUsageStatsService service = 29066143fa5b34eea7413335111838fb692987b611aAdam Lesinski getUserDataAndInitializeIfNeededLocked(userId, timeNow); 2917f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return service.queryConfigurationStats(bucketType, beginTime, endTime); 2927f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 2937f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 2943516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 2957f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski /** 2967f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski * Called by the Binder stub. 2977f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski */ 2987f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski UsageEvents queryEvents(int userId, long beginTime, long endTime) { 2993516800b611a79339a3c188332d13a26e9086b09Adam Lesinski synchronized (mLock) { 30066143fa5b34eea7413335111838fb692987b611aAdam Lesinski final long timeNow = checkAndGetTimeLocked(); 30166143fa5b34eea7413335111838fb692987b611aAdam Lesinski if (!validRange(timeNow, beginTime, endTime)) { 30266143fa5b34eea7413335111838fb692987b611aAdam Lesinski return null; 30366143fa5b34eea7413335111838fb692987b611aAdam Lesinski } 30466143fa5b34eea7413335111838fb692987b611aAdam Lesinski 30566143fa5b34eea7413335111838fb692987b611aAdam Lesinski final UserUsageStatsService service = 30666143fa5b34eea7413335111838fb692987b611aAdam Lesinski getUserDataAndInitializeIfNeededLocked(userId, timeNow); 3073516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return service.queryEvents(beginTime, endTime); 3083516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 3090debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 3100debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 31166143fa5b34eea7413335111838fb692987b611aAdam Lesinski private static boolean validRange(long currentTime, long beginTime, long endTime) { 31266143fa5b34eea7413335111838fb692987b611aAdam Lesinski return beginTime <= currentTime && beginTime < endTime; 3137f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 3147f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 3153c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski private void flushToDiskLocked() { 3163c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski final int userCount = mUserState.size(); 3173c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski for (int i = 0; i < userCount; i++) { 3183c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski UserUsageStatsService service = mUserState.valueAt(i); 3193c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski service.persistActiveStats(); 3200debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 3210debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 3223c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski mHandler.removeMessages(MSG_FLUSH_TO_DISK); 3230debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 3240debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 3251bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski /** 3261bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski * Called by the Binder stub. 3271bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski */ 3281bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski void dump(String[] args, PrintWriter pw) { 3291bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski synchronized (mLock) { 3301bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski IndentingPrintWriter idpw = new IndentingPrintWriter(pw, " "); 3311bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski ArraySet<String> argSet = new ArraySet<>(); 3321bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski argSet.addAll(Arrays.asList(args)); 3331bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski 3341bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski final int userCount = mUserState.size(); 3351bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski for (int i = 0; i < userCount; i++) { 3361bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski idpw.printPair("user", mUserState.keyAt(i)); 3371bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski idpw.println(); 3381bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski idpw.increaseIndent(); 3391bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski if (argSet.contains("--checkin")) { 3401bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski mUserState.valueAt(i).checkin(idpw); 3411bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski } else { 3421bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski mUserState.valueAt(i).dump(idpw); 3431bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski } 3441bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski idpw.decreaseIndent(); 3451bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski } 3461bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski } 3471bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski } 3481bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski 3490debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski class H extends Handler { 3500debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski public H(Looper looper) { 3510debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski super(looper); 3520debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 3530debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 3540debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski @Override 3550debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski public void handleMessage(Message msg) { 3560debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski switch (msg.what) { 3570debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski case MSG_REPORT_EVENT: 3583516800b611a79339a3c188332d13a26e9086b09Adam Lesinski reportEvent((UsageEvents.Event) msg.obj, msg.arg1); 3590debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski break; 3600debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 3610debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski case MSG_FLUSH_TO_DISK: 3623c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski flushToDisk(); 3633c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski break; 3643c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski 3653c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski case MSG_REMOVE_USER: 3663c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski removeUser(msg.arg1); 3670debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski break; 3680debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 3690debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski default: 3700debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski super.handleMessage(msg); 3710debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski break; 3720debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 3730debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 3740debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 3750debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 3760debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski private class BinderService extends IUsageStatsManager.Stub { 3770debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 37853ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski private boolean hasPermission(String callingPackage) { 3797eb599b267d00cbde891c0a87924f2f5086f4497Jeff Hao final int callingUid = Binder.getCallingUid(); 3807eb599b267d00cbde891c0a87924f2f5086f4497Jeff Hao if (callingUid == Process.SYSTEM_UID) { 3817eb599b267d00cbde891c0a87924f2f5086f4497Jeff Hao return true; 3827eb599b267d00cbde891c0a87924f2f5086f4497Jeff Hao } 38353ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski final int mode = mAppOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS, 3847eb599b267d00cbde891c0a87924f2f5086f4497Jeff Hao callingUid, callingPackage); 385e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski if (mode == AppOpsManager.MODE_DEFAULT) { 386e159e2e0b83f9ea9d48f4c8666f9536e9338a70cAdam Lesinski // The default behavior here is to check if PackageManager has given the app 38753ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski // permission. 38853ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski return getContext().checkCallingPermission(Manifest.permission.PACKAGE_USAGE_STATS) 38953ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski == PackageManager.PERMISSION_GRANTED; 39053ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski } 39153ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski return mode == AppOpsManager.MODE_ALLOWED; 39253ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski } 39353ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski 3940debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski @Override 3953516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public ParceledListSlice<UsageStats> queryUsageStats(int bucketType, long beginTime, 3963516800b611a79339a3c188332d13a26e9086b09Adam Lesinski long endTime, String callingPackage) { 39753ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski if (!hasPermission(callingPackage)) { 3983516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return null; 3990debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 4000debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 4013c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski final int userId = UserHandle.getCallingUserId(); 4023c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski final long token = Binder.clearCallingIdentity(); 4030debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski try { 4049a0b289f060e68e42d3db0b843d55cf920f3da12Adam Lesinski final List<UsageStats> results = UsageStatsService.this.queryUsageStats( 4059a0b289f060e68e42d3db0b843d55cf920f3da12Adam Lesinski userId, bucketType, beginTime, endTime); 4069a0b289f060e68e42d3db0b843d55cf920f3da12Adam Lesinski if (results != null) { 4079a0b289f060e68e42d3db0b843d55cf920f3da12Adam Lesinski return new ParceledListSlice<>(results); 4089a0b289f060e68e42d3db0b843d55cf920f3da12Adam Lesinski } 4090debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } finally { 4100debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski Binder.restoreCallingIdentity(token); 4110debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 4129a0b289f060e68e42d3db0b843d55cf920f3da12Adam Lesinski return null; 4130debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 4140debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 4150debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski @Override 4167f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski public ParceledListSlice<ConfigurationStats> queryConfigurationStats(int bucketType, 4177f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski long beginTime, long endTime, String callingPackage) throws RemoteException { 4187f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (!hasPermission(callingPackage)) { 4197f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return null; 4207f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 4217f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 4227f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski final int userId = UserHandle.getCallingUserId(); 4237f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski final long token = Binder.clearCallingIdentity(); 4247f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski try { 4257f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski final List<ConfigurationStats> results = 4267f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski UsageStatsService.this.queryConfigurationStats(userId, bucketType, 4277f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski beginTime, endTime); 4287f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (results != null) { 4297f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return new ParceledListSlice<>(results); 4307f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 4317f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } finally { 4327f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski Binder.restoreCallingIdentity(token); 4337f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 4347f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return null; 4357f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 4367f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 4377f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski @Override 4383516800b611a79339a3c188332d13a26e9086b09Adam Lesinski public UsageEvents queryEvents(long beginTime, long endTime, String callingPackage) { 43953ab92d89069fb0178ba98eb641a6fc87145543aAdam Lesinski if (!hasPermission(callingPackage)) { 4403516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return null; 4410debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 4420debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 4433c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski final int userId = UserHandle.getCallingUserId(); 4443c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski final long token = Binder.clearCallingIdentity(); 4450debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski try { 4463516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return UsageStatsService.this.queryEvents(userId, beginTime, endTime); 4470debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } finally { 4480debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski Binder.restoreCallingIdentity(token); 4490debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 4500debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 4511bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski 4521bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski @Override 4531bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 4541bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 4551bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski != PackageManager.PERMISSION_GRANTED) { 4561bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski pw.println("Permission Denial: can't dump UsageStats from pid=" 4571bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() 4581bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski + " without permission " + android.Manifest.permission.DUMP); 4591bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski return; 4601bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski } 4611bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski UsageStatsService.this.dump(args, pw); 4621bb18c435dbf967f3a9bc9d680411471b8bab4acAdam Lesinski } 4630debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 4640debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 4650debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski /** 4660debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * This local service implementation is primarily used by ActivityManagerService. 4670debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * ActivityManagerService will call these methods holding the 'am' lock, which means we 4680debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski * shouldn't be doing any IO work or other long running tasks in these methods. 4690debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski */ 4700debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski private class LocalService extends UsageStatsManagerInternal { 4710debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 4720debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski @Override 4737f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski public void reportEvent(ComponentName component, int userId, int eventType) { 4743516800b611a79339a3c188332d13a26e9086b09Adam Lesinski if (component == null) { 4753516800b611a79339a3c188332d13a26e9086b09Adam Lesinski Slog.w(TAG, "Event reported without a component name"); 4763516800b611a79339a3c188332d13a26e9086b09Adam Lesinski return; 4773516800b611a79339a3c188332d13a26e9086b09Adam Lesinski } 4783516800b611a79339a3c188332d13a26e9086b09Adam Lesinski 4793516800b611a79339a3c188332d13a26e9086b09Adam Lesinski UsageEvents.Event event = new UsageEvents.Event(); 4809d9607527f5bbf49c96565b63b90e36276b0dda7Adam Lesinski event.mPackage = component.getPackageName(); 4819d9607527f5bbf49c96565b63b90e36276b0dda7Adam Lesinski event.mClass = component.getClassName(); 48266143fa5b34eea7413335111838fb692987b611aAdam Lesinski 48366143fa5b34eea7413335111838fb692987b611aAdam Lesinski // This will later be converted to system time. 48466143fa5b34eea7413335111838fb692987b611aAdam Lesinski event.mTimeStamp = SystemClock.elapsedRealtime(); 48566143fa5b34eea7413335111838fb692987b611aAdam Lesinski 4863516800b611a79339a3c188332d13a26e9086b09Adam Lesinski event.mEventType = eventType; 4873c153519ca5f2b66b88901374383f943c9d77df7Adam Lesinski mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 4880debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 4890debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski 4900debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski @Override 4917f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski public void reportConfigurationChange(Configuration config, int userId) { 4927f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski if (config == null) { 4937f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski Slog.w(TAG, "Configuration event reported with a null config"); 4947f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski return; 4957f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 4967f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 4977f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski UsageEvents.Event event = new UsageEvents.Event(); 4987f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski event.mPackage = "android"; 49966143fa5b34eea7413335111838fb692987b611aAdam Lesinski 50066143fa5b34eea7413335111838fb692987b611aAdam Lesinski // This will later be converted to system time. 50166143fa5b34eea7413335111838fb692987b611aAdam Lesinski event.mTimeStamp = SystemClock.elapsedRealtime(); 50266143fa5b34eea7413335111838fb692987b611aAdam Lesinski 5037f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE; 5047f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski event.mConfiguration = new Configuration(config); 5057f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); 5067f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski } 5077f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski 5087f61e96db7c90c1f4418359672aa4656aebee500Adam Lesinski @Override 5090debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski public void prepareShutdown() { 5100debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski // This method *WILL* do IO work, but we must block until it is finished or else 5110debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski // we might not shutdown cleanly. This is ok to do with the 'am' lock held, because 5120debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski // we are shutting down. 5130debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski shutdown(); 5140debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 5150debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski } 5160debc9aff4c0cbc28e083a948081d91b0f171319Adam Lesinski} 517