Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e35ae5cc authored by Ritesh Reddy's avatar Ritesh Reddy
Browse files

UsageStatsBackup Bug Fix

Fixed a bug which caused a null pointer exception on restore
in deleteDirectoryContents() method.
Also made other cosmetic changes.

Change-Id: I75712ec585fdfdbca462c468acf2229a47331b59
parent ee081d5b
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -2,11 +2,8 @@ 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;

@@ -26,7 +23,7 @@ public class UsageStatsBackupHelper extends BlobBackupHelper {
    static final int BLOB_VERSION = 1;

    // Key under which the payload blob is stored
    // same as UsageStatsBackupHelperAssistant.KEY_USAGE_STATS
    // same as UsageStatsDatabase.KEY_USAGE_STATS
    static final String KEY_USAGE_STATS = "usage_stats";

    public UsageStatsBackupHelper(Context context) {
@@ -36,7 +33,8 @@ public class UsageStatsBackupHelper extends BlobBackupHelper {
    @Override
    protected byte[] getBackupPayload(String key) {
        if (KEY_USAGE_STATS.equals(key)) {
            UsageStatsManagerInternal localUsageStatsManager = LocalServices.getService(UsageStatsManagerInternal.class);
            UsageStatsManagerInternal localUsageStatsManager =
                    LocalServices.getService(UsageStatsManagerInternal.class);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            DataOutputStream out  = new DataOutputStream(baos);
            try {
@@ -55,12 +53,13 @@ public class UsageStatsBackupHelper extends BlobBackupHelper {
    @Override
    protected void applyRestoredPayload(String key, byte[] payload)  {
        if (KEY_USAGE_STATS.equals(key)) {
            UsageStatsManagerInternal localUsageStatsManager = LocalServices.getService(UsageStatsManagerInternal.class);
            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);
                in.read(restoreData, 0, restoreData.length);
                localUsageStatsManager.applyRestoredPayload(user, key, restoreData);
            } catch (IOException ioe) {
                if (DEBUG) Log.e(TAG, "Failed to restore Usage Stats", ioe);
+60 −39
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
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;
@@ -45,7 +44,7 @@ class UsageStatsDatabase {
    private static final int CURRENT_VERSION = 3;

    // Current version of the backup schema
    static final int BACKUP_STATE_VERSION = 1;
    static final int BACKUP_VERSION = 1;

    // Key under which the payload blob is stored
    // same as UsageStatsBackupHelper.KEY_USAGE_STATS
@@ -536,6 +535,7 @@ class UsageStatsDatabase {
     * Update the stats in the database. They may not be written to disk immediately.
     */
    public void putUsageStats(int intervalType, IntervalStats stats) throws IOException {
        if (stats == null) return;
        synchronized (mLock) {
            if (intervalType < 0 || intervalType >= mIntervalDirs.length) {
                throw new IllegalArgumentException("Bad interval type " + intervalType);
@@ -555,33 +555,41 @@ class UsageStatsDatabase {


    /* Backup/Restore Code */
    protected byte[] getBackupPayload(String key){
    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(BACKUP_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));
                    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));
                    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));
                    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));
                    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) {
@@ -594,22 +602,31 @@ class UsageStatsDatabase {

    }

    protected void applyRestoredPayload(String key, byte[] payload){
    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);
                IntervalStats dailyConfigSource =
                        getLatestUsageStats(UsageStatsManager.INTERVAL_DAILY);
                IntervalStats weeklyConfigSource =
                        getLatestUsageStats(UsageStatsManager.INTERVAL_WEEKLY);
                IntervalStats monthlyConfigSource =
                        getLatestUsageStats(UsageStatsManager.INTERVAL_MONTHLY);
                IntervalStats yearlyConfigSource =
                        getLatestUsageStats(UsageStatsManager.INTERVAL_YEARLY);

                try {
                    DataInputStream in = new DataInputStream(new ByteArrayInputStream(payload));
                    int backupDataVersion = in.readInt();

                    // Can't handle this backup set
                    if (backupDataVersion < 1 || backupDataVersion > BACKUP_VERSION) return;

                    // Delete all stats files
                    // Do this after reading version and before actually restoring
                    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++) {
@@ -641,8 +658,7 @@ class UsageStatsDatabase {
                    if (DEBUG) Slog.i(TAG, "Completed Restoring UsageStats");
                } catch (IOException ioe) {
                    Slog.d(TAG, "Failed to read data from input stream", ioe);
                }
                finally {
                } finally {
                    indexFilesLocked();
                }
            }
@@ -654,13 +670,16 @@ class UsageStatsDatabase {
     * with the backed up usage statistics.
     */
    private IntervalStats mergeStats(IntervalStats beingRestored, IntervalStats onDevice) {
        if (onDevice == null) return beingRestored;
        if (beingRestored == null) return null;
        beingRestored.activeConfiguration = onDevice.activeConfiguration;
        beingRestored.configurations.putAll(onDevice.configurations);
        beingRestored.events = onDevice.events;
        return beingRestored;
    }

    private void writeIntervalStatsToStream(DataOutputStream out, AtomicFile statsFile) throws IOException{
    private void writeIntervalStatsToStream(DataOutputStream out, AtomicFile statsFile)
            throws IOException {
        IntervalStats stats = new IntervalStats();
        try {
            UsageStatsXml.read(statsFile, stats);
@@ -725,6 +744,7 @@ class UsageStatsDatabase {

    private static void deleteDirectory(File directory) {
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (!file.isDirectory()) {
                    file.delete();
@@ -732,6 +752,7 @@ class UsageStatsDatabase {
                    deleteDirectory(file);
                }
            }
        }
        directory.delete();
    }
}
 No newline at end of file