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