Loading services/usage/java/com/android/server/usage/UsageStatsService.java +40 −32 Original line number Original line Diff line number Diff line Loading @@ -76,7 +76,6 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArrayMap; import android.util.ArraySet; import android.util.ArraySet; import android.util.AtomicFile; import android.util.AtomicFile; Loading Loading @@ -140,13 +139,26 @@ public class UsageStatsService extends SystemService implements private static final boolean ENABLE_KERNEL_UPDATES = true; private static final boolean ENABLE_KERNEL_UPDATES = true; private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set"); private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set"); private static final File USAGE_STATS_LEGACY_DIR = new File( // /data/system/usagestats. Now only used for globalcomponentusage. Previously per-user stats Environment.getDataSystemDirectory(), "usagestats"); // were stored here too, but they've been moved to /data/system_ce/$userId/usagestats. // For migration purposes, indicates whether to keep the legacy usage stats directory or not private static final File COMMON_USAGE_STATS_DIR = private static final boolean KEEP_LEGACY_DIR = false; new File(Environment.getDataSystemDirectory(), "usagestats"); private static final File LEGACY_USER_USAGE_STATS_DIR = COMMON_USAGE_STATS_DIR; private static final File COMMON_USAGE_STATS_DE_DIR = // /data/system_de/usagestats. When the globalcomponentusage file was added, it was incorrectly // added here instead of in /data/system/usagestats where it should be. We lazily migrate this // file by reading it from here if needed, and always writing it to the new path. We don't // delete the old directory, as system_server no longer has permission to do so. // // Note, this migration is *not* related to the migration of the per-user stats from // /data/system/usagestats/$userId to /data/system_ce/$userId/usagestats mentioned above. Both // of these just happen to involve /data/system/usagestats. /data/system is the right place for // system data not tied to a user, but the wrong place for per-user data. So due to two // separate mistakes, we've unfortunately ended up with one case where we need to move files out // of /data/system, and one case where we need to move a different file *into* /data/system. private static final File LEGACY_COMMON_USAGE_STATS_DIR = new File(Environment.getDataSystemDeDirectory(), "usagestats"); new File(Environment.getDataSystemDeDirectory(), "usagestats"); private static final String GLOBAL_COMPONENT_USAGE_FILE_NAME = "globalcomponentusage"; private static final String GLOBAL_COMPONENT_USAGE_FILE_NAME = "globalcomponentusage"; private static final char TOKEN_DELIMITER = '/'; private static final char TOKEN_DELIMITER = '/'; Loading Loading @@ -630,7 +642,7 @@ public class UsageStatsService extends SystemService implements final int previousVersion = Integer.parseInt(reader.readLine()); final int previousVersion = Integer.parseInt(reader.readLine()); // UsageStatsDatabase.BACKUP_VERSION was 4 when usage stats were migrated to CE. // UsageStatsDatabase.BACKUP_VERSION was 4 when usage stats were migrated to CE. if (previousVersion >= 4) { if (previousVersion >= 4) { deleteLegacyDir(userId); deleteLegacyUserDir(userId); return; return; } } // If migration logic needs to be changed in a future version, do it here. // If migration logic needs to be changed in a future version, do it here. Loading @@ -651,7 +663,7 @@ public class UsageStatsService extends SystemService implements } } Slog.i(TAG, "Starting migration to system CE for user " + userId); Slog.i(TAG, "Starting migration to system CE for user " + userId); final File legacyUserDir = new File(USAGE_STATS_LEGACY_DIR, Integer.toString(userId)); final File legacyUserDir = new File(LEGACY_USER_USAGE_STATS_DIR, Integer.toString(userId)); if (legacyUserDir.exists()) { if (legacyUserDir.exists()) { copyRecursively(usageStatsDir, legacyUserDir); copyRecursively(usageStatsDir, legacyUserDir); } } Loading @@ -666,8 +678,8 @@ public class UsageStatsService extends SystemService implements } } Slog.i(TAG, "Finished migration to system CE for user " + userId); Slog.i(TAG, "Finished migration to system CE for user " + userId); // Migration was successful - delete the legacy directory // Migration was successful - delete the legacy user directory deleteLegacyDir(userId); deleteLegacyUserDir(userId); } } private static void copyRecursively(final File parent, File f) { private static void copyRecursively(final File parent, File f) { Loading Loading @@ -698,21 +710,14 @@ public class UsageStatsService extends SystemService implements } } } } private void deleteLegacyDir(int userId) { private void deleteLegacyUserDir(int userId) { final File legacyUserDir = new File(USAGE_STATS_LEGACY_DIR, Integer.toString(userId)); final File legacyUserDir = new File(LEGACY_USER_USAGE_STATS_DIR, Integer.toString(userId)); if (!KEEP_LEGACY_DIR && legacyUserDir.exists()) { if (legacyUserDir.exists()) { deleteRecursively(legacyUserDir); deleteRecursively(legacyUserDir); if (legacyUserDir.exists()) { if (legacyUserDir.exists()) { Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats " Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats " + "dir for user " + userId); + "dir for user " + userId); } } // If all users have been migrated, delete the parent legacy usage stats directory if (USAGE_STATS_LEGACY_DIR.list() != null && USAGE_STATS_LEGACY_DIR.list().length == 0) { if (!USAGE_STATS_LEGACY_DIR.delete()) { Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats dir"); } } } } } } Loading Loading @@ -807,13 +812,16 @@ public class UsageStatsService extends SystemService implements } } private void loadGlobalComponentUsageLocked() { private void loadGlobalComponentUsageLocked() { final File[] packageUsageFile = COMMON_USAGE_STATS_DE_DIR.listFiles( AtomicFile af = new AtomicFile(new File(COMMON_USAGE_STATS_DIR, (dir, name) -> TextUtils.equals(name, GLOBAL_COMPONENT_USAGE_FILE_NAME)); GLOBAL_COMPONENT_USAGE_FILE_NAME)); if (packageUsageFile == null || packageUsageFile.length == 0) { if (!af.exists()) { af = new AtomicFile(new File(LEGACY_COMMON_USAGE_STATS_DIR, GLOBAL_COMPONENT_USAGE_FILE_NAME)); if (!af.exists()) { return; return; } } Slog.i(TAG, "Reading " + GLOBAL_COMPONENT_USAGE_FILE_NAME + " file from old location"); final AtomicFile af = new AtomicFile(packageUsageFile[0]); } final Map<String, Long> tmpUsage = new ArrayMap<>(); final Map<String, Long> tmpUsage = new ArrayMap<>(); try { try { try (FileInputStream in = af.openRead()) { try (FileInputStream in = af.openRead()) { Loading @@ -831,7 +839,7 @@ public class UsageStatsService extends SystemService implements } } } catch (Exception e) { } catch (Exception e) { // Most likely trying to read a corrupted file - log the failure // Most likely trying to read a corrupted file - log the failure Slog.e(TAG, "Could not read " + packageUsageFile[0]); Slog.e(TAG, "Could not read " + af.getBaseFile()); } } } } Loading @@ -840,11 +848,11 @@ public class UsageStatsService extends SystemService implements return; return; } } if (!COMMON_USAGE_STATS_DE_DIR.mkdirs() && !COMMON_USAGE_STATS_DE_DIR.exists()) { if (!COMMON_USAGE_STATS_DIR.mkdirs() && !COMMON_USAGE_STATS_DIR.exists()) { throw new IllegalStateException("Common usage stats DE directory does not exist: " throw new IllegalStateException("Common usage stats directory does not exist: " + COMMON_USAGE_STATS_DE_DIR.getAbsolutePath()); + COMMON_USAGE_STATS_DIR.getAbsolutePath()); } } final File lastTimePackageFile = new File(COMMON_USAGE_STATS_DE_DIR, final File lastTimePackageFile = new File(COMMON_USAGE_STATS_DIR, GLOBAL_COMPONENT_USAGE_FILE_NAME); GLOBAL_COMPONENT_USAGE_FILE_NAME); final AtomicFile af = new AtomicFile(lastTimePackageFile); final AtomicFile af = new AtomicFile(lastTimePackageFile); FileOutputStream fos = null; FileOutputStream fos = null; Loading Loading
services/usage/java/com/android/server/usage/UsageStatsService.java +40 −32 Original line number Original line Diff line number Diff line Loading @@ -76,7 +76,6 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserHandle; import android.os.UserManager; import android.os.UserManager; import android.provider.Settings; import android.provider.Settings; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArrayMap; import android.util.ArraySet; import android.util.ArraySet; import android.util.AtomicFile; import android.util.AtomicFile; Loading Loading @@ -140,13 +139,26 @@ public class UsageStatsService extends SystemService implements private static final boolean ENABLE_KERNEL_UPDATES = true; private static final boolean ENABLE_KERNEL_UPDATES = true; private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set"); private static final File KERNEL_COUNTER_FILE = new File("/proc/uid_procstat/set"); private static final File USAGE_STATS_LEGACY_DIR = new File( // /data/system/usagestats. Now only used for globalcomponentusage. Previously per-user stats Environment.getDataSystemDirectory(), "usagestats"); // were stored here too, but they've been moved to /data/system_ce/$userId/usagestats. // For migration purposes, indicates whether to keep the legacy usage stats directory or not private static final File COMMON_USAGE_STATS_DIR = private static final boolean KEEP_LEGACY_DIR = false; new File(Environment.getDataSystemDirectory(), "usagestats"); private static final File LEGACY_USER_USAGE_STATS_DIR = COMMON_USAGE_STATS_DIR; private static final File COMMON_USAGE_STATS_DE_DIR = // /data/system_de/usagestats. When the globalcomponentusage file was added, it was incorrectly // added here instead of in /data/system/usagestats where it should be. We lazily migrate this // file by reading it from here if needed, and always writing it to the new path. We don't // delete the old directory, as system_server no longer has permission to do so. // // Note, this migration is *not* related to the migration of the per-user stats from // /data/system/usagestats/$userId to /data/system_ce/$userId/usagestats mentioned above. Both // of these just happen to involve /data/system/usagestats. /data/system is the right place for // system data not tied to a user, but the wrong place for per-user data. So due to two // separate mistakes, we've unfortunately ended up with one case where we need to move files out // of /data/system, and one case where we need to move a different file *into* /data/system. private static final File LEGACY_COMMON_USAGE_STATS_DIR = new File(Environment.getDataSystemDeDirectory(), "usagestats"); new File(Environment.getDataSystemDeDirectory(), "usagestats"); private static final String GLOBAL_COMPONENT_USAGE_FILE_NAME = "globalcomponentusage"; private static final String GLOBAL_COMPONENT_USAGE_FILE_NAME = "globalcomponentusage"; private static final char TOKEN_DELIMITER = '/'; private static final char TOKEN_DELIMITER = '/'; Loading Loading @@ -630,7 +642,7 @@ public class UsageStatsService extends SystemService implements final int previousVersion = Integer.parseInt(reader.readLine()); final int previousVersion = Integer.parseInt(reader.readLine()); // UsageStatsDatabase.BACKUP_VERSION was 4 when usage stats were migrated to CE. // UsageStatsDatabase.BACKUP_VERSION was 4 when usage stats were migrated to CE. if (previousVersion >= 4) { if (previousVersion >= 4) { deleteLegacyDir(userId); deleteLegacyUserDir(userId); return; return; } } // If migration logic needs to be changed in a future version, do it here. // If migration logic needs to be changed in a future version, do it here. Loading @@ -651,7 +663,7 @@ public class UsageStatsService extends SystemService implements } } Slog.i(TAG, "Starting migration to system CE for user " + userId); Slog.i(TAG, "Starting migration to system CE for user " + userId); final File legacyUserDir = new File(USAGE_STATS_LEGACY_DIR, Integer.toString(userId)); final File legacyUserDir = new File(LEGACY_USER_USAGE_STATS_DIR, Integer.toString(userId)); if (legacyUserDir.exists()) { if (legacyUserDir.exists()) { copyRecursively(usageStatsDir, legacyUserDir); copyRecursively(usageStatsDir, legacyUserDir); } } Loading @@ -666,8 +678,8 @@ public class UsageStatsService extends SystemService implements } } Slog.i(TAG, "Finished migration to system CE for user " + userId); Slog.i(TAG, "Finished migration to system CE for user " + userId); // Migration was successful - delete the legacy directory // Migration was successful - delete the legacy user directory deleteLegacyDir(userId); deleteLegacyUserDir(userId); } } private static void copyRecursively(final File parent, File f) { private static void copyRecursively(final File parent, File f) { Loading Loading @@ -698,21 +710,14 @@ public class UsageStatsService extends SystemService implements } } } } private void deleteLegacyDir(int userId) { private void deleteLegacyUserDir(int userId) { final File legacyUserDir = new File(USAGE_STATS_LEGACY_DIR, Integer.toString(userId)); final File legacyUserDir = new File(LEGACY_USER_USAGE_STATS_DIR, Integer.toString(userId)); if (!KEEP_LEGACY_DIR && legacyUserDir.exists()) { if (legacyUserDir.exists()) { deleteRecursively(legacyUserDir); deleteRecursively(legacyUserDir); if (legacyUserDir.exists()) { if (legacyUserDir.exists()) { Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats " Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats " + "dir for user " + userId); + "dir for user " + userId); } } // If all users have been migrated, delete the parent legacy usage stats directory if (USAGE_STATS_LEGACY_DIR.list() != null && USAGE_STATS_LEGACY_DIR.list().length == 0) { if (!USAGE_STATS_LEGACY_DIR.delete()) { Slog.w(TAG, "Error occurred while attempting to delete legacy usage stats dir"); } } } } } } Loading Loading @@ -807,13 +812,16 @@ public class UsageStatsService extends SystemService implements } } private void loadGlobalComponentUsageLocked() { private void loadGlobalComponentUsageLocked() { final File[] packageUsageFile = COMMON_USAGE_STATS_DE_DIR.listFiles( AtomicFile af = new AtomicFile(new File(COMMON_USAGE_STATS_DIR, (dir, name) -> TextUtils.equals(name, GLOBAL_COMPONENT_USAGE_FILE_NAME)); GLOBAL_COMPONENT_USAGE_FILE_NAME)); if (packageUsageFile == null || packageUsageFile.length == 0) { if (!af.exists()) { af = new AtomicFile(new File(LEGACY_COMMON_USAGE_STATS_DIR, GLOBAL_COMPONENT_USAGE_FILE_NAME)); if (!af.exists()) { return; return; } } Slog.i(TAG, "Reading " + GLOBAL_COMPONENT_USAGE_FILE_NAME + " file from old location"); final AtomicFile af = new AtomicFile(packageUsageFile[0]); } final Map<String, Long> tmpUsage = new ArrayMap<>(); final Map<String, Long> tmpUsage = new ArrayMap<>(); try { try { try (FileInputStream in = af.openRead()) { try (FileInputStream in = af.openRead()) { Loading @@ -831,7 +839,7 @@ public class UsageStatsService extends SystemService implements } } } catch (Exception e) { } catch (Exception e) { // Most likely trying to read a corrupted file - log the failure // Most likely trying to read a corrupted file - log the failure Slog.e(TAG, "Could not read " + packageUsageFile[0]); Slog.e(TAG, "Could not read " + af.getBaseFile()); } } } } Loading @@ -840,11 +848,11 @@ public class UsageStatsService extends SystemService implements return; return; } } if (!COMMON_USAGE_STATS_DE_DIR.mkdirs() && !COMMON_USAGE_STATS_DE_DIR.exists()) { if (!COMMON_USAGE_STATS_DIR.mkdirs() && !COMMON_USAGE_STATS_DIR.exists()) { throw new IllegalStateException("Common usage stats DE directory does not exist: " throw new IllegalStateException("Common usage stats directory does not exist: " + COMMON_USAGE_STATS_DE_DIR.getAbsolutePath()); + COMMON_USAGE_STATS_DIR.getAbsolutePath()); } } final File lastTimePackageFile = new File(COMMON_USAGE_STATS_DE_DIR, final File lastTimePackageFile = new File(COMMON_USAGE_STATS_DIR, GLOBAL_COMPONENT_USAGE_FILE_NAME); GLOBAL_COMPONENT_USAGE_FILE_NAME); final AtomicFile af = new AtomicFile(lastTimePackageFile); final AtomicFile af = new AtomicFile(lastTimePackageFile); FileOutputStream fos = null; FileOutputStream fos = null; Loading