Merge "RoamingDialog stays open on rotation"
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 56b6390..6593e3d 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -16,12 +16,14 @@
 
 package com.android.phone;
 
+import android.app.DialogFragment;
 import com.android.ims.ImsManager;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.TelephonyProperties;
+import com.android.phone.RoamingDialogFragment.RoamingDialogListener;
 import com.android.settingslib.RestrictedLockUtils;
 
 import java.util.ArrayList;
@@ -29,10 +31,8 @@
 import java.util.List;
 
 import android.app.ActionBar;
-import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -76,8 +76,7 @@
  * available from the Phone app (see CallFeaturesSetting for that.)
  */
 public class MobileNetworkSettings extends PreferenceActivity
-        implements DialogInterface.OnClickListener,
-        DialogInterface.OnDismissListener, Preference.OnPreferenceChangeListener{
+        implements Preference.OnPreferenceChangeListener, RoamingDialogListener {
 
     // debug data
     private static final String LOG_TAG = "NetworkSettings";
@@ -87,6 +86,9 @@
     // Number of active Subscriptions to show tabs
     private static final int TAB_THRESHOLD = 2;
 
+    // fragment tag for roaming data dialog
+    private static final String ROAMING_TAG = "RoamingDialogFragment";
+
     //String keys for preference lookup
     private static final String BUTTON_PREFERED_NETWORK_MODE = "preferred_network_mode_key";
     private static final String BUTTON_ROAMING_KEY = "button_roaming_key";
@@ -154,6 +156,12 @@
 
     private final BroadcastReceiver mPhoneChangeReceiver = new PhoneChangeReceiver();
 
+    @Override
+    public void onPositiveButtonClick(DialogFragment dialog) {
+        mPhone.setDataRoamingEnabled(true);
+        mButtonDataRoam.setChecked(true);
+    }
+
     private class PhoneChangeReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -165,24 +173,6 @@
         }
     }
 
-    //This is a method implemented for DialogInterface.OnClickListener.
-    //  Used to dismiss the dialogs when they come up.
-    public void onClick(DialogInterface dialog, int which) {
-        if (which == DialogInterface.BUTTON_POSITIVE) {
-            mPhone.setDataRoamingEnabled(true);
-            mOkClicked = true;
-        } else {
-            // Reset the toggle
-            mButtonDataRoam.setChecked(false);
-        }
-    }
-
-    @Override
-    public void onDismiss(DialogInterface dialog) {
-        // Assuming that onClick gets called first
-        mButtonDataRoam.setChecked(mOkClicked);
-    }
-
     /**
      * Invoked on each preference click in this hierarchy, overrides
      * PreferenceActivity's implementation.  Used to make sure we track the
@@ -925,14 +915,10 @@
             if (!mButtonDataRoam.isChecked()) {
                 // First confirm with a warning dialog about charges
                 mOkClicked = false;
-                new AlertDialog.Builder(this).setMessage(
-                        getResources().getString(R.string.roaming_warning))
-                        .setTitle(R.string.roaming_alert_title)
-                        .setIconAttribute(android.R.attr.alertDialogIcon)
-                        .setPositiveButton(android.R.string.yes, this)
-                        .setNegativeButton(android.R.string.no, this)
-                        .show()
-                        .setOnDismissListener(this);
+                RoamingDialogFragment fragment = new RoamingDialogFragment();
+                fragment.show(getFragmentManager(), ROAMING_TAG);
+                // Don't update the toggle unless the confirm button is actually pressed.
+                return false;
             } else {
                 mPhone.setDataRoamingEnabled(false);
             }
diff --git a/src/com/android/phone/RoamingDialogFragment.java b/src/com/android/phone/RoamingDialogFragment.java
new file mode 100644
index 0000000..ec2967f
--- /dev/null
+++ b/src/com/android/phone/RoamingDialogFragment.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.phone;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnClickListener;
+import android.os.Bundle;
+
+/**
+ * A dialog fragment that asks the user if they are sure they want to turn on data roaming
+ * to avoid accidental charges.
+ */
+public class RoamingDialogFragment extends DialogFragment implements OnClickListener {
+
+    /**
+     * The interface we expect a host activity to implement.
+     */
+    public interface RoamingDialogListener {
+        void onPositiveButtonClick(DialogFragment dialog);
+    }
+
+    // the host activity which implements the listening interface
+    private RoamingDialogListener mListener;
+
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        // Verify host activity implemented callback interface
+        try {
+            mListener = (RoamingDialogListener) getActivity();
+        } catch (ClassCastException e) {
+            throw new ClassCastException(getActivity().toString() +
+                    "must implement RoamingDialogListener");
+        }
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+        builder.setMessage(getResources().getString(R.string.roaming_warning))
+                .setTitle(R.string.roaming_alert_title)
+                .setIconAttribute(android.R.attr.alertDialogIcon)
+                .setPositiveButton(android.R.string.yes, this)
+                .setNegativeButton(android.R.string.no, this);
+        return builder.create();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        // let the host know that the positive button has been clicked
+        if (which == dialog.BUTTON_POSITIVE) {
+            mListener.onPositiveButtonClick(this);
+        }
+    }
+}
diff --git a/tests/Android.mk b/tests/Android.mk
index 66df1a8..2feb55a 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -32,6 +32,8 @@
 LOCAL_STATIC_JAVA_LIBRARIES := \
         android-support-test \
         mockito-target \
-        legacy-android-test
-
+        legacy-android-test \
+        mockito-target-minus-junit4 \
+        espresso-core \
+        truth-prebuilt
 include $(BUILD_PACKAGE)
diff --git a/tests/src/com/android/phone/RoamingDialogFragmentTest.java b/tests/src/com/android/phone/RoamingDialogFragmentTest.java
new file mode 100644
index 0000000..96a3fda
--- /dev/null
+++ b/tests/src/com/android/phone/RoamingDialogFragmentTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.phone;
+
+import android.app.Activity;
+import android.content.pm.ActivityInfo;
+import android.provider.Settings.Global;
+import android.provider.Settings.SettingNotFoundException;
+import android.support.test.espresso.matcher.PreferenceMatchers;
+import android.support.test.rule.ActivityTestRule;
+import com.google.common.truth.Truth;
+import junit.framework.AssertionFailedError;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static android.support.test.espresso.Espresso.onData;
+import static android.support.test.espresso.Espresso.onView;
+import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static android.support.test.espresso.assertion.ViewAssertions.matches;
+import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
+import static android.support.test.espresso.matcher.ViewMatchers.isChecked;
+import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static android.support.test.espresso.matcher.ViewMatchers.withId;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
+import static com.google.common.truth.Truth.assertThat;
+
+/**
+ * Espresso tests to check some properties of the dialog that appears when a user
+ * tries to turn on data roaming.
+ */
+public class RoamingDialogFragmentTest {
+
+    @Rule
+    public ActivityTestRule<MobileNetworkSettings> mRule =
+            new ActivityTestRule<>(MobileNetworkSettings.class);
+    private Activity mActivity;
+
+    /**
+     * Make sure roaming is off before we start a test since this checks the dialog that only
+     * shows up when we try to turn it on.
+     */
+    @Before
+    public void disableRoaming() {
+        mActivity = mRule.getActivity();
+
+        // turn off data roaming if it is on
+        try {
+            onData(PreferenceMatchers.withTitle(R.string.roaming))
+                    .check(matches(hasDescendant(isChecked())))
+                    .perform(click());
+        } catch (AssertionFailedError e) {
+            // don't click the switch if it is already off.
+        }
+    }
+
+    @Test
+    public void dataRoamingDialogPersistsOnRotation() {
+        // click on the data roaming preference to trigger warning dialog
+        onData(PreferenceMatchers.withTitle(R.string.roaming)).perform(click());
+
+        // request both orientations to ensure at least one rotation occurs
+        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+
+        // verify the title of the dialog is visible
+        onView(withText(R.string.roaming_alert_title)).check(matches(isDisplayed()));
+
+    }
+
+    @Test
+    public void dataRoamingEnabledWhenPositiveButtonClicked() throws SettingNotFoundException {
+        // click on the data roaming preference to trigger warning dialog
+        onData(PreferenceMatchers.withTitle(R.string.roaming)).perform(click());
+
+        // click to confirm we want to turn on data roaming
+        onView(withId(android.R.id.button1)).perform(click());
+
+        // verify that the the setting has actually been changed
+        assertThat(Global.getInt(mActivity.getApplicationContext().getContentResolver(),
+                Global.DATA_ROAMING)).isEqualTo(1);
+    }
+
+    @Test
+    public void dialogDismissedOnNegativeButtonClicked() {
+        // click on the data roaming preference to trigger warning dialog
+        onData(PreferenceMatchers.withTitle(R.string.roaming)).perform(click());
+
+        // click to cancel turning on data roaming
+        onView(withId(android.R.id.button2)).perform(click());
+
+        // verify the title of the dialog is gone
+        onView(withText(R.string.roaming_alert_title)).check(doesNotExist());
+    }
+
+    @Test
+    public void dataRoamingStaysDisabledWhenDialogCanceled() throws SettingNotFoundException {
+        // click on the data roaming preference to trigger warning dialog
+        onData(PreferenceMatchers.withTitle(R.string.roaming)).perform(click());
+
+        // click to cancel turning on data roaming
+        onView(withId(android.R.id.button2)).perform(click());
+
+        // verify that the the setting has not been changed
+        assertThat(Global.getInt(mActivity.getApplicationContext().getContentResolver(),
+                Global.DATA_ROAMING)).isEqualTo(0);
+
+    }
+}