diff options
Diffstat (limited to 'services/java/com/android/server/am/UsageStatsService.java')
-rwxr-xr-x | services/java/com/android/server/am/UsageStatsService.java | 192 |
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()); + } +} |