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