platform-packages-apps-Settings / src / com / android / settings / backup / ToggleBackupSettingFragment.java
ToggleBackupSettingFragment.java
Raw
package com.android.settings.backup;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.backup.IBackupManager;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.PreferenceViewHolder;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.ToggleSwitch;

/**
 * Fragment to display a bunch of text about backup and restore, and allow the user to enable/
 * disable it.
 */
public class ToggleBackupSettingFragment extends SettingsPreferenceFragment
        implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
    private static final String TAG = "ToggleBackupSettingFragment";

    private static final String BACKUP_TOGGLE = "toggle_backup";

    // System setting that governs whether the user is eligible for full app-data backup,
    // based on whether they have been presented with the details of what that backup entails
    // (usually surfaced somewhere like device setup)
    private static final String USER_FULL_DATA_BACKUP_AWARE = "user_full_data_backup_aware";

    private IBackupManager mBackupManager;

    protected SwitchBar mSwitchBar;
    protected ToggleSwitch mToggleSwitch;

    private Preference mSummaryPreference;

    private Dialog mConfirmDialog;

    private boolean mWaitingForConfirmationDialog = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mBackupManager = IBackupManager.Stub.asInterface(
                ServiceManager.getService(Context.BACKUP_SERVICE));

        PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
                getActivity());
        setPreferenceScreen(preferenceScreen);
        mSummaryPreference = new Preference(getPrefContext()) {
            @Override
            public void onBindViewHolder(PreferenceViewHolder view) {
                super.onBindViewHolder(view);
                final TextView summaryView = (TextView) view.findViewById(android.R.id.summary);
                summaryView.setText(getSummary());
            }
        };
        mSummaryPreference.setPersistent(false);
        mSummaryPreference.setLayoutResource(R.layout.text_description_preference);
        preferenceScreen.addPreference(mSummaryPreference);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        SettingsActivity activity = (SettingsActivity) getActivity();
        mSwitchBar = activity.getSwitchBar();
        mToggleSwitch = mSwitchBar.getSwitch();

        // Set up UI.
        // If the user has not seen legal text for full data backup (if they OTA from L to M) then
        // full data backup will be off and here we want to show the old summary here that does
        // not mention full data backup
        if (Settings.Secure.getInt(getContentResolver(), USER_FULL_DATA_BACKUP_AWARE, 0) != 0) {
            mSummaryPreference.setSummary(R.string.fullbackup_data_summary);
        } else {
            mSummaryPreference.setSummary(R.string.backup_data_summary);
        }
        try {
            boolean backupEnabled = mBackupManager == null ?
                    false : mBackupManager.isBackupEnabled();
            mSwitchBar.setCheckedInternal(backupEnabled);
        } catch (RemoteException e) {
            // The world is aflame, turn it off.
            mSwitchBar.setEnabled(false);
        }
        getActivity().setTitle(R.string.backup_data_title);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();

        mToggleSwitch.setOnBeforeCheckedChangeListener(null);
        mSwitchBar.hide();
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // Set up toggle listener. We need this b/c we have to intercept the toggle event in order
        // to pop up the dialogue.
        mToggleSwitch.setOnBeforeCheckedChangeListener(
                new ToggleSwitch.OnBeforeCheckedChangeListener() {
                    @Override
                    public boolean onBeforeCheckedChanged(
                            ToggleSwitch toggleSwitch, boolean checked) {
                        if (!checked) {
                            // Don't change Switch status until user makes choice in dialog
                            // so return true here.
                            showEraseBackupDialog();
                            return true;
                        } else {
                            setBackupEnabled(true);
                            mSwitchBar.setCheckedInternal(true);
                            return true;
                        }
                    }
                });
        mSwitchBar.show();
    }

    /** Get rid of the dialog if it's still showing. */
    @Override
    public void onStop() {
        if (mConfirmDialog != null && mConfirmDialog.isShowing()) {
            mConfirmDialog.dismiss();
        }
        mConfirmDialog = null;
        super.onStop();
    }

    @Override
    public void onClick(DialogInterface dialog, int which) {
        // Accept turning off backup
        if (which == DialogInterface.BUTTON_POSITIVE) {
            mWaitingForConfirmationDialog = false;
            setBackupEnabled(false);
            mSwitchBar.setCheckedInternal(false);
        } else if (which == DialogInterface.BUTTON_NEGATIVE) {
            // Reject turning off backup
            mWaitingForConfirmationDialog = false;
            setBackupEnabled(true);
            mSwitchBar.setCheckedInternal(true);
        }
    }

    @Override
    public void onDismiss(DialogInterface dialog) {
        if (mWaitingForConfirmationDialog) {
            // dismiss turning off backup
            setBackupEnabled(true);
            mSwitchBar.setCheckedInternal(true);
        }
    }

    private void showEraseBackupDialog() {
        CharSequence msg;

        // If the user has not seen legal text for full data backup (if they OTA from L to M) then
        // full data backup will be off and here we want to show the old erase_dialog_message here
        // that does not mention full data backup
        if (Settings.Secure.getInt(getContentResolver(), USER_FULL_DATA_BACKUP_AWARE, 0) != 0) {
            msg = getResources().getText(R.string.fullbackup_erase_dialog_message);
        } else {
            msg = getResources().getText(R.string.backup_erase_dialog_message);
        }

        mWaitingForConfirmationDialog = true;

        // TODO: DialogFragment?
        mConfirmDialog = new AlertDialog.Builder(getActivity()).setMessage(msg)
                .setTitle(R.string.backup_erase_dialog_title)
                .setPositiveButton(android.R.string.ok, this)
                .setNegativeButton(android.R.string.cancel, this)
                .setOnDismissListener(this)
                .show();
    }

    @Override
    public int getMetricsCategory() {
        return MetricsEvent.PRIVACY;
    }

    /**
     * Informs the BackupManager of a change in backup state - if backup is disabled,
     * the data on the server will be erased.
     * @param enable whether to enable backup
     */
    private void setBackupEnabled(boolean enable) {
        if (mBackupManager != null) {
            try {
                mBackupManager.setBackupEnabled(enable);
            } catch (RemoteException e) {
                Log.e(TAG, "Error communicating with BackupManager", e);
                return;
            }
        }
    }
}