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

Commit 5b53875f authored by Artem Iglikov's avatar Artem Iglikov
Browse files

Clear app data before full restore for specified packages

In some cases (deferred restore) the app data needs to be cleared even
if the app has implemented backup agent. As a quick fix introduce
PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE secure setting, which
transport can fill prior to restore.

Bug: 69069240
Test: adb shell settings put secure packages_to_clear_data_before_full_restore com.google.android.apps.nexuslauncher && adb shell bmgr restore com.google.android.apps.nexuslauncher
Change-Id: I2a4651365d9cf4747f32d2ba69312f54cd03d118
parent 3a5dabbb
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -7808,6 +7808,14 @@ public final class Settings {
        public static final String SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION =
                "suppress_auto_battery_saver_suggestion";

        /**
         * List of packages, which data need to be unconditionally cleared before full restore.
         * Type: string
         * @hide
         */
        public static final String PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE =
                "packages_to_clear_data_before_full_restore";

        /**
         * This are the settings to be backed up.
         *
+1 −0
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ message SecureSettingsProto {
        optional SettingProto transport = 4 [ (android.privacy).dest = DEST_AUTOMATIC ];
        optional SettingProto manager_constants = 5;
        optional SettingProto local_transport_parameters = 6;
        optional SettingProto packages_to_clear_data_before_full_restore = 7;
    }
    optional Backup backup = 10;

+2 −1
Original line number Diff line number Diff line
@@ -587,7 +587,8 @@ public class SettingsBackupTest {
                 Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING,
                 Settings.Secure.LOW_POWER_MANUAL_ACTIVATION_COUNT,
                 Settings.Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
                 Settings.Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION);
                 Settings.Secure.SUPPRESS_AUTO_BATTERY_SAVER_SUGGESTION,
                 Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE);

    @Test
    public void systemSettingsBackedUpOrBlacklisted() {
+3 −0
Original line number Diff line number Diff line
@@ -1724,6 +1724,9 @@ class SettingsProtoDumpUtil {
        dumpSetting(s, p,
                Settings.Secure.BACKUP_LOCAL_TRANSPORT_PARAMETERS,
                SecureSettingsProto.Backup.LOCAL_TRANSPORT_PARAMETERS);
        dumpSetting(s, p,
                Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE,
                SecureSettingsProto.Backup.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE);
        p.end(backupToken);

        // Settings.Secure.BLUETOOTH_ON intentionally excluded since it's deprecated.
+33 −5
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.Signature;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;

import com.android.server.LocalServices;
@@ -56,8 +58,11 @@ import com.android.server.backup.utils.TarBackupReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

/**
 * Full restore engine, used by both adb restore and transport-based full restore.
@@ -322,10 +327,15 @@ public class FullRestoreEngine extends RestoreEngine {
                            // If we haven't sent any data to this app yet, we probably
                            // need to clear it first. Check that.
                            if (!mClearedPackages.contains(pkg)) {
                                // apps with their own backup agents are
                                // responsible for coherently managing a full
                                // restore.
                                if (mTargetApp.backupAgentName == null) {
                                // Apps with their own backup agents are responsible for coherently
                                // managing a full restore.
                                // In some rare cases they can't, especially in case of deferred
                                // restore. In this case check whether this app should be forced to
                                // clear up.
                                // TODO: Fix this properly with manifest parameter.
                                boolean forceClear = shouldForceClearAppDataOnFullRestore(
                                        mTargetApp.packageName);
                                if (mTargetApp.backupAgentName == null || forceClear) {
                                    if (DEBUG) {
                                        Slog.d(TAG,
                                                "Clearing app data preparatory to full restore");
@@ -623,6 +633,24 @@ public class FullRestoreEngine extends RestoreEngine {
        return true;
    }

    /**
     * Returns whether the package is in the list of the packages for which clear app data should
     * be called despite the fact that they have backup agent.
     *
     * <p>The list is read from {@link Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE}.
     */
    private boolean shouldForceClearAppDataOnFullRestore(String packageName) {
        String packageListString = Settings.Secure.getString(
                mBackupManagerService.getContext().getContentResolver(),
                Settings.Secure.PACKAGES_TO_CLEAR_DATA_BEFORE_FULL_RESTORE);
        if (TextUtils.isEmpty(packageListString)) {
            return false;
        }

        List<String> packages = Arrays.asList(packageListString.split(";"));
        return packages.contains(packageName);
    }

    void sendOnRestorePackage(String name) {
        if (mObserver != null) {
            try {