BackupRestoreConfirmation.java revision dc92c82b4180e8067f1acd00a7db7935afce00ff
1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.backupconfirm; 18 19import android.app.Activity; 20import android.app.backup.FullBackup; 21import android.app.backup.IBackupManager; 22import android.app.backup.IFullBackupRestoreObserver; 23import android.content.Context; 24import android.content.Intent; 25import android.os.Bundle; 26import android.os.Handler; 27import android.os.Message; 28import android.os.RemoteException; 29import android.os.ServiceManager; 30import android.util.Slog; 31import android.view.View; 32import android.widget.Button; 33import android.widget.TextView; 34import android.widget.Toast; 35 36/** 37 * Confirm with the user that a requested full backup/restore operation is legitimate. 38 * Any attempt to perform a full backup/restore will launch this UI and wait for a 39 * designated timeout interval (nominally 30 seconds) for the user to confirm. If the 40 * user fails to respond within the timeout period, or explicitly refuses the operation 41 * within the UI presented here, no data will be transferred off the device. 42 * 43 * Note that the fully scoped name of this class is baked into the backup manager service. 44 * 45 * @hide 46 */ 47public class BackupRestoreConfirmation extends Activity { 48 static final String TAG = "BackupRestoreConfirmation"; 49 static final boolean DEBUG = true; 50 51 static final int MSG_START_BACKUP = 1; 52 static final int MSG_BACKUP_PACKAGE = 2; 53 static final int MSG_END_BACKUP = 3; 54 static final int MSG_START_RESTORE = 11; 55 static final int MSG_RESTORE_PACKAGE = 12; 56 static final int MSG_END_RESTORE = 13; 57 static final int MSG_TIMEOUT = 100; 58 59 Handler mHandler; 60 IBackupManager mBackupManager; 61 FullObserver mObserver; 62 int mToken; 63 64 TextView mStatusView; 65 Button mAllowButton; 66 Button mDenyButton; 67 68 // Handler for dealing with observer callbacks on the main thread 69 class ObserverHandler extends Handler { 70 Context mContext; 71 ObserverHandler(Context context) { 72 mContext = context; 73 } 74 75 @Override 76 public void handleMessage(Message msg) { 77 switch (msg.what) { 78 case MSG_START_BACKUP: { 79 Toast.makeText(mContext, "!!! Backup starting !!!", Toast.LENGTH_LONG).show(); 80 } 81 break; 82 83 case MSG_BACKUP_PACKAGE: { 84 String name = (String) msg.obj; 85 mStatusView.setText(name); 86 } 87 break; 88 89 case MSG_END_BACKUP: { 90 Toast.makeText(mContext, "!!! Backup ended !!!", Toast.LENGTH_SHORT).show(); 91 finish(); 92 } 93 break; 94 95 case MSG_START_RESTORE: { 96 Toast.makeText(mContext, "!!! Restore starting !!!", Toast.LENGTH_LONG).show(); 97 } 98 break; 99 100 case MSG_RESTORE_PACKAGE: { 101 } 102 break; 103 104 case MSG_END_RESTORE: { 105 Toast.makeText(mContext, "!!! Restore ended !!!", Toast.LENGTH_SHORT).show(); 106 finish(); 107 } 108 break; 109 110 case MSG_TIMEOUT: { 111 Toast.makeText(mContext, "!!! TIMED OUT !!!", Toast.LENGTH_LONG).show(); 112 } 113 break; 114 } 115 } 116 } 117 118 @Override 119 public void onCreate(Bundle icicle) { 120 super.onCreate(icicle); 121 122 final Intent intent = getIntent(); 123 final String action = intent.getAction(); 124 125 int layoutId; 126 if (action.equals(FullBackup.FULL_BACKUP_INTENT_ACTION)) { 127 layoutId = R.layout.confirm_backup; 128 } else if (action.equals(FullBackup.FULL_RESTORE_INTENT_ACTION)) { 129 layoutId = R.layout.confirm_restore; 130 } else { 131 Slog.w(TAG, "Backup/restore confirmation activity launched with invalid action!"); 132 finish(); 133 return; 134 } 135 136 mToken = intent.getIntExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, -1); 137 if (mToken < 0) { 138 Slog.e(TAG, "Backup/restore confirmation requested but no token passed!"); 139 finish(); 140 return; 141 } 142 143 mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE)); 144 145 mHandler = new ObserverHandler(getApplicationContext()); 146 mObserver = new FullObserver(); 147 148 setContentView(layoutId); 149 150 // Same resource IDs for each layout variant (backup / restore) 151 mStatusView = (TextView) findViewById(R.id.package_name); 152 mAllowButton = (Button) findViewById(R.id.button_allow); 153 mDenyButton = (Button) findViewById(R.id.button_deny); 154 155 mAllowButton.setOnClickListener(new View.OnClickListener() { 156 @Override 157 public void onClick(View v) { 158 try { 159 mBackupManager.acknowledgeFullBackupOrRestore(mToken, true, mObserver); 160 } catch (RemoteException e) { 161 // TODO: bail gracefully if we can't contact the backup manager 162 } 163 mAllowButton.setEnabled(false); 164 mDenyButton.setEnabled(false); 165 } 166 }); 167 168 mDenyButton.setOnClickListener(new View.OnClickListener() { 169 @Override 170 public void onClick(View v) { 171 try { 172 mBackupManager.acknowledgeFullBackupOrRestore(mToken, false, mObserver); 173 } catch (RemoteException e) { 174 // TODO: bail gracefully if we can't contact the backup manager 175 } 176 mAllowButton.setEnabled(false); 177 mDenyButton.setEnabled(false); 178 } 179 }); 180 } 181 182 @Override 183 public void onStop() { 184 super.onStop(); 185 186 // We explicitly equate departure from the UI with refusal. This includes the 187 // implicit configuration-changed stop/restart cycle. 188 try { 189 mBackupManager.acknowledgeFullBackupOrRestore(mToken, false, null); 190 } catch (RemoteException e) { 191 // if this fails we'll still time out with no acknowledgment 192 } 193 finish(); 194 } 195 196 /** 197 * The observer binder for showing backup/restore progress. This binder just bounces 198 * the notifications onto the main thread. 199 */ 200 class FullObserver extends IFullBackupRestoreObserver.Stub { 201 // 202 // IFullBackupRestoreObserver implementation 203 // 204 @Override 205 public void onStartBackup() throws RemoteException { 206 mHandler.sendEmptyMessage(MSG_START_BACKUP); 207 } 208 209 @Override 210 public void onBackupPackage(String name) throws RemoteException { 211 mHandler.sendMessage(mHandler.obtainMessage(MSG_BACKUP_PACKAGE, name)); 212 } 213 214 @Override 215 public void onEndBackup() throws RemoteException { 216 mHandler.sendEmptyMessage(MSG_END_BACKUP); 217 } 218 219 @Override 220 public void onStartRestore() throws RemoteException { 221 mHandler.sendEmptyMessage(MSG_START_RESTORE); 222 } 223 224 @Override 225 public void onRestorePackage(String name) throws RemoteException { 226 mHandler.sendMessage(mHandler.obtainMessage(MSG_RESTORE_PACKAGE, name)); 227 } 228 229 @Override 230 public void onEndRestore() throws RemoteException { 231 mHandler.sendEmptyMessage(MSG_END_RESTORE); 232 } 233 234 @Override 235 public void onTimeout() throws RemoteException { 236 mHandler.sendEmptyMessage(MSG_TIMEOUT); 237 } 238 } 239} 240