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