14a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate/*
24a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * Copyright (C) 2011 The Android Open Source Project
34a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate *
44a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * Licensed under the Apache License, Version 2.0 (the "License");
54a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * you may not use this file except in compliance with the License.
64a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * You may obtain a copy of the License at
74a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate *
84a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate *      http://www.apache.org/licenses/LICENSE-2.0
94a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate *
104a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * Unless required by applicable law or agreed to in writing, software
114a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * distributed under the License is distributed on an "AS IS" BASIS,
124a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * See the License for the specific language governing permissions and
144a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * limitations under the License.
154a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate */
164a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
174a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tatepackage com.android.backupconfirm;
184a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
194a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.app.Activity;
204a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.app.backup.FullBackup;
214a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.app.backup.IBackupManager;
224a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.app.backup.IFullBackupRestoreObserver;
234a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.content.Context;
244a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.content.Intent;
254a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.os.Bundle;
264a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.os.Handler;
274a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.os.Message;
284a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.os.RemoteException;
294a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.os.ServiceManager;
3032418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tateimport android.os.storage.IMountService;
3132418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tateimport android.util.Log;
324a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.util.Slog;
334a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.view.View;
344a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.widget.Button;
354a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.widget.TextView;
364a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tateimport android.widget.Toast;
374a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
384a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate/**
394a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * Confirm with the user that a requested full backup/restore operation is legitimate.
404a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * Any attempt to perform a full backup/restore will launch this UI and wait for a
414a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * designated timeout interval (nominally 30 seconds) for the user to confirm.  If the
424a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * user fails to respond within the timeout period, or explicitly refuses the operation
434a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * within the UI presented here, no data will be transferred off the device.
444a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate *
454a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * Note that the fully scoped name of this class is baked into the backup manager service.
464a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate *
474a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate * @hide
484a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate */
494a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tatepublic class BackupRestoreConfirmation extends Activity {
504a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    static final String TAG = "BackupRestoreConfirmation";
514a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    static final boolean DEBUG = true;
524a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
533851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate    static final String DID_ACKNOWLEDGE = "did_acknowledge";
543851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate
554a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    static final int MSG_START_BACKUP = 1;
564a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    static final int MSG_BACKUP_PACKAGE = 2;
574a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    static final int MSG_END_BACKUP = 3;
584a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    static final int MSG_START_RESTORE = 11;
594a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    static final int MSG_RESTORE_PACKAGE = 12;
604a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    static final int MSG_END_RESTORE = 13;
614a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    static final int MSG_TIMEOUT = 100;
624a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
634a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    Handler mHandler;
644a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    IBackupManager mBackupManager;
6532418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate    IMountService mMountService;
664a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    FullObserver mObserver;
674a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    int mToken;
6832418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate    boolean mIsEncrypted;
69ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate    boolean mDidAcknowledge;
704a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
714a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    TextView mStatusView;
72728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate    TextView mCurPassword;
73728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate    TextView mEncPassword;
744a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    Button mAllowButton;
754a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    Button mDenyButton;
764a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
774a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    // Handler for dealing with observer callbacks on the main thread
784a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    class ObserverHandler extends Handler {
794a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        Context mContext;
804a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        ObserverHandler(Context context) {
814a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            mContext = context;
82ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate            mDidAcknowledge = false;
834a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
844a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
854a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        @Override
864a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        public void handleMessage(Message msg) {
874a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            switch (msg.what) {
884a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                case MSG_START_BACKUP: {
8928b591c2a416d7f5955371970272bcaa2b1b303eChristopher Tate                    Toast.makeText(mContext, R.string.toast_backup_started, Toast.LENGTH_LONG).show();
904a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                }
914a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                break;
924a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
934a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                case MSG_BACKUP_PACKAGE: {
944a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                    String name = (String) msg.obj;
954a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                    mStatusView.setText(name);
964a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                }
974a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                break;
984a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
994a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                case MSG_END_BACKUP: {
10028b591c2a416d7f5955371970272bcaa2b1b303eChristopher Tate                    Toast.makeText(mContext, R.string.toast_backup_ended, Toast.LENGTH_LONG).show();
101dc92c82b4180e8067f1acd00a7db7935afce00ffChristopher Tate                    finish();
1024a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                }
1034a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                break;
1044a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1054a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                case MSG_START_RESTORE: {
10628b591c2a416d7f5955371970272bcaa2b1b303eChristopher Tate                    Toast.makeText(mContext, R.string.toast_restore_started, Toast.LENGTH_LONG).show();
1074a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                }
1084a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                break;
1094a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1104a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                case MSG_RESTORE_PACKAGE: {
11175a99709accef8cf221fd436d646727e7c8dd1f1Christopher Tate                    String name = (String) msg.obj;
11275a99709accef8cf221fd436d646727e7c8dd1f1Christopher Tate                    mStatusView.setText(name);
1134a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                }
1144a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                break;
1154a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1164a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                case MSG_END_RESTORE: {
11728b591c2a416d7f5955371970272bcaa2b1b303eChristopher Tate                    Toast.makeText(mContext, R.string.toast_restore_ended, Toast.LENGTH_SHORT).show();
118dc92c82b4180e8067f1acd00a7db7935afce00ffChristopher Tate                    finish();
1194a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                }
1204a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                break;
1214a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1224a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                case MSG_TIMEOUT: {
12328b591c2a416d7f5955371970272bcaa2b1b303eChristopher Tate                    Toast.makeText(mContext, R.string.toast_timeout, Toast.LENGTH_LONG).show();
1244a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                }
1254a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                break;
1264a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            }
1274a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
1284a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    }
1294a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1304a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    @Override
1314a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    public void onCreate(Bundle icicle) {
1324a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        super.onCreate(icicle);
1334a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1344a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        final Intent intent = getIntent();
1354a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        final String action = intent.getAction();
1364a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1372efd2dbbac9eac89620683696c6076463c3a1cd6Christopher Tate        final int layoutId;
138c58cf7dd02ad227a68d62a0204152cee62c13182Christopher Tate        final int titleId;
1394a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        if (action.equals(FullBackup.FULL_BACKUP_INTENT_ACTION)) {
1404a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            layoutId = R.layout.confirm_backup;
141c58cf7dd02ad227a68d62a0204152cee62c13182Christopher Tate            titleId = R.string.backup_confirm_title;
1424a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        } else if (action.equals(FullBackup.FULL_RESTORE_INTENT_ACTION)) {
1434a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            layoutId = R.layout.confirm_restore;
144c58cf7dd02ad227a68d62a0204152cee62c13182Christopher Tate            titleId = R.string.restore_confirm_title;
1454a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        } else {
1464a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            Slog.w(TAG, "Backup/restore confirmation activity launched with invalid action!");
1474a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            finish();
1484a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            return;
1494a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
1504a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1514a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        mToken = intent.getIntExtra(FullBackup.CONF_TOKEN_INTENT_EXTRA, -1);
1524a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        if (mToken < 0) {
1534a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            Slog.e(TAG, "Backup/restore confirmation requested but no token passed!");
1544a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            finish();
1554a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            return;
1564a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
1574a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1584a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));
15932418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate        mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
1604a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1614a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        mHandler = new ObserverHandler(getApplicationContext());
1623851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        final Object oldObserver = getLastNonConfigurationInstance();
1633851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        if (oldObserver == null) {
1643851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate            mObserver = new FullObserver(mHandler);
1653851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        } else {
1663851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate            mObserver = (FullObserver) oldObserver;
1673851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate            mObserver.setHandler(mHandler);
1683851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        }
1694a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
170c58cf7dd02ad227a68d62a0204152cee62c13182Christopher Tate        setTitle(titleId);
1714a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        setContentView(layoutId);
1724a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
1734a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        // Same resource IDs for each layout variant (backup / restore)
1744a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        mStatusView = (TextView) findViewById(R.id.package_name);
1754a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        mAllowButton = (Button) findViewById(R.id.button_allow);
1764a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        mDenyButton = (Button) findViewById(R.id.button_deny);
1774a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
178728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate        mCurPassword = (TextView) findViewById(R.id.password);
179728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate        mEncPassword = (TextView) findViewById(R.id.enc_password);
180728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate        TextView curPwDesc = (TextView) findViewById(R.id.password_desc);
181728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate
18232418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate        // We vary the password prompt depending on whether one is predefined, and whether
18332418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate        // the device is encrypted.
18432418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate        mIsEncrypted = deviceIsEncrypted();
18532418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate        if (mIsEncrypted) {
18632418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate            Log.d(TAG, "Device is encrypted: requiring encryption pw");
18732418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate            TextView pwPrompt = (TextView) findViewById(R.id.password_desc);
18832418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate            // this password is mandatory; we hide the other options during backup
18932418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate            if (layoutId == R.layout.confirm_backup) {
19032418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate                pwPrompt.setText(R.string.device_encryption_backup_text);
19132418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate                TextView tv = (TextView) findViewById(R.id.enc_password);
19232418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate                tv.setVisibility(View.GONE);
19332418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate                tv = (TextView) findViewById(R.id.enc_password_desc);
19432418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate                tv.setVisibility(View.GONE);
19532418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate            } else {
19632418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate                pwPrompt.setText(R.string.device_encryption_restore_text);
19732418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate            }
19832418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate        } else if (!haveBackupPassword()) {
199728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate            curPwDesc.setVisibility(View.GONE);
200728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate            mCurPassword.setVisibility(View.GONE);
201728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate            if (layoutId == R.layout.confirm_backup) {
202728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate                TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
203728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate                encPwDesc.setText(R.string.backup_enc_password_optional);
2042efd2dbbac9eac89620683696c6076463c3a1cd6Christopher Tate            }
2052efd2dbbac9eac89620683696c6076463c3a1cd6Christopher Tate        }
2062efd2dbbac9eac89620683696c6076463c3a1cd6Christopher Tate
2074a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        mAllowButton.setOnClickListener(new View.OnClickListener() {
2084a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            @Override
2094a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            public void onClick(View v) {
210ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate                sendAcknowledgement(mToken, true, mObserver);
2114a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                mAllowButton.setEnabled(false);
2124a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                mDenyButton.setEnabled(false);
2134a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            }
2144a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        });
2154a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
2164a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        mDenyButton.setOnClickListener(new View.OnClickListener() {
2174a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            @Override
2184a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            public void onClick(View v) {
219ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate                sendAcknowledgement(mToken, false, mObserver);
2204a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                mAllowButton.setEnabled(false);
2214a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate                mDenyButton.setEnabled(false);
2224a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            }
2234a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        });
2243851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate
2253851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        // if we're a relaunch we may need to adjust button enable state
2263851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        if (icicle != null) {
2273851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate            mDidAcknowledge = icicle.getBoolean(DID_ACKNOWLEDGE, false);
2283851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate            mAllowButton.setEnabled(!mDidAcknowledge);
2293851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate            mDenyButton.setEnabled(!mDidAcknowledge);
2303851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        }
2314a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    }
2324a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
2333851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate    // Preserve the restore observer callback binder across activity relaunch
2344a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    @Override
2353851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate    public Object onRetainNonConfigurationInstance() {
2363851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        return mObserver;
2373851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate    }
2384a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
2393851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate    @Override
2403851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate    protected void onSaveInstanceState(Bundle outState) {
2413851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        outState.putBoolean(DID_ACKNOWLEDGE, mDidAcknowledge);
2424a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    }
2434a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
244ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate    void sendAcknowledgement(int token, boolean allow, IFullBackupRestoreObserver observer) {
245ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate        if (!mDidAcknowledge) {
246ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate            mDidAcknowledge = true;
2472efd2dbbac9eac89620683696c6076463c3a1cd6Christopher Tate
248ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate            try {
24932418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate                CharSequence encPassword = (mIsEncrypted)
25032418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate                        ? mCurPassword.getText() : mEncPassword.getText();
251728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate                mBackupManager.acknowledgeFullBackupOrRestore(mToken,
252728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate                        allow,
253728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate                        String.valueOf(mCurPassword.getText()),
25432418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate                        String.valueOf(encPassword),
255728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate                        mObserver);
256ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate            } catch (RemoteException e) {
257ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate                // TODO: bail gracefully if we can't contact the backup manager
258ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate            }
259ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate        }
260ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate    }
261ec5d4a0f9765f1645ab2e28ad2ef3cad247a042bChristopher Tate
26232418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate    boolean deviceIsEncrypted() {
26332418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate        try {
26432418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate            return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE);
26532418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate        } catch (Exception e) {
26632418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate            // If we can't talk to the mount service we have a serious problem; fail
26732418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate            // "secure" i.e. assuming that the device is encrypted.
268a23b343299783e5990370579cfc7d93e62dacb8dChristopher Tate            Slog.e(TAG, "Unable to communicate with mount service: " + e.getMessage());
26932418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate            return true;
27032418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate        }
27132418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate    }
27232418be49e5b61c2e9281528cb8fb67939e301e8Christopher Tate
273728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate    boolean haveBackupPassword() {
274728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate        try {
275728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate            return mBackupManager.hasBackupPassword();
276728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate        } catch (RemoteException e) {
277728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate            return true;        // in the failure case, assume we need one
278728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate        }
279728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate    }
280728a1c4d5ed3b808172013a7f5bb5065d1e964f6Christopher Tate
2814a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    /**
2824a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate     * The observer binder for showing backup/restore progress.  This binder just bounces
2834a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate     * the notifications onto the main thread.
2844a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate     */
2854a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    class FullObserver extends IFullBackupRestoreObserver.Stub {
2863851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        private Handler mHandler;
2873851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate
2883851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        public FullObserver(Handler h) {
2893851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate            mHandler = h;
2903851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        }
2913851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate
2923851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        public void setHandler(Handler h) {
2933851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate            mHandler = h;
2943851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate        }
2953851fa9c8d180ca636e69b25f84fdcc294150009Christopher Tate
2964a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        //
2974a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        // IFullBackupRestoreObserver implementation
2984a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        //
2994a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        @Override
3004a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        public void onStartBackup() throws RemoteException {
3014a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            mHandler.sendEmptyMessage(MSG_START_BACKUP);
3024a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
3034a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
3044a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        @Override
3054a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        public void onBackupPackage(String name) throws RemoteException {
3064a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            mHandler.sendMessage(mHandler.obtainMessage(MSG_BACKUP_PACKAGE, name));
3074a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
3084a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
3094a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        @Override
3104a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        public void onEndBackup() throws RemoteException {
3114a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            mHandler.sendEmptyMessage(MSG_END_BACKUP);
3124a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
3134a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
3144a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        @Override
3154a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        public void onStartRestore() throws RemoteException {
3164a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            mHandler.sendEmptyMessage(MSG_START_RESTORE);
3174a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
3184a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
3194a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        @Override
3204a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        public void onRestorePackage(String name) throws RemoteException {
3214a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            mHandler.sendMessage(mHandler.obtainMessage(MSG_RESTORE_PACKAGE, name));
3224a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
3234a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
3244a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        @Override
3254a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        public void onEndRestore() throws RemoteException {
3264a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            mHandler.sendEmptyMessage(MSG_END_RESTORE);
3274a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
3284a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate
3294a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        @Override
3304a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        public void onTimeout() throws RemoteException {
3314a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate            mHandler.sendEmptyMessage(MSG_TIMEOUT);
3324a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate        }
3334a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate    }
3344a627c71ff53a4fca1f961f4b1dcc0461df18a06Christopher Tate}
335