193 lines
6.5 KiB
Java
Executable File
193 lines
6.5 KiB
Java
Executable File
/*
|
|
* 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());
|
|
}
|
|
}
|