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

Commit 7b6831b2 authored by Chen Su's avatar Chen Su Committed by Steve McKay
Browse files

Preferences backup & restore.

Bug: 33234117
Test: Unit Tests (PrefsBackupHelperTest)
Change-Id: If5509e21d116f258875b43b6a6576715a92d4a67
(cherry picked from commit 24613680)
parent 40c85052
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -12,7 +12,14 @@
        android:name=".DocumentsApplication"
        android:label="@string/app_label"
        android:icon="@drawable/app_icon"
        android:supportsRtl="true">
        android:supportsRtl="true"
        android:allowBackup="true"
        android:backupAgent=".prefs.BackupAgent"
        android:fullBackupOnly="false">

        <meta-data
            android:name="com.google.android.backup.api_key"
            android:value="AEdPqrEAAAAInBA8ued0O_ZyYUsVhwinUF-x50NIe9K0GzBW4A" />

        <activity
            android:name=".picker.PickActivity"
+17 −0
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ import com.android.documentsui.base.State.ViewMode;
import com.android.documentsui.dirlist.AnimationView;
import com.android.documentsui.dirlist.DirectoryFragment;
import com.android.documentsui.prefs.LocalPreferences;
import com.android.documentsui.prefs.PreferencesMonitor;
import com.android.documentsui.queries.DebugCommandProcessor;
import com.android.documentsui.queries.SearchViewManager;
import com.android.documentsui.queries.SearchViewManager.SearchManagerListener;
@@ -97,6 +98,8 @@ public abstract class BaseActivity

    private long mStartTime;

    private PreferencesMonitor mPreferencesMonitor;

    public BaseActivity(@LayoutRes int layoutId, String tag) {
        mLayoutId = layoutId;
        mTag = tag;
@@ -178,6 +181,8 @@ public abstract class BaseActivity
        mSearchManager = new SearchViewManager(searchListener, dbgCommands, icicle);
        mSortController = SortController.create(this, mState.derivedMode, mState.sortModel);

        mPreferencesMonitor = new PreferencesMonitor(getApplicationContext());

        // Base classes must update result in their onCreate.
        setResult(Activity.RESULT_CANCELED);
    }
@@ -208,6 +213,18 @@ public abstract class BaseActivity
        return showMenu;
    }

    @Override
    protected void onResume() {
        super.onResume();
        mPreferencesMonitor.start();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mPreferencesMonitor.stop();
    }

    @Override
    @CallSuper
    public boolean onPrepareOptionsMenu(Menu menu) {
+94 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.documentsui.prefs;

import android.app.backup.BackupAgentHelper;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.SharedPreferencesBackupHelper;
import android.content.SharedPreferences;
import android.os.ParcelFileDescriptor;
import android.support.annotation.VisibleForTesting;

import java.io.IOException;

/**
 * Provides glue between backup infrastructure and PrefsBackupHelper (which contains the core logic
 * for retrieving and restoring settings).
 *
 * When doing backup & restore, we create and add a {@link SharedPreferencesBackupHelper} for our
 * backup preferences file in {@link #onCreate}, and populate the backup preferences file in
 * {@link #onBackup} and {@link #onRestore}. Then {@link BackupAgentHelper#onBackup} and
 * {@link BackupAgentHelper#onRestore} will take care of the rest of the work. See external
 * documentation below.
 *
 * https://developer.android.com/guide/topics/data/keyvaluebackup.html#BackupAgentHelper
 */
public class BackupAgent extends BackupAgentHelper {

    /**
     * Name of the shared preferences file used by BackupAgent. Should only be used in
     * this class.
     *
     * @see #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)
     * @see #onRestore(BackupDataInput, int, ParcelFileDescriptor)
     */
    private static final String BACKUP_PREFS = "documentsui_backup_prefs";

    /**
     * An arbitrary string used by the BackupHelper.
     *
     * BackupAgentHelper works with BackupHelper. When adding a BackupHelper in #onCreate,
     * it requires a "key". This string is that "key".
     *
     * https://developer.android.com/guide/topics/data/keyvaluebackup.html#BackupAgentHelper
     * See "Backing up SharedPreference" for the purpose of this string.
     *
     * @see #onCreate()
     */
    private static final String BACKUP_HELPER_KEY = "DOCUMENTSUI_BACKUP_HELPER_KEY";

    private PrefsBackupHelper mPrefsBackupHelper;
    private SharedPreferences mBackupPreferences;

    @Override
    public void onCreate() {
        addHelper(BACKUP_HELPER_KEY, new SharedPreferencesBackupHelper(this, BACKUP_PREFS));
        mPrefsBackupHelper = new PrefsBackupHelper(this);
        mBackupPreferences = getSharedPreferences(BACKUP_PREFS, MODE_PRIVATE);
    }

    @Override
    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
            ParcelFileDescriptor newState) throws IOException {
        mPrefsBackupHelper.getBackupPreferences(mBackupPreferences);
        super.onBackup(oldState, data, newState);
        mBackupPreferences.edit().clear().apply();
    }

    @Override
    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
            throws IOException {
        // TODO: refresh the UI after restore finished. Currently the restore for system apps only
        // happens during SUW, at which time user haven't open the app. However the restore time may
        // change in ODR. Once it happens, we may need to refresh the UI after restore finished.
        super.onRestore(data, appVersionCode, newState);
        mPrefsBackupHelper.putBackupPreferences(mBackupPreferences);
        mBackupPreferences.edit().clear().apply();
    }

}
+4 −0
Original line number Diff line number Diff line
@@ -123,4 +123,8 @@ public class LocalPreferences {
                ? userId + "|" + packageName + "||" + directory
                : userId + "|" + packageName + "|" + uuid + "|" + directory;
    }

    static boolean shouldBackup(String s) {
        return (s != null) ? s.startsWith(ROOT_VIEW_MODE_PREFIX) : false;
    }
}
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.documentsui.prefs;

import android.app.backup.BackupManager;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

/**
 * A class that monitors changes to the default shared preferences file. If a preference which
 * should be backed up changed, schedule a backup.
 */
public final class PreferencesMonitor
        implements SharedPreferences.OnSharedPreferenceChangeListener {

    private Context mContext;

    public PreferencesMonitor(Context context) {
        mContext = context;
    }

    public void start() {
        PreferenceManager.getDefaultSharedPreferences(mContext)
                .registerOnSharedPreferenceChangeListener(this);
    }

    public void stop() {
        PreferenceManager.getDefaultSharedPreferences(mContext)
                .unregisterOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (PrefsBackupHelper.shouldBackup(key)) {
            BackupManager.dataChanged(mContext.getPackageName());
        }
    }
}
Loading