In developing PhoneLab Conductor, I need to get various statistics about a installed package to determine if a app is actively used by participant. For example, for interactive apps, I’d like to know how many times the user launches the app, and how long user actively interact with the app. For background apps (e.g., data collection), I’d like to know how long the background service has been running.
There is this dumpsys tool in Android which will provide various information about the status of the system, including package statistics.
Here is the sample output.
root@android:/ # dumpsys usagestats
Date: 20140402
com.android.launcher: 2 times, 43748 ms
com.android.launcher2.Launcher: 2 starts
com.tencent.mm: 1 times, 167750 ms
com.tencent.mm.ui.chatting.ChattingUI: 4 starts, 1000-1500ms=2, 4000-5000ms=1
com.tencent.mm.ui.tools.ImageGalleryUI: 1 starts, 250-500ms=1
com.tencent.mm.ui.LauncherUI: 4 starts, 2000-3000ms=1
com.tencent.mm.ui.friend.FMessageConversationUI: 1 starts, 250-500ms=1
com.android.settings: 2 times, 93065 ms
com.android.settings.Settings: 2 starts
com.android.settings.SubSettings: 2 starts, 250-500ms=1, 500-750ms=2
com.google.android.gm: 1 times, 11396 ms
com.google.android.
At first glance, this is a perfect fit for my purpose. But there’re two problems.
After poking around Android Settings app’s source code, I found there is one internal interface called IUsageStats
. It’s defined in framework/base/core/java/com/android/internal/app/IUsageStats.aidl
inside AOSP tree. You can find it here
package com.android.internal.app;
import android.content.ComponentName;
import com.android.internal.os.PkgUsageStats;
interface IUsageStats {
void noteResumeComponent(in ComponentName componentName);
void notePauseComponent(in ComponentName componentName);
void noteLaunchTime(in ComponentName componentName, int millis);
PkgUsageStats getPkgUsageStats(in ComponentName componentName);
PkgUsageStats[] getAllPkgUsageStats();
}
Where PkgUsageStats
class is defined in framework/base/core/java/com/android/internal/os/PkgUsageStats.java
link.
public class PkgUsageStats implements Parcelable {
public String packageName;
public int launchCount;
public long usageTime;
public Map componentResumeTimes;
// other stuff...
}
It contains all the information I need about foreground apps!
Now is the problem of how to access the internal class and interface of Android. There’s plenty way to do this. Since I have aosp source tree at hand, I just copy those two files into my project. For PkgUsageStats
, I also need to copy the aidl file (framework/base/core/java/com/android/internal/os/PkgUsageStats.aidl
).
Here is the final directory structure of my src
folder.
|
Here is the code snippet that get the IUsageStats
service.
|
Here I use Java reflection to get the class of android.os.ServiceManager
, which is also internal interface.
After that, you just get all the package statistics like so:
|
It seems that Settings->Apps->Running Apps are already showing the information that how long a process or service has been running.
After inspecting the source code of Settings app, I found that information is coming from ActivityManager.RunningServiceInfo
. There is a field named activeSince
, which is the time when the service was first made active.
It seems the reflection need system permission (I haven’t tested yet). Since we build our own platform, it’s not a problem–we just sign our apk with the platform key and declare our app’s user as system in AndroidManifest.xml
.
转自:http://jhshi.me/2014/04/02/get-package-usage-statistics-in-android/
1
|
|
But if you don’t have the platform key, then this approach probably won’t work. The other way I can think of is you run the dumpsys
command and parse the output, but it still requites root permission.