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