1package com.android.settings.backup;
2
3import android.app.AlertDialog;
4import android.app.Dialog;
5import android.app.backup.IBackupManager;
6import android.content.Context;
7import android.content.DialogInterface;
8import android.os.Bundle;
9import android.os.RemoteException;
10import android.os.ServiceManager;
11import android.provider.Settings;
12import android.support.v7.preference.Preference;
13import android.support.v7.preference.PreferenceScreen;
14import android.support.v7.preference.PreferenceViewHolder;
15import android.util.Log;
16import android.view.View;
17import android.widget.TextView;
18
19import com.android.internal.logging.MetricsProto.MetricsEvent;
20import com.android.settings.R;
21import com.android.settings.SettingsActivity;
22import com.android.settings.SettingsPreferenceFragment;
23import com.android.settings.widget.SwitchBar;
24import com.android.settings.widget.ToggleSwitch;
25
26/**
27 * Fragment to display a bunch of text about backup and restore, and allow the user to enable/
28 * disable it.
29 */
30public class ToggleBackupSettingFragment extends SettingsPreferenceFragment
31        implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
32    private static final String TAG = "ToggleBackupSettingFragment";
33
34    private static final String BACKUP_TOGGLE = "toggle_backup";
35
36    // System setting that governs whether the user is eligible for full app-data backup,
37    // based on whether they have been presented with the details of what that backup entails
38    // (usually surfaced somewhere like device setup)
39    private static final String USER_FULL_DATA_BACKUP_AWARE = "user_full_data_backup_aware";
40
41    private IBackupManager mBackupManager;
42
43    protected SwitchBar mSwitchBar;
44    protected ToggleSwitch mToggleSwitch;
45
46    private Preference mSummaryPreference;
47
48    private Dialog mConfirmDialog;
49
50    private boolean mWaitingForConfirmationDialog = false;
51
52    @Override
53    public void onCreate(Bundle savedInstanceState) {
54        super.onCreate(savedInstanceState);
55
56        mBackupManager = IBackupManager.Stub.asInterface(
57                ServiceManager.getService(Context.BACKUP_SERVICE));
58
59        PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
60                getActivity());
61        setPreferenceScreen(preferenceScreen);
62        mSummaryPreference = new Preference(getPrefContext()) {
63            @Override
64            public void onBindViewHolder(PreferenceViewHolder view) {
65                super.onBindViewHolder(view);
66                final TextView summaryView = (TextView) view.findViewById(android.R.id.summary);
67                summaryView.setText(getSummary());
68            }
69        };
70        mSummaryPreference.setPersistent(false);
71        mSummaryPreference.setLayoutResource(R.layout.text_description_preference);
72        preferenceScreen.addPreference(mSummaryPreference);
73    }
74
75    @Override
76    public void onViewCreated(View view, Bundle savedInstanceState) {
77        super.onViewCreated(view, savedInstanceState);
78
79        SettingsActivity activity = (SettingsActivity) getActivity();
80        mSwitchBar = activity.getSwitchBar();
81        mToggleSwitch = mSwitchBar.getSwitch();
82
83        // Set up UI.
84        // If the user has not seen legal text for full data backup (if they OTA from L to M) then
85        // full data backup will be off and here we want to show the old summary here that does
86        // not mention full data backup
87        if (Settings.Secure.getInt(getContentResolver(), USER_FULL_DATA_BACKUP_AWARE, 0) != 0) {
88            mSummaryPreference.setSummary(R.string.fullbackup_data_summary);
89        } else {
90            mSummaryPreference.setSummary(R.string.backup_data_summary);
91        }
92        try {
93            boolean backupEnabled = mBackupManager == null ?
94                    false : mBackupManager.isBackupEnabled();
95            mSwitchBar.setCheckedInternal(backupEnabled);
96        } catch (RemoteException e) {
97            // The world is aflame, turn it off.
98            mSwitchBar.setEnabled(false);
99        }
100        getActivity().setTitle(R.string.backup_data_title);
101    }
102
103    @Override
104    public void onDestroyView() {
105        super.onDestroyView();
106
107        mToggleSwitch.setOnBeforeCheckedChangeListener(null);
108        mSwitchBar.hide();
109    }
110
111    @Override
112    public void onActivityCreated(Bundle savedInstanceState) {
113        super.onActivityCreated(savedInstanceState);
114
115        // Set up toggle listener. We need this b/c we have to intercept the toggle event in order
116        // to pop up the dialogue.
117        mToggleSwitch.setOnBeforeCheckedChangeListener(
118                new ToggleSwitch.OnBeforeCheckedChangeListener() {
119                    @Override
120                    public boolean onBeforeCheckedChanged(
121                            ToggleSwitch toggleSwitch, boolean checked) {
122                        if (!checked) {
123                            // Don't change Switch status until user makes choice in dialog
124                            // so return true here.
125                            showEraseBackupDialog();
126                            return true;
127                        } else {
128                            setBackupEnabled(true);
129                            mSwitchBar.setCheckedInternal(true);
130                            return true;
131                        }
132                    }
133                });
134        mSwitchBar.show();
135    }
136
137    /** Get rid of the dialog if it's still showing. */
138    @Override
139    public void onStop() {
140        if (mConfirmDialog != null && mConfirmDialog.isShowing()) {
141            mConfirmDialog.dismiss();
142        }
143        mConfirmDialog = null;
144        super.onStop();
145    }
146
147    @Override
148    public void onClick(DialogInterface dialog, int which) {
149        // Accept turning off backup
150        if (which == DialogInterface.BUTTON_POSITIVE) {
151            mWaitingForConfirmationDialog = false;
152            setBackupEnabled(false);
153            mSwitchBar.setCheckedInternal(false);
154        } else if (which == DialogInterface.BUTTON_NEGATIVE) {
155            // Reject turning off backup
156            mWaitingForConfirmationDialog = false;
157            setBackupEnabled(true);
158            mSwitchBar.setCheckedInternal(true);
159        }
160    }
161
162    @Override
163    public void onDismiss(DialogInterface dialog) {
164        if (mWaitingForConfirmationDialog) {
165            // dismiss turning off backup
166            setBackupEnabled(true);
167            mSwitchBar.setCheckedInternal(true);
168        }
169    }
170
171    private void showEraseBackupDialog() {
172        CharSequence msg;
173
174        // If the user has not seen legal text for full data backup (if they OTA from L to M) then
175        // full data backup will be off and here we want to show the old erase_dialog_message here
176        // that does not mention full data backup
177        if (Settings.Secure.getInt(getContentResolver(), USER_FULL_DATA_BACKUP_AWARE, 0) != 0) {
178            msg = getResources().getText(R.string.fullbackup_erase_dialog_message);
179        } else {
180            msg = getResources().getText(R.string.backup_erase_dialog_message);
181        }
182
183        mWaitingForConfirmationDialog = true;
184
185        // TODO: DialogFragment?
186        mConfirmDialog = new AlertDialog.Builder(getActivity()).setMessage(msg)
187                .setTitle(R.string.backup_erase_dialog_title)
188                .setPositiveButton(android.R.string.ok, this)
189                .setNegativeButton(android.R.string.cancel, this)
190                .setOnDismissListener(this)
191                .show();
192    }
193
194    @Override
195    protected int getMetricsCategory() {
196        return MetricsEvent.PRIVACY;
197    }
198
199    /**
200     * Informs the BackupManager of a change in backup state - if backup is disabled,
201     * the data on the server will be erased.
202     * @param enable whether to enable backup
203     */
204    private void setBackupEnabled(boolean enable) {
205        if (mBackupManager != null) {
206            try {
207                mBackupManager.setBackupEnabled(enable);
208            } catch (RemoteException e) {
209                Log.e(TAG, "Error communicating with BackupManager", e);
210                return;
211            }
212        }
213    }
214}
215