Merge "Handle rotation gracefully in the backup/restore confirmation UI"
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
index 7dfa53e..6504435 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_backup.xml
@@ -21,13 +21,15 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="match_parent" 
               android:layout_height="match_parent"
-              android:orientation="vertical"
-              android:padding="16dp" >
+              android:orientation="vertical" >
 
-    <ScrollView 
+    <ScrollView
             android:layout_height="0dp"
             android:layout_weight="1"
-            android:layout_width="match_parent">
+            android:layout_width="match_parent"
+            android:padding="16dp"
+            android:clipToPadding="false" >
+
         <LinearLayout
                 android:orientation="vertical"
                 android:layout_height="wrap_content"
@@ -76,24 +78,29 @@
         </LinearLayout>
     </ScrollView>
 
+    <!-- button bar divider -->
+    <View android:background="?android:attr/dividerHorizontal"
+          android:layout_height="1dp"
+          android:layout_width="match_parent" />
+
+    <!-- button bar -->
     <LinearLayout android:orientation="horizontal"
+                  style="?android:attr/buttonBarStyle"                 
                   android:layout_height="wrap_content"
                   android:layout_width="match_parent"
                   android:layout_gravity="bottom">
 
-    <Button android:id="@+id/button_allow"
-            android:filterTouchesWhenObscured="true"
-            android:text="@string/allow_backup_button_label"
-            android:layout_below="@id/package_name"
+    <Button android:id="@+id/button_deny"
+            style="?android:attr/buttonBarButtonStyle"
+            android:text="@string/deny_backup_button_label"
             android:layout_height="wrap_content"
             android:layout_width="0dp"
             android:layout_weight="1" />
 
-    <Button android:id="@+id/button_deny"
-            android:text="@string/deny_backup_button_label"
-            android:layout_below="@id/package_name"
-            android:layout_toRightOf="@id/button_allow"
-            android:layout_alignTop="@id/button_allow"
+    <Button android:id="@+id/button_allow"
+            style="?android:attr/buttonBarButtonStyle"
+            android:filterTouchesWhenObscured="true"
+            android:text="@string/allow_backup_button_label"
             android:layout_height="wrap_content"
             android:layout_width="0dp"
             android:layout_weight="1" />
diff --git a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
index 4927cbb..3522e7c 100644
--- a/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
+++ b/packages/BackupRestoreConfirmation/res/layout/confirm_restore.xml
@@ -76,24 +76,29 @@
         </LinearLayout>
     </ScrollView>
 
+    <!-- button bar divider -->
+    <View android:background="?android:attr/dividerHorizontal"
+          android:layout_height="1dp"
+          android:layout_width="match_parent" />
+
+    <!-- button bar -->
     <LinearLayout android:orientation="horizontal"
+                  style="?android:attr/buttonBarStyle"                 
                   android:layout_height="wrap_content"
                   android:layout_width="match_parent"
                   android:layout_gravity="bottom">
 
-        <Button android:id="@+id/button_allow"
-                android:filterTouchesWhenObscured="true"
-                android:text="@string/allow_restore_button_label"
-                android:layout_below="@id/package_name"
+        <Button android:id="@+id/button_deny"
+                style="?android:attr/buttonBarButtonStyle"
+                android:text="@string/deny_restore_button_label"
                 android:layout_height="wrap_content"
                 android:layout_width="0dp"
                 android:layout_weight="1" />
 
-        <Button android:id="@+id/button_deny"
-                android:text="@string/deny_restore_button_label"
-                android:layout_below="@id/package_name"
-                android:layout_toRightOf="@id/button_allow"
-                android:layout_alignTop="@id/button_allow"
+        <Button android:id="@+id/button_allow"
+                style="?android:attr/buttonBarButtonStyle"
+                android:filterTouchesWhenObscured="true"
+                android:text="@string/allow_restore_button_label"
                 android:layout_height="wrap_content"
                 android:layout_width="0dp"
                 android:layout_weight="1" />
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index f65a62f..5448e0b 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -48,6 +48,8 @@
     static final String TAG = "BackupRestoreConfirmation";
     static final boolean DEBUG = true;
 
+    static final String DID_ACKNOWLEDGE = "did_acknowledge";
+
     static final int MSG_START_BACKUP = 1;
     static final int MSG_BACKUP_PACKAGE = 2;
     static final int MSG_END_BACKUP = 3;
@@ -149,7 +151,13 @@
         mBackupManager = IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));
 
         mHandler = new ObserverHandler(getApplicationContext());
-        mObserver = new FullObserver();
+        final Object oldObserver = getLastNonConfigurationInstance();
+        if (oldObserver == null) {
+            mObserver = new FullObserver(mHandler);
+        } else {
+            mObserver = (FullObserver) oldObserver;
+            mObserver.setHandler(mHandler);
+        }
 
         setContentView(layoutId);
 
@@ -189,16 +197,24 @@
                 mDenyButton.setEnabled(false);
             }
         });
+
+        // if we're a relaunch we may need to adjust button enable state
+        if (icicle != null) {
+            mDidAcknowledge = icicle.getBoolean(DID_ACKNOWLEDGE, false);
+            mAllowButton.setEnabled(!mDidAcknowledge);
+            mDenyButton.setEnabled(!mDidAcknowledge);
+        }
+    }
+
+    // Preserve the restore observer callback binder across activity relaunch
+    @Override
+    public Object onRetainNonConfigurationInstance() {
+        return mObserver;
     }
 
     @Override
-    public void onStop() {
-        super.onStop();
-
-        // We explicitly equate departure from the UI with refusal.  This includes the
-        // implicit configuration-changed stop/restart cycle.
-        sendAcknowledgement(mToken, false, null);
-        finish();
+    protected void onSaveInstanceState(Bundle outState) {
+        outState.putBoolean(DID_ACKNOWLEDGE, mDidAcknowledge);
     }
 
     void sendAcknowledgement(int token, boolean allow, IFullBackupRestoreObserver observer) {
@@ -230,6 +246,16 @@
      * the notifications onto the main thread.
      */
     class FullObserver extends IFullBackupRestoreObserver.Stub {
+        private Handler mHandler;
+
+        public FullObserver(Handler h) {
+            mHandler = h;
+        }
+
+        public void setHandler(Handler h) {
+            mHandler = h;
+        }
+
         //
         // IFullBackupRestoreObserver implementation
         //