Loading core/java/android/app/usage/UsageStatsManagerInternal.java +7 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package android.app.usage; import android.content.ComponentName; import android.content.res.Configuration; import java.io.IOException; /** * UsageStatsManager local system service interface. * Loading Loading @@ -109,4 +111,9 @@ public abstract class UsageStatsManagerInternal { public abstract void onParoleStateChanged(boolean isParoleOn); } /* Backup/Restore API */ public abstract byte[] getBackupPayload(int user, String key); public abstract void applyRestoredPayload(int user, String key, byte[] payload); } core/java/com/android/server/backup/SystemBackupAgent.java +4 −2 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ public class SystemBackupAgent extends BackupAgentHelper { private static final String PREFERRED_HELPER = "preferred_activities"; private static final String NOTIFICATION_HELPER = "notifications"; private static final String PERMISSION_HELPER = "permissions"; private static final String USAGE_STATS_HELPER = "usage_stats"; // These paths must match what the WallpaperManagerService uses. The leaf *_FILENAME // are also used in the full-backup file format, so must not change unless steps are Loading Loading @@ -96,7 +97,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper()); addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this)); addHelper(PERMISSION_HELPER, new PermissionBackupHelper()); addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); super.onBackup(oldState, data, newState); } Loading Loading @@ -131,6 +132,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper()); addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this)); addHelper(PERMISSION_HELPER, new PermissionBackupHelper()); addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); try { super.onRestore(data, appVersionCode, newState); Loading core/java/com/android/server/backup/UsageStatsBackupHelper.java 0 → 100644 +70 −0 Original line number Diff line number Diff line package com.android.server.backup; import android.app.backup.BlobBackupHelper; import android.app.usage.IUsageStatsManager; import android.app.usage.UsageStatsManagerInternal; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.util.Log; import com.android.server.LocalServices; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class UsageStatsBackupHelper extends BlobBackupHelper { static final String TAG = "UsgStatsBackupHelper"; // must be < 23 chars static final boolean DEBUG = false; // Current version of the blob schema static final int BLOB_VERSION = 1; // Key under which the payload blob is stored // same as UsageStatsBackupHelperAssistant.KEY_USAGE_STATS static final String KEY_USAGE_STATS = "usage_stats"; public UsageStatsBackupHelper(Context context) { super(BLOB_VERSION, KEY_USAGE_STATS); } @Override protected byte[] getBackupPayload(String key) { if(KEY_USAGE_STATS.equals(key)) { UsageStatsManagerInternal localUsageStatsManager = LocalServices.getService(UsageStatsManagerInternal.class); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(baos); try{ out.writeInt(UserHandle.USER_SYSTEM); out.write(localUsageStatsManager.getBackupPayload(UserHandle.USER_SYSTEM, key)); } catch (IOException ioe){ if (DEBUG) Log.e(TAG, "Failed to backup Usage Stats", ioe); baos.reset(); } return baos.toByteArray(); } return null; } @Override protected void applyRestoredPayload(String key, byte[] payload) { if (KEY_USAGE_STATS.equals(key)) { UsageStatsManagerInternal localUsageStatsManager = LocalServices.getService(UsageStatsManagerInternal.class); DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload)); try{ int user = in.readInt(); byte[] restoreData = new byte[payload.length - 4]; in.read(restoreData, 0, payload.length-4); localUsageStatsManager.applyRestoredPayload(user, key, restoreData); } catch (IOException ioe){ if (DEBUG) Log.e(TAG, "Failed to restore Usage Stats", ioe); } } } } services/usage/java/com/android/server/usage/UsageStatsDatabase.java +195 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.usage; import android.app.usage.TimeSparseArray; import android.app.usage.UsageStats; import android.app.usage.UsageStatsManager; import android.os.Build; import android.util.AtomicFile; Loading @@ -25,6 +26,10 @@ import android.util.TimeUtils; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileReader; import java.io.FileWriter; Loading @@ -39,6 +44,14 @@ import java.util.List; class UsageStatsDatabase { private static final int CURRENT_VERSION = 3; // Current version of the backup schema static final int BACKUP_STATE_VERSION = 1; // Key under which the payload blob is stored // same as UsageStatsBackupHelper.KEY_USAGE_STATS static final String KEY_USAGE_STATS = "usage_stats"; private static final String TAG = "UsageStatsDatabase"; private static final boolean DEBUG = UsageStatsService.DEBUG; private static final String BAK_SUFFIX = ".bak"; Loading Loading @@ -539,4 +552,186 @@ class UsageStatsDatabase { stats.lastTimeSaved = f.getLastModifiedTime(); } } /* Backup/Restore Code */ protected byte[] getBackupPayload(String key){ synchronized (mLock) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); if (KEY_USAGE_STATS.equals(key)) { prune(System.currentTimeMillis()); DataOutputStream out = new DataOutputStream(baos); try { out.writeInt(BACKUP_STATE_VERSION); out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY].size()); for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY].size(); i++){ writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY].valueAt(i)); } out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_WEEKLY].size()); for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_WEEKLY].size(); i++){ writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_WEEKLY].valueAt(i)); } out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_MONTHLY].size()); for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_MONTHLY].size(); i++){ writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_MONTHLY].valueAt(i)); } out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_YEARLY].size()); for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_YEARLY].size(); i++){ writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_YEARLY].valueAt(i)); } if (DEBUG) Slog.i(TAG, "Written " + baos.size() + " bytes of data"); } catch (IOException ioe){ Slog.d(TAG, "Failed to write data to output stream", ioe); baos.reset(); } } return baos.toByteArray(); } } protected void applyRestoredPayload(String key, byte[] payload){ synchronized (mLock) { if (KEY_USAGE_STATS.equals(key)) { // Read stats files for the current device configs IntervalStats dailyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_DAILY); IntervalStats weeklyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_WEEKLY); IntervalStats monthlyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_MONTHLY); IntervalStats yearlyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_YEARLY); // Delete all stats files for(int i = 0; i<mIntervalDirs.length; i++){ deleteDirectoryContents(mIntervalDirs[i]); } try { DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload)); int stateVersion = in.readInt(); int fileCount = in.readInt(); for(int i = 0; i<fileCount; i++){ IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in)); stats = mergeStats(stats, dailyConfigSource); putUsageStats(UsageStatsManager.INTERVAL_DAILY, stats); } fileCount = in.readInt(); for(int i = 0; i<fileCount; i++){ IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in)); stats = mergeStats(stats, weeklyConfigSource); putUsageStats(UsageStatsManager.INTERVAL_WEEKLY, stats); } fileCount = in.readInt(); for(int i = 0; i<fileCount; i++){ IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in)); stats = mergeStats(stats, monthlyConfigSource); putUsageStats(UsageStatsManager.INTERVAL_MONTHLY, stats); } fileCount = in.readInt(); for(int i = 0; i<fileCount; i++){ IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in)); stats = mergeStats(stats, yearlyConfigSource); putUsageStats(UsageStatsManager.INTERVAL_YEARLY, stats); } if (DEBUG) Slog.i(TAG, "Completed Restoring UsageStats"); } catch (IOException ioe){ Slog.d(TAG, "Failed to read data from input stream", ioe); } finally { indexFilesLocked(); } } } } /** * Get the Configuration Statistics from the current device statistics and merge them * with the backed up usage statistics. */ private IntervalStats mergeStats(IntervalStats beingRestored, IntervalStats onDevice) { beingRestored.activeConfiguration = onDevice.activeConfiguration; beingRestored.configurations.putAll(onDevice.configurations); beingRestored.events = onDevice.events; return beingRestored; } private void writeIntervalStatsToStream(DataOutputStream out, AtomicFile statsFile) throws IOException{ IntervalStats stats = new IntervalStats(); try { UsageStatsXml.read(statsFile, stats); } catch (IOException e) { Slog.e(TAG, "Failed to read usage stats file", e); out.writeInt(0); return; } sanitizeIntervalStatsForBackup(stats); byte[] data = serializeIntervalStats(stats); out.writeInt(data.length); out.write(data); } private static byte[] getIntervalStatsBytes(DataInputStream in) throws IOException { int length = in.readInt(); byte[] buffer = new byte[length]; in.read(buffer, 0, length); return buffer; } private static void sanitizeIntervalStatsForBackup(IntervalStats stats) { if (stats == null) return; stats.activeConfiguration = null; stats.configurations.clear(); if (stats.events != null) stats.events.clear(); } private static byte[] serializeIntervalStats(IntervalStats stats) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(baos); try { out.writeLong(stats.beginTime); UsageStatsXml.write(out, stats); } catch (IOException ioe) { Slog.d(TAG, "Serializing IntervalStats Failed", ioe); baos.reset(); } return baos.toByteArray(); } private static IntervalStats deserializeIntervalStats(byte[] data) { ByteArrayInputStream bais = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bais); IntervalStats stats = new IntervalStats(); try { stats.beginTime = in.readLong(); UsageStatsXml.read(in, stats); } catch (IOException ioe) { Slog.d(TAG, "DeSerializing IntervalStats Failed", ioe); stats = null; } return stats; } private static void deleteDirectoryContents(File directory){ File[] files = directory.listFiles(); for (File file : files) { deleteDirectory(file); } } private static void deleteDirectory(File directory) { File[] files = directory.listFiles(); for (File file : files) { if (!file.isDirectory()) { file.delete(); } else { deleteDirectory(file); } } directory.delete(); } } services/usage/java/com/android/server/usage/UsageStatsService.java +23 −0 Original line number Diff line number Diff line Loading @@ -1310,6 +1310,8 @@ public class UsageStatsService extends SystemService implements } UsageStatsService.this.dump(args, pw); } } /** Loading Loading @@ -1416,5 +1418,26 @@ public class UsageStatsService extends SystemService implements AppIdleStateChangeListener listener) { UsageStatsService.this.removeListener(listener); } @Override public byte[] getBackupPayload(int user, String key) { // Check to ensure that only user 0's data is b/r for now if (user == UserHandle.USER_SYSTEM) { final UserUsageStatsService userStats = getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked()); return userStats.getBackupPayload(key); } else { return null; } } @Override public void applyRestoredPayload(int user, String key, byte[] payload) { if (user == UserHandle.USER_SYSTEM) { final UserUsageStatsService userStats = getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked()); userStats.applyRestoredPayload(key, payload); } } } } Loading
core/java/android/app/usage/UsageStatsManagerInternal.java +7 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ package android.app.usage; import android.content.ComponentName; import android.content.res.Configuration; import java.io.IOException; /** * UsageStatsManager local system service interface. * Loading Loading @@ -109,4 +111,9 @@ public abstract class UsageStatsManagerInternal { public abstract void onParoleStateChanged(boolean isParoleOn); } /* Backup/Restore API */ public abstract byte[] getBackupPayload(int user, String key); public abstract void applyRestoredPayload(int user, String key, byte[] payload); }
core/java/com/android/server/backup/SystemBackupAgent.java +4 −2 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ public class SystemBackupAgent extends BackupAgentHelper { private static final String PREFERRED_HELPER = "preferred_activities"; private static final String NOTIFICATION_HELPER = "notifications"; private static final String PERMISSION_HELPER = "permissions"; private static final String USAGE_STATS_HELPER = "usage_stats"; // These paths must match what the WallpaperManagerService uses. The leaf *_FILENAME // are also used in the full-backup file format, so must not change unless steps are Loading Loading @@ -96,7 +97,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper()); addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this)); addHelper(PERMISSION_HELPER, new PermissionBackupHelper()); addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); super.onBackup(oldState, data, newState); } Loading Loading @@ -131,6 +132,7 @@ public class SystemBackupAgent extends BackupAgentHelper { addHelper(PREFERRED_HELPER, new PreferredActivityBackupHelper()); addHelper(NOTIFICATION_HELPER, new NotificationBackupHelper(this)); addHelper(PERMISSION_HELPER, new PermissionBackupHelper()); addHelper(USAGE_STATS_HELPER, new UsageStatsBackupHelper(this)); try { super.onRestore(data, appVersionCode, newState); Loading
core/java/com/android/server/backup/UsageStatsBackupHelper.java 0 → 100644 +70 −0 Original line number Diff line number Diff line package com.android.server.backup; import android.app.backup.BlobBackupHelper; import android.app.usage.IUsageStatsManager; import android.app.usage.UsageStatsManagerInternal; import android.content.Context; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.util.Log; import com.android.server.LocalServices; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; public class UsageStatsBackupHelper extends BlobBackupHelper { static final String TAG = "UsgStatsBackupHelper"; // must be < 23 chars static final boolean DEBUG = false; // Current version of the blob schema static final int BLOB_VERSION = 1; // Key under which the payload blob is stored // same as UsageStatsBackupHelperAssistant.KEY_USAGE_STATS static final String KEY_USAGE_STATS = "usage_stats"; public UsageStatsBackupHelper(Context context) { super(BLOB_VERSION, KEY_USAGE_STATS); } @Override protected byte[] getBackupPayload(String key) { if(KEY_USAGE_STATS.equals(key)) { UsageStatsManagerInternal localUsageStatsManager = LocalServices.getService(UsageStatsManagerInternal.class); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(baos); try{ out.writeInt(UserHandle.USER_SYSTEM); out.write(localUsageStatsManager.getBackupPayload(UserHandle.USER_SYSTEM, key)); } catch (IOException ioe){ if (DEBUG) Log.e(TAG, "Failed to backup Usage Stats", ioe); baos.reset(); } return baos.toByteArray(); } return null; } @Override protected void applyRestoredPayload(String key, byte[] payload) { if (KEY_USAGE_STATS.equals(key)) { UsageStatsManagerInternal localUsageStatsManager = LocalServices.getService(UsageStatsManagerInternal.class); DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload)); try{ int user = in.readInt(); byte[] restoreData = new byte[payload.length - 4]; in.read(restoreData, 0, payload.length-4); localUsageStatsManager.applyRestoredPayload(user, key, restoreData); } catch (IOException ioe){ if (DEBUG) Log.e(TAG, "Failed to restore Usage Stats", ioe); } } } }
services/usage/java/com/android/server/usage/UsageStatsDatabase.java +195 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.usage; import android.app.usage.TimeSparseArray; import android.app.usage.UsageStats; import android.app.usage.UsageStatsManager; import android.os.Build; import android.util.AtomicFile; Loading @@ -25,6 +26,10 @@ import android.util.TimeUtils; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileReader; import java.io.FileWriter; Loading @@ -39,6 +44,14 @@ import java.util.List; class UsageStatsDatabase { private static final int CURRENT_VERSION = 3; // Current version of the backup schema static final int BACKUP_STATE_VERSION = 1; // Key under which the payload blob is stored // same as UsageStatsBackupHelper.KEY_USAGE_STATS static final String KEY_USAGE_STATS = "usage_stats"; private static final String TAG = "UsageStatsDatabase"; private static final boolean DEBUG = UsageStatsService.DEBUG; private static final String BAK_SUFFIX = ".bak"; Loading Loading @@ -539,4 +552,186 @@ class UsageStatsDatabase { stats.lastTimeSaved = f.getLastModifiedTime(); } } /* Backup/Restore Code */ protected byte[] getBackupPayload(String key){ synchronized (mLock) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); if (KEY_USAGE_STATS.equals(key)) { prune(System.currentTimeMillis()); DataOutputStream out = new DataOutputStream(baos); try { out.writeInt(BACKUP_STATE_VERSION); out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY].size()); for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY].size(); i++){ writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY].valueAt(i)); } out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_WEEKLY].size()); for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_WEEKLY].size(); i++){ writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_WEEKLY].valueAt(i)); } out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_MONTHLY].size()); for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_MONTHLY].size(); i++){ writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_MONTHLY].valueAt(i)); } out.writeInt(mSortedStatFiles[UsageStatsManager.INTERVAL_YEARLY].size()); for(int i = 0; i<mSortedStatFiles[UsageStatsManager.INTERVAL_YEARLY].size(); i++){ writeIntervalStatsToStream(out, mSortedStatFiles[UsageStatsManager.INTERVAL_YEARLY].valueAt(i)); } if (DEBUG) Slog.i(TAG, "Written " + baos.size() + " bytes of data"); } catch (IOException ioe){ Slog.d(TAG, "Failed to write data to output stream", ioe); baos.reset(); } } return baos.toByteArray(); } } protected void applyRestoredPayload(String key, byte[] payload){ synchronized (mLock) { if (KEY_USAGE_STATS.equals(key)) { // Read stats files for the current device configs IntervalStats dailyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_DAILY); IntervalStats weeklyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_WEEKLY); IntervalStats monthlyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_MONTHLY); IntervalStats yearlyConfigSource = getLatestUsageStats(UsageStatsManager.INTERVAL_YEARLY); // Delete all stats files for(int i = 0; i<mIntervalDirs.length; i++){ deleteDirectoryContents(mIntervalDirs[i]); } try { DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload)); int stateVersion = in.readInt(); int fileCount = in.readInt(); for(int i = 0; i<fileCount; i++){ IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in)); stats = mergeStats(stats, dailyConfigSource); putUsageStats(UsageStatsManager.INTERVAL_DAILY, stats); } fileCount = in.readInt(); for(int i = 0; i<fileCount; i++){ IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in)); stats = mergeStats(stats, weeklyConfigSource); putUsageStats(UsageStatsManager.INTERVAL_WEEKLY, stats); } fileCount = in.readInt(); for(int i = 0; i<fileCount; i++){ IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in)); stats = mergeStats(stats, monthlyConfigSource); putUsageStats(UsageStatsManager.INTERVAL_MONTHLY, stats); } fileCount = in.readInt(); for(int i = 0; i<fileCount; i++){ IntervalStats stats = deserializeIntervalStats(getIntervalStatsBytes(in)); stats = mergeStats(stats, yearlyConfigSource); putUsageStats(UsageStatsManager.INTERVAL_YEARLY, stats); } if (DEBUG) Slog.i(TAG, "Completed Restoring UsageStats"); } catch (IOException ioe){ Slog.d(TAG, "Failed to read data from input stream", ioe); } finally { indexFilesLocked(); } } } } /** * Get the Configuration Statistics from the current device statistics and merge them * with the backed up usage statistics. */ private IntervalStats mergeStats(IntervalStats beingRestored, IntervalStats onDevice) { beingRestored.activeConfiguration = onDevice.activeConfiguration; beingRestored.configurations.putAll(onDevice.configurations); beingRestored.events = onDevice.events; return beingRestored; } private void writeIntervalStatsToStream(DataOutputStream out, AtomicFile statsFile) throws IOException{ IntervalStats stats = new IntervalStats(); try { UsageStatsXml.read(statsFile, stats); } catch (IOException e) { Slog.e(TAG, "Failed to read usage stats file", e); out.writeInt(0); return; } sanitizeIntervalStatsForBackup(stats); byte[] data = serializeIntervalStats(stats); out.writeInt(data.length); out.write(data); } private static byte[] getIntervalStatsBytes(DataInputStream in) throws IOException { int length = in.readInt(); byte[] buffer = new byte[length]; in.read(buffer, 0, length); return buffer; } private static void sanitizeIntervalStatsForBackup(IntervalStats stats) { if (stats == null) return; stats.activeConfiguration = null; stats.configurations.clear(); if (stats.events != null) stats.events.clear(); } private static byte[] serializeIntervalStats(IntervalStats stats) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(baos); try { out.writeLong(stats.beginTime); UsageStatsXml.write(out, stats); } catch (IOException ioe) { Slog.d(TAG, "Serializing IntervalStats Failed", ioe); baos.reset(); } return baos.toByteArray(); } private static IntervalStats deserializeIntervalStats(byte[] data) { ByteArrayInputStream bais = new ByteArrayInputStream(data); DataInputStream in = new DataInputStream(bais); IntervalStats stats = new IntervalStats(); try { stats.beginTime = in.readLong(); UsageStatsXml.read(in, stats); } catch (IOException ioe) { Slog.d(TAG, "DeSerializing IntervalStats Failed", ioe); stats = null; } return stats; } private static void deleteDirectoryContents(File directory){ File[] files = directory.listFiles(); for (File file : files) { deleteDirectory(file); } } private static void deleteDirectory(File directory) { File[] files = directory.listFiles(); for (File file : files) { if (!file.isDirectory()) { file.delete(); } else { deleteDirectory(file); } } directory.delete(); } }
services/usage/java/com/android/server/usage/UsageStatsService.java +23 −0 Original line number Diff line number Diff line Loading @@ -1310,6 +1310,8 @@ public class UsageStatsService extends SystemService implements } UsageStatsService.this.dump(args, pw); } } /** Loading Loading @@ -1416,5 +1418,26 @@ public class UsageStatsService extends SystemService implements AppIdleStateChangeListener listener) { UsageStatsService.this.removeListener(listener); } @Override public byte[] getBackupPayload(int user, String key) { // Check to ensure that only user 0's data is b/r for now if (user == UserHandle.USER_SYSTEM) { final UserUsageStatsService userStats = getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked()); return userStats.getBackupPayload(key); } else { return null; } } @Override public void applyRestoredPayload(int user, String key, byte[] payload) { if (user == UserHandle.USER_SYSTEM) { final UserUsageStatsService userStats = getUserDataAndInitializeIfNeededLocked(user, checkAndGetTimeLocked()); userStats.applyRestoredPayload(key, payload); } } } }