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