Fonctionnement et mise en œuvre du service de statistiques d'utilisation dans Android

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ées
  • queryEventStats() : É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")
        };
    }
}

Étiquettes: UsageStatsService UserUsageStatsService UsageStatsManager UsageStatsDatabase AndroidFramework

Publié le 13 juin à 02h11