Vue d'ensemble
UsageStatsService colletce, agrège et stocke les données d'utilisation des applications. Ces données sont accessibles aux applications autorisées via AppOps. Le code source réside dans framework/base/services/usage/java/com/android/server/usage/.
UserUsageStatsService gère spécifiquement les données par utilisateur, créé et démarré par UsageStatsService.
Initilaisation du service
// SystemServer.java
public static void main(String[] args) {
new SystemServer().launch();
}
private void launch() {
startCoreServices();
}
private void startCoreServices() {
mSystemServiceManager.startService(UsageStatsService.class);
mActivityManager.setUsageStatsManager(
LocalServices.getService(UsageStatsManagerInternal.class)
);
}
Cycle de vie du service
@Override
public void onStart() {
File dataDir = new File(Environment.getDataDirectory(), "system");
mStatsDirectory = new File(dataDir, "usagestats");
mStatsDirectory.mkdirs();
registerLocalService(UsageStatsManagerInternal.class, new InternalHandler());
publishBinderService(Context.USAGE_STATS_SERVICE, new ServiceBinder());
initializeUserResources(UserHandle.USER_SYSTEM, System.currentTimeMillis());
}
Gestion des utilisateurs
@Override
public void onUserUnlocked(int userId) {
HashMap<String, Long> packages = fetchInstalledPackages(userId);
synchronized (mLock) {
mActiveUsers.add(userId);
migrateToSystemCe(userId);
initializeUserService(userId, System.currentTimeMillis(), packages);
}
}
private void initializeUserService(int userId, long timestamp,
HashMap<String, Long> packages) {
File userDir = new File(Environment.getDataSystemCeDirectory(userId), "usagestats");
UserUsageStatsService service = new UserUsageStatsService(mContext, userId, userDir);
service.initialize(timestamp, packages);
mUserServices.put(userId, service);
}
Traitement des données
private static final long FLUSH_DELAY = 20 * 60 * 1000;
void persistData() {
synchronized (mLock) {
Event flushEvent = new Event(FLUSH_TO_DISK, SystemClock.elapsedRealtime());
flushEvent.packageName = SYSTEM_PACKAGE;
reportGlobalEvent(flushEvent);
writeToStorage();
}
}
private void writeToStorage() {
for (int i = 0; i < mUserServices.size(); i++) {
int userId = mUserServices.keyAt(i);
UserUsageStatsService service = mUserServices.get(userId);
if (service != null) {
service.commitStats();
}
}
}
UsageStatsManager
Interface client pour accéder aux données d'utilisation. Méthodes principales :
queryUsageStats(): Statistiques agrégéesqueryEventStats(): Événements système
Types d'événements
public static class Event {
public static final int ACTIVITY_RESUMED = 1;
public static final int ACTIVITY_PAUSED = 2;
public static final int DEVICE_SHUTDOWN = 26;
public static final int DEVICE_STARTUP = 27;
public static final int SCREEN_INTERACTIVE = 15;
public static final int SCREEN_NON_INTERACTIVE = 16;
public static final int KEYGUARD_SHOWN = 17;
public static final int KEYGUARD_HIDDEN = 18;
}
Stockage des données
public UserUsageStatsService(Context ctx, int uid, File dir) {
mDatabase = new UsageStatsDatabase(dir);
}
public class UsageStatsDatabase {
public UsageStatsDatabase(File root) {
mIntervalDirectories = new File[] {
new File(root, "daily"),
new File(root, "weekly"),
new File(root, "monthly"),
new File(root, "yearly")
};
}
}