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