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

Commit 9e111f19 authored by Ruslan Tkhakokhov's avatar Ruslan Tkhakokhov
Browse files

Add BackupManager#excludeKeysFromRestore()

Add the method as a hidden API for now. Move to System API later.

Bug: 145126096
Test: 1. Call BM#excludeKeyFromRestore for a test package
      2. Reboot the device
      3. Run restore for the test package
      4. Verify excluded keys are not restored

Change-Id: Ice57299eaf54cee8428b86e2d4f78de12b8db4fc
parent 2ddae3ed
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import android.os.UserHandle;
import android.util.Log;
import android.util.Pair;

import java.util.List;

/**
 * The interface through which an application interacts with the Android backup service to
 * request backup and restore operations.
@@ -948,6 +950,27 @@ public class BackupManager {
        return null;
    }

    /**
     * Excludes keys from KV restore for a given package. The corresponding data will be excluded
     * from the data set available the backup agent during restore. However,  final list  of keys
     * that have been excluded will be passed to the agent to make it aware of the exclusions.
     *
     * @param packageName The name of the package for which to exclude keys.
     * @param keys The list of keys to exclude.
     *
     * @hide
     */
    public void excludeKeysFromRestore(String packageName, List<String> keys) {
        checkServiceBinder();
        if (sService != null) {
            try {
                sService.excludeKeysFromRestore(packageName, keys);
            } catch (RemoteException e) {
                Log.e(TAG, "excludeKeysFromRestore() couldn't connect");
            }
        }
    }

    /*
     * We wrap incoming binder calls with a private class implementation that
     * redirects them into main-thread actions.  This serializes the backup
+6 −0
Original line number Diff line number Diff line
@@ -710,4 +710,10 @@ interface IBackupManager {
     */
    void setAncestralSerialNumber(in long ancestralSerialNumber);

    /**
     * Excludes keys from KV restore for a given package. The corresponding data will be excluded
     * from the data set available the backup agent during restore. However,  final list  of keys
     * that have been excluded will be passed to the agent to make it aware of the exclusions.
     */
    void excludeKeysFromRestore(String packageName, in List<String> keys);
}
+21 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Set;

/**
@@ -1509,6 +1510,26 @@ public class BackupManagerService extends IBackupManager.Stub {
        }
    }

    /**
     * Excludes keys from KV restore for a given package. The corresponding data will be excluded
     * from the data set available the backup agent during restore. However,  final list  of keys
     * that have been excluded will be passed to the agent to make it aware of the exclusions.
     */
    public void excludeKeysFromRestore(String packageName, List<String> keys) {
        int userId = Binder.getCallingUserHandle().getIdentifier();
        if (!isUserReadyForBackup(userId)) {
            Slog.w(TAG, "Returning from excludeKeysFromRestore as backup for user" + userId +
                    " is not initialized yet");
            return;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "excludeKeysFromRestore()");

        if (userBackupManagerService != null) {
            userBackupManagerService.excludeKeysFromRestore(packageName, keys);
        }
    }

    /**
     * Returns the {@link UserBackupManagerService} instance for the specified user {@code userId}.
     * If the user is not registered with the service (either the user is locked or not eligible for
+23 −1
Original line number Diff line number Diff line
@@ -158,6 +158,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Random;
import java.util.Set;
@@ -332,6 +333,8 @@ public class UserBackupManagerService {
    // locking around the pending-backup management
    private final Object mQueueLock = new Object();

    private final UserBackupPreferences mBackupPreferences;

    // The thread performing the sequence of queued backups binds to each app's agent
    // in succession.  Bind notifications are asynchronously delivered through the
    // Activity Manager; use this lock object to signal when a requested binding has
@@ -632,6 +635,8 @@ public class UserBackupManagerService {
        // the pending backup set
        mBackupHandler.postDelayed(this::parseLeftoverJournals, INITIALIZATION_DELAY_MILLIS);

        mBackupPreferences = new UserBackupPreferences(mContext, mBaseStateDir);

        // Power management
        mWakelock = new BackupWakeLock(
                mPowerManager.newWakeLock(
@@ -1097,6 +1102,14 @@ public class UserBackupManagerService {
        }
    }

    public Map<String, Set<String>> getExcludedRestoreKeys(String... packages) {
        return mBackupPreferences.getExcludedRestoreKeysForPackages(packages);
    }

    public Map<String, Set<String>> getAllExcludedRestoreKeys() {
        return mBackupPreferences.getAllExcludedRestoreKeys();
    }

    /** Used for generating random salts or passwords. */
    public byte[] randomBytes(int bits) {
        byte[] array = new byte[bits / 8];
@@ -2746,6 +2759,14 @@ public class UserBackupManagerService {
        }
    }

    /**
     * Excludes keys from KV restore for a given package. The keys won't be part of the data passed
     * to the backup agent during restore.
     */
    public void excludeKeysFromRestore(String packageName, List<String> keys) {
        mBackupPreferences.addExcludedKeys(packageName, keys);
    }

    private boolean startConfirmationUi(int token, String action) {
        try {
            Intent confIntent = new Intent(action);
@@ -3341,7 +3362,8 @@ public class UserBackupManagerService {
                                restoreSet,
                                packageName,
                                token,
                                listener);
                                listener,
                                getExcludedRestoreKeys(packageName));
                mBackupHandler.sendMessage(msg);
            } catch (Exception e) {
                // Calling into the transport broke; back off and proceed with the installation.
+63 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.backup;

import android.content.Context;
import android.content.SharedPreferences;

import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/** Manages the persisted backup preferences per user. */
public class UserBackupPreferences {
    private static final String PREFERENCES_FILE = "backup_preferences";

    private final SharedPreferences mPreferences;
    private final SharedPreferences.Editor mEditor;

    UserBackupPreferences(Context conext, File storageDir) {
        File excludedKeysFile = new File(storageDir, PREFERENCES_FILE);
        mPreferences = conext.getSharedPreferences(excludedKeysFile, Context.MODE_PRIVATE);
        mEditor = mPreferences.edit();
    }

    void addExcludedKeys(String packageName, List<String> keys) {
        Set<String> existingKeys =
                new HashSet<>(mPreferences.getStringSet(packageName, Collections.emptySet()));
        existingKeys.addAll(keys);
        mEditor.putStringSet(packageName, existingKeys);
        mEditor.commit();
    }

    Map<String, Set<String>> getExcludedRestoreKeysForPackages(String... packages) {
        Map<String, Set<String>> excludedKeys = new HashMap<>();
        for (String packageName : packages) {
            excludedKeys.put(packageName,
                    mPreferences.getStringSet(packageName, Collections.emptySet()));
        }
        return excludedKeys;
    }

    Map<String, Set<String>> getAllExcludedRestoreKeys() {
        return (Map<String, Set<String>>) mPreferences.getAll();
    }
}
Loading