summaryrefslogtreecommitdiff
path: root/services/java/com/android/server/am/UsageStatsService.java
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-02-10 15:44:00 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-02-10 15:44:00 -0800
commitd24b8183b93e781080b2c16c487e60d51c12da31 (patch)
treefbb89154858984eb8e41556da7e9433040d55cd4 /services/java/com/android/server/am/UsageStatsService.java
parentf1e484acb594a726fb57ad0ae4cfe902c7f35858 (diff)
auto import from //branches/cupcake/...@130745
Diffstat (limited to 'services/java/com/android/server/am/UsageStatsService.java')
-rwxr-xr-xservices/java/com/android/server/am/UsageStatsService.java192
1 files changed, 192 insertions, 0 deletions
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
new file mode 100755
index 000000000000..001987fd0ff3
--- /dev/null
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2006-2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.internal.app.IUsageStats;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import com.android.internal.os.PkgUsageStats;
+import android.os.Process;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.util.Log;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This service collects the statistics associated with usage
+ * of various components, like when a particular package is launched or
+ * paused and aggregates events like number of time a component is launched
+ * total duration of a component launch.
+ */
+public final class UsageStatsService extends IUsageStats.Stub {
+ public static final String SERVICE_NAME = "usagestats";
+ private static final boolean localLOGV = false;
+ private static final String TAG = "UsageStats";
+ static IUsageStats sService;
+ private Context mContext;
+ private String mFileName;
+ final private Map<String, PkgUsageStatsExtended> mStats;
+ private String mResumedPkg;
+
+ private class PkgUsageStatsExtended {
+ int mLaunchCount;
+ long mUsageTime;
+ long mChgTime;
+ PkgUsageStatsExtended() {
+ mLaunchCount = 0;
+ mUsageTime = 0;
+ mChgTime = SystemClock.elapsedRealtime();
+ }
+ void updateResume() {
+ mLaunchCount ++;
+ mChgTime = SystemClock.elapsedRealtime();
+ }
+ void updatePause() {
+ long currTime = SystemClock.elapsedRealtime();
+ mUsageTime += (currTime - mChgTime);
+ mChgTime = currTime;
+ }
+ }
+
+ UsageStatsService(String filename) {
+ mFileName = filename;
+ mStats = new HashMap<String, PkgUsageStatsExtended>();
+ }
+
+ public void publish(Context context) {
+ mContext = context;
+ ServiceManager.addService(SERVICE_NAME, asBinder());
+ }
+
+ public static IUsageStats getService() {
+ if (sService != null) {
+ return sService;
+ }
+ IBinder b = ServiceManager.getService(SERVICE_NAME);
+ sService = asInterface(b);
+ return sService;
+ }
+
+ public void noteResumeComponent(ComponentName componentName) {
+ enforceCallingPermission();
+ String pkgName;
+ if ((componentName == null) ||
+ ((pkgName = componentName.getPackageName()) == null)) {
+ return;
+ }
+ if ((mResumedPkg != null) && (mResumedPkg.equalsIgnoreCase(pkgName))) {
+ // Moving across activities in same package. just return
+ return;
+ }
+ if (localLOGV) Log.i(TAG, "started component:"+pkgName);
+ PkgUsageStatsExtended pus = mStats.get(pkgName);
+ if (pus == null) {
+ pus = new PkgUsageStatsExtended();
+ mStats.put(pkgName, pus);
+ }
+ pus.updateResume();
+ mResumedPkg = pkgName;
+ }
+
+ public void notePauseComponent(ComponentName componentName) {
+ enforceCallingPermission();
+ String pkgName;
+ if ((componentName == null) ||
+ ((pkgName = componentName.getPackageName()) == null)) {
+ return;
+ }
+ if ((mResumedPkg == null) || (!pkgName.equalsIgnoreCase(mResumedPkg))) {
+ Log.w(TAG, "Something wrong here, Didn't expect "+pkgName+" to be paused");
+ return;
+ }
+ if (localLOGV) Log.i(TAG, "paused component:"+pkgName);
+ PkgUsageStatsExtended pus = mStats.get(pkgName);
+ if (pus == null) {
+ // Weird some error here
+ Log.w(TAG, "No package stats for pkg:"+pkgName);
+ return;
+ }
+ pus.updatePause();
+ }
+
+ public void enforceCallingPermission() {
+ if (Binder.getCallingPid() == Process.myPid()) {
+ return;
+ }
+ mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
+ Binder.getCallingPid(), Binder.getCallingUid(), null);
+ }
+
+ public PkgUsageStats getPkgUsageStats(ComponentName componentName) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.PACKAGE_USAGE_STATS, null);
+ String pkgName;
+ if ((componentName == null) ||
+ ((pkgName = componentName.getPackageName()) == null)) {
+ return null;
+ }
+ PkgUsageStatsExtended pus = mStats.get(pkgName);
+ if (pus == null) {
+ return null;
+ }
+ return new PkgUsageStats(pkgName, pus.mLaunchCount, pus.mUsageTime);
+ }
+
+ public PkgUsageStats[] getAllPkgUsageStats() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.PACKAGE_USAGE_STATS, null);
+ synchronized (mStats) {
+ Set<String> keys = mStats.keySet();
+ int size = keys.size();
+ if (size <= 0) {
+ return null;
+ }
+ PkgUsageStats retArr[] = new PkgUsageStats[size];
+ int i = 0;
+ for (String key: keys) {
+ PkgUsageStatsExtended pus = mStats.get(key);
+ retArr[i] = new PkgUsageStats(key, pus.mLaunchCount, pus.mUsageTime);
+ i++;
+ }
+ return retArr;
+ }
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ StringBuilder sb = new StringBuilder();
+ synchronized (mStats) {
+ Set<String> keys = mStats.keySet();
+ for (String key: keys) {
+ PkgUsageStatsExtended ps = mStats.get(key);
+ sb.append("pkg=");
+ sb.append(key);
+ sb.append(", launchCount=");
+ sb.append(ps.mLaunchCount);
+ sb.append(", usageTime=");
+ sb.append(ps.mUsageTime+" ms\n");
+ }
+ }
+ pw.write(sb.toString());
+ }
+}