Moving Settings tests closer to the settings code

Change-Id: Ia456db3a8728b35390963c989d5788f4f23806cd
diff --git a/tests/uitests/Android.mk b/tests/uitests/Android.mk
new file mode 100644
index 0000000..23357e8
--- /dev/null
+++ b/tests/uitests/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2018 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.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := SettingsUITests
+LOCAL_COMPATIBILITY_SUITE := device-tests
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_MODULE_TAGS := tests
+LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    app-helpers-base \
+    launcher-helper-lib \
+    settings-helper \
+    timeresult-helper-lib \
+    ub-uiautomator \
+    sysui-helper \
+    metrics-helper-lib \
+    platform-test-annotations \
+
+#LOCAL_SDK_VERSION := current
+
+include $(BUILD_PACKAGE)
diff --git a/tests/uitests/AndroidManifest.xml b/tests/uitests/AndroidManifest.xml
new file mode 100644
index 0000000..06d74c6
--- /dev/null
+++ b/tests/uitests/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.settings.ui">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+    <uses-permission android:name="android.permission.READ_LOGS" />
+
+    <instrumentation
+            android:name="android.support.test.runner.AndroidJUnitRunner"
+            android:targetPackage="com.android.settings.ui"
+            android:label="Android Settings Functional UI Tests" />
+</manifest>
diff --git a/tests/uitests/AndroidTest.xml b/tests/uitests/AndroidTest.xml
new file mode 100644
index 0000000..fbeea2d
--- /dev/null
+++ b/tests/uitests/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+<configuration description="Run Android Settings Functional UI Tests.">
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="SettingsUITests.apk" />
+    </target_preparer>
+
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-tag" value="SettingsUITests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.settings.ui" />
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/tests/uitests/src/com/android/settings/ui/AboutPhoneSettingsTests.java b/tests/uitests/src/com/android/settings/ui/AboutPhoneSettingsTests.java
new file mode 100644
index 0000000..57f9bc2
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/AboutPhoneSettingsTests.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.content.Intent;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/** Verifies basic functionality of the About Phone screen */
+public class AboutPhoneSettingsTests extends InstrumentationTestCase {
+    private static final boolean LOCAL_LOGV = false;
+    private static final String TAG = "AboutPhoneSettingsTest";
+    private static final int TIMEOUT = 2000;
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
+
+    private UiDevice mDevice;
+
+    // TODO: retrieve using name/ids from com.android.settings package
+    private static final String[] sResourceTexts = {
+        "Status",
+        "Legal information",
+        "Regulatory labels",
+        "Model",
+        "Android version",
+        "Android security patch level",
+        "Baseband version",
+        "Kernel version",
+        "Build number"
+    };
+
+    private static final String[] sClickableResourceTexts = {
+        "Status", "Legal information", "Regulatory labels",
+    };
+
+    @Override
+    public void setUp() throws Exception {
+        if (LOCAL_LOGV) {
+            Log.d(TAG, "-------");
+        }
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("Failed to freeze device orientaion", e);
+        }
+
+        // make sure we are in a clean state before starting the test
+        mDevice.pressHome();
+        Thread.sleep(TIMEOUT * 2);
+        launchAboutPhoneSettings(Settings.ACTION_DEVICE_INFO_SETTINGS);
+        // TODO: make sure we are always at the top of the app
+        // currently this will fail if the user has navigated into submenus
+        UiObject2 view =
+                mDevice.wait(
+                        Until.findObject(By.res(SETTINGS_PACKAGE + ":id/main_content")), TIMEOUT);
+        assertNotNull("Could not find main About Phone screen", view);
+        view.scroll(Direction.UP, 1.0f);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Adding an extra pressBack so we exit About Phone Settings
+        // and finish the test cleanly
+        mDevice.pressBack();
+        mDevice.pressHome(); // finish settings activity
+        mDevice.waitForIdle(TIMEOUT * 2); // give UI time to finish animating
+        super.tearDown();
+    }
+
+    private void launchAboutPhoneSettings(String aboutSetting) throws Exception {
+        Intent aboutIntent = new Intent(aboutSetting);
+        aboutIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        getInstrumentation().getContext().startActivity(aboutIntent);
+    }
+
+    /**
+     * Callable actions that can be taken when a UIObject2 is found
+     *
+     * @param device The current UiDevice
+     * @param item The UiObject2 that was found and can be acted on
+     *
+     * @return {@code true} if the call was successful, and {@code false} otherwise
+     */
+    public interface UIObject2Callback {
+        boolean call(UiDevice device, UiObject2 item) throws Exception;
+    }
+
+    /**
+     * Clicks the given item and then presses the Back button
+     *
+     * <p>Used to test whether a given UiObject2 can be successfully clicked.
+     * Presses Back to restore state to the previous screen.
+     *
+     * @param device The device that can be used to press Back
+     * @param item The item to click
+     *
+     * @return {@code true} if clicking the item succeeded, and {@code false} otherwise
+     */
+    public class UiObject2Clicker implements UIObject2Callback {
+        public boolean call(UiDevice device, UiObject2 item) throws Exception {
+            item.click();
+            Thread.sleep(TIMEOUT * 2); // give UI time to finish animating
+            boolean pressWorked = device.pressBack();
+            Thread.sleep(TIMEOUT * 2);
+            return pressWorked;
+        }
+    }
+
+    /**
+     * Removes items found in the view and optionally takes some action.
+     *
+     * @param device The current UiDevice
+     * @param itemsLeftToFind The items to search for in the current view
+     * @param action Action to call on each item that is found; pass {@code null} to take no action
+     */
+    private void removeItemsAndTakeAction(
+            UiDevice device, ArrayList<String> itemsLeftToFind, UIObject2Callback action) throws Exception {
+        for (Iterator<String> iterator = itemsLeftToFind.iterator(); iterator.hasNext(); ) {
+            String itemText = iterator.next();
+            UiObject2 item = device.wait(Until.findObject(By.text(itemText)), TIMEOUT);
+            if (item != null) {
+                if (LOCAL_LOGV) {
+                    Log.d(TAG, itemText + " is present");
+                }
+                iterator.remove();
+                if (action != null) {
+                    boolean success = action.call(device, item);
+                    assertTrue("Calling action after " + itemText + " did not work", success);
+                }
+            } else {
+                if (LOCAL_LOGV) {
+                    Log.d(TAG, "Could not find " + itemText);
+                }
+            }
+        }
+    }
+
+    /**
+     * Searches for UI elements in the current view and optionally takes some action.
+     *
+     * <p>Will scroll down the screen until it has found all elements or reached the bottom.
+     * This allows elements to be found and acted on even if they change order.
+     *
+     * @param device The current UiDevice
+     * @param itemsToFind The items to search for in the current view
+     * @param action Action to call on each item that is found; pass {@code null} to take no action
+     */
+    public void searchForItemsAndTakeAction(UiDevice device, String[] itemsToFind, UIObject2Callback action)
+            throws Exception {
+
+        ArrayList<String> itemsLeftToFind = new ArrayList<String>(Arrays.asList(itemsToFind));
+        assertFalse(
+                "There must be at least one item to search for on the screen!",
+                itemsLeftToFind.isEmpty());
+
+        if (LOCAL_LOGV) {
+            Log.d(TAG, "items: " + TextUtils.join(", ", itemsLeftToFind));
+        }
+        boolean canScrollDown = true;
+        while (canScrollDown && !itemsLeftToFind.isEmpty()) {
+            removeItemsAndTakeAction(device, itemsLeftToFind, action);
+
+            // when we've finished searching the current view, scroll down
+            UiObject2 view =
+                    device.wait(
+                            Until.findObject(By.res(SETTINGS_PACKAGE + ":id/main_content")),
+                            TIMEOUT * 2);
+            if (view != null) {
+                canScrollDown = view.scroll(Direction.DOWN, 1.0f);
+            } else {
+                canScrollDown = false;
+            }
+        }
+        // check the last items once we have reached the bottom of the view
+        removeItemsAndTakeAction(device, itemsLeftToFind, action);
+
+        assertTrue(
+                "The following items were not found on the screen: "
+                        + TextUtils.join(", ", itemsLeftToFind),
+                itemsLeftToFind.isEmpty());
+    }
+
+    @MediumTest // UI interaction
+    public void testAllMenuEntriesExist() throws Exception {
+        searchForItemsAndTakeAction(mDevice, sResourceTexts, null);
+    }
+
+    // Suppressing this test as it might be causing other test failures
+    // Will verify that this test is the cause before proceeding with solution
+    @Suppress
+    @MediumTest // UI interaction
+    public void testClickableEntriesCanBeClicked() throws Exception {
+        searchForItemsAndTakeAction(mDevice, sClickableResourceTexts, new UiObject2Clicker());
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/AccessibilitySettingsTests.java b/tests/uitests/src/com/android/settings/ui/AccessibilitySettingsTests.java
new file mode 100644
index 0000000..83afa65
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/AccessibilitySettingsTests.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.content.Context;
+import android.net.wifi.WifiManager;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.support.test.metricshelper.MetricsAsserts;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.SettingsHelper;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+import android.metrics.MetricsReader;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+public class AccessibilitySettingsTests extends InstrumentationTestCase {
+
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
+    private static final int TIMEOUT = 2000;
+    private UiDevice mDevice;
+    private MetricsReader mMetricsReader;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientaion", e);
+        }
+        mMetricsReader = new MetricsReader();
+        // Clear out old logs
+        mMetricsReader.checkpoint();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Need to finish settings activity
+        mDevice.pressBack();
+        mDevice.pressHome();
+        mDevice.waitForIdle();
+        super.tearDown();
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testHighContrastTextOn() throws Exception {
+        verifyAccessibilitySettingOnOrOff("High contrast text",
+                Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0, 1);
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testHighContrastTextOff() throws Exception {
+        verifyAccessibilitySettingOnOrOff("High contrast text",
+               Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 1, 0);
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testPowerButtonEndsCallOn() throws Exception {
+        verifyAccessibilitySettingOnOrOff("Power button ends call",
+                Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, 1, 2);
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testPowerButtonEndsCallOff() throws Exception {
+        verifyAccessibilitySettingOnOrOff("Power button ends call",
+                Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, 2, 1);
+    }
+
+    /* Suppressing these four tests. The settings don't play
+     * nice with Settings.System.putInt or Settings.Secure.putInt.
+     * Need further clarification. Filed bug b/27792029
+     */
+    @Suppress
+    @MediumTest
+    public void testAutoRotateScreenOn() throws Exception {
+        verifyAccessibilitySettingOnOrOff("Auto-rotate screen",
+               Settings.System.ACCELEROMETER_ROTATION, 0, 1);
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAutoRotateScreenOff() throws Exception {
+       verifyAccessibilitySettingOnOrOff("Auto-rotate screen",
+               Settings.System.ACCELEROMETER_ROTATION, 1, 0);
+    }
+
+    @Suppress
+    @MediumTest
+    public void testMonoAudioOn() throws Exception {
+        verifyAccessibilitySettingOnOrOff("Mono audio",
+               Settings.System.MASTER_MONO, 0, 1);
+    }
+
+    @Suppress
+    @MediumTest
+    public void testMonoAudioOff() throws Exception {
+         verifyAccessibilitySettingOnOrOff("Mono audio",
+                Settings.System.MASTER_MONO, 1, 0);
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testLargeMousePointerOn() throws Exception {
+         verifyAccessibilitySettingOnOrOff("Large mouse pointer",
+                 Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, 0, 1);
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testLargeMousePointerOff() throws Exception {
+         verifyAccessibilitySettingOnOrOff("Large mouse pointer",
+                 Settings.Secure.ACCESSIBILITY_LARGE_POINTER_ICON, 1, 0);
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testColorCorrection() throws Exception {
+        verifySettingToggleAfterScreenLoad("Color correction",
+                Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED);
+        MetricsAsserts.assertHasVisibilityLog("Missing color correction log",
+                mMetricsReader, MetricsEvent.ACCESSIBILITY_TOGGLE_DALTONIZER, true);
+    }
+
+    // Suppressing this test, since UiAutomator + talkback don't play nice
+    @Suppress
+    @MediumTest
+    public void testTalkback() throws Exception {
+        verifySettingToggleAfterScreenLoad("TalkBack",
+                Settings.Secure.ACCESSIBILITY_ENABLED);
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testCaptions() throws Exception {
+         verifySettingToggleAfterScreenLoad("Captions",
+                 Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED);
+        MetricsAsserts.assertHasVisibilityLog("Missing captions log",
+                mMetricsReader, MetricsEvent.ACCESSIBILITY_CAPTION_PROPERTIES, true);
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testMagnificationGesture() throws Exception {
+        verifySettingToggleAfterScreenLoad("Magnification", "Magnify with triple-tap",
+                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
+        MetricsAsserts.assertHasVisibilityLog("Missing magnification log",
+                mMetricsReader, MetricsEvent.ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION, true);
+    }
+
+    @MediumTest
+    public void testClickAfterPointerStopsMoving() throws Exception {
+         verifySettingToggleAfterScreenLoad("Click after pointer stops moving",
+                  Settings.Secure.ACCESSIBILITY_AUTOCLICK_ENABLED);
+    }
+
+    @MediumTest
+    public void testAccessibilitySettingsLoadLog() throws Exception {
+        launchAccessibilitySettings();
+        MetricsAsserts.assertHasVisibilityLog("Missing accessibility settings load log",
+                mMetricsReader, MetricsEvent.ACCESSIBILITY, true);
+    }
+
+    public void launchAccessibilitySettings() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                Settings.ACTION_ACCESSIBILITY_SETTINGS);
+    }
+
+    private void verifyAccessibilitySettingOnOrOff(String settingText,
+            String settingFlag, int initialFlagValue, int expectedFlagValue)
+            throws Exception {
+        Settings.Secure.putInt(getInstrumentation().getContext().getContentResolver(),
+                settingFlag, initialFlagValue);
+        launchAccessibilitySettings();
+        UiObject2 settingsTitle = findItemOnScreen(settingText);
+        settingsTitle.click();
+        Thread.sleep(TIMEOUT);
+        int settingValue = Settings.Secure
+                .getInt(getInstrumentation().getContext().getContentResolver(), settingFlag);
+        assertEquals(settingText + " not correctly set after toggle",
+                expectedFlagValue, settingValue);
+    }
+
+    private void verifySettingToggleAfterScreenLoad(String settingText, String settingFlag)
+            throws Exception {
+        verifySettingToggleAfterScreenLoad(settingText, null, settingFlag);
+    }
+
+    private void verifySettingToggleAfterScreenLoad
+            (String settingText, String subSetting, String settingFlag) throws Exception {
+        // Load accessibility settings
+        launchAccessibilitySettings();
+        Settings.Secure.putInt(getInstrumentation().getContext().getContentResolver(),
+                settingFlag, 0);
+        Thread.sleep(TIMEOUT);
+        // Tap on setting required
+        UiObject2 settingTitle = findItemOnScreen(settingText);
+        // Load screen
+        settingTitle.click();
+        Thread.sleep(TIMEOUT);
+        if (subSetting != null) {
+            UiObject2 subSettingObject = findItemOnScreen(subSetting);
+            subSettingObject.click();
+            Thread.sleep(TIMEOUT);
+        }
+        // Toggle value
+        UiObject2 settingToggle =  mDevice.wait(Until.findObject(By.text("Off")),
+                            TIMEOUT);
+        settingToggle.click();
+        dismissOpenDialog();
+        Thread.sleep(TIMEOUT);
+        // Assert new value
+        int settingValue = Settings.Secure.
+                getInt(getInstrumentation().getContext().getContentResolver(), settingFlag);
+        assertEquals(settingText + " value not set correctly", 1, settingValue);
+        // Toogle value
+        settingToggle.click();
+        dismissOpenDialog();
+        mDevice.pressBack();
+        Thread.sleep(TIMEOUT);
+        // Assert reset to old value
+        settingValue = Settings.Secure.
+                getInt(getInstrumentation().getContext().getContentResolver(), settingFlag);
+        assertEquals(settingText + " value not set correctly", 0, settingValue);
+    }
+
+    private UiObject2 findItemOnScreen(String item) throws Exception {
+        int count = 0;
+        UiObject2 settingsPanel = mDevice.wait(Until.findObject
+                (By.res(SETTINGS_PACKAGE, "list")), TIMEOUT);
+        while (settingsPanel.fling(Direction.UP) && count < 3) {
+            count++;
+        }
+        count = 0;
+        UiObject2 setting = null;
+        while(count < 3 && setting == null) {
+            setting = mDevice.wait(Until.findObject(By.text(item)), TIMEOUT);
+            if (setting == null) {
+                settingsPanel.scroll(Direction.DOWN, 1.0f);
+            }
+            count++;
+        }
+        return setting;
+    }
+
+    private void dismissOpenDialog() throws Exception {
+        UiObject2 okButton = mDevice.wait(Until.findObject
+                (By.res("android:id/button1")), TIMEOUT*2);
+        if (okButton != null) {
+            okButton.click();
+        }
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/AppsSettingsTests.java b/tests/uitests/src/com/android/settings/ui/AppsSettingsTests.java
new file mode 100644
index 0000000..6be49d6
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/AppsSettingsTests.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.content.Intent;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.ActivityHelper;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+/** Verifies basic functionality of the About Phone screen */
+public class AppsSettingsTests extends InstrumentationTestCase {
+    private static final boolean LOCAL_LOGV = false;
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
+    private static final String TAG = "AboutPhoneSettingsTest";
+    private static final int TIMEOUT = 2000;
+    private ActivityHelper mActivityHelper = null;
+
+    private UiDevice mDevice;
+
+    private static final String[] sResourceTexts = {
+        "Storage",
+        "Data usage",
+        "Permissions",
+        "App notifications",
+        "Open by default",
+        "Battery",
+        "Memory"
+    };
+
+    @Override
+    public void setUp() throws Exception {
+        if (LOCAL_LOGV) {
+            Log.d(TAG, "-------");
+        }
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mActivityHelper = ActivityHelper.getInstance();
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("Failed to freeze device orientaion", e);
+        }
+
+        // make sure we are in a clean state before starting the test
+        mDevice.pressHome();
+        Thread.sleep(TIMEOUT * 2);
+        launchAppsSettings();
+        UiObject2 view =
+                mDevice.wait(
+                        Until.findObject(By.text("All apps")), TIMEOUT);
+        assertNotNull("Could not find Settings > Apps screen", view);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDevice.pressBack();
+        mDevice.pressHome(); // finish settings activity
+        mDevice.waitForIdle(TIMEOUT * 2); // give UI time to finish animating
+        super.tearDown();
+    }
+
+    @MediumTest
+    public void testAppSettingsListForCalculator() {
+        UiObject2 calculator = mDevice.wait(
+                Until.findObject(By.text("Calculator")), TIMEOUT);
+        calculator.click();
+        for (String setting : sResourceTexts) {
+            UiObject2 appSetting =
+                mDevice.wait(
+                        Until.findObject(By.text(setting)), TIMEOUT);
+            assertNotNull("Missing setting for Calculator: " + setting, appSetting);
+            appSetting.scroll(Direction.DOWN, 10.0f);
+        }
+    }
+
+    @MediumTest
+    public void testDisablingAndEnablingSystemApp() throws Exception {
+        launchAppsSettings();
+        UiObject2 calculator = mDevice.wait(
+                Until.findObject(By.text("Calculator")), TIMEOUT);
+        calculator.click();
+        mDevice.waitForIdle(TIMEOUT);
+        UiObject2 appInfoList = mDevice.wait(
+            Until.findObject(By.res(SETTINGS_PACKAGE, "list")), TIMEOUT);
+        appInfoList.scroll(Direction.DOWN, 100.0f);
+        UiObject2 disableButton = mDevice.wait(
+                Until.findObject(By.text("DISABLE")), TIMEOUT);
+        disableButton.click();
+        mDevice.waitForIdle(TIMEOUT);
+        // Click on "Disable App" on dialog.
+        mDevice.wait(
+                Until.findObject(By.text("DISABLE APP")), TIMEOUT).click();
+        mDevice.waitForIdle(TIMEOUT);
+        UiObject2 enableButton = mDevice.wait(
+                Until.findObject(By.text("ENABLE")), TIMEOUT);
+        assertNotNull("App not disabled successfully", enableButton);
+        enableButton.click();
+        mDevice.waitForIdle(TIMEOUT);
+        disableButton = mDevice.wait(
+                Until.findObject(By.text("DISABLE")), TIMEOUT);
+        assertNotNull("App not enabled successfully", disableButton);
+    }
+
+    private void launchAppsSettings() throws Exception {
+        Intent appsSettingsIntent = new
+                Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS);
+        mActivityHelper.launchIntent(appsSettingsIntent);
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/BluetoothNetworkSettingsTests.java b/tests/uitests/src/com/android/settings/ui/BluetoothNetworkSettingsTests.java
new file mode 100644
index 0000000..d41be9c
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/BluetoothNetworkSettingsTests.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.content.Context;
+import android.content.Intent;
+import android.metrics.MetricsReader;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.support.test.metricshelper.MetricsAsserts;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
+public class BluetoothNetworkSettingsTests extends InstrumentationTestCase {
+
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
+    private static final int TIMEOUT = 2000;
+    private static final int LONG_TIMEOUT = 40000;
+    private UiDevice mDevice;
+    private MetricsReader mMetricsReader;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientaion", e);
+        }
+        mMetricsReader = new MetricsReader();
+        // Clear out old logs
+        mMetricsReader.checkpoint();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDevice.pressBack();
+        mDevice.pressHome();
+        mDevice.waitForIdle();
+        super.tearDown();
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testBluetoothEnabled() throws Exception {
+        verifyBluetoothOnOrOff(true);
+        MetricsAsserts.assertHasActionLog("missing bluetooth toggle log",
+                mMetricsReader, MetricsEvent.ACTION_BLUETOOTH_TOGGLE);
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testBluetoothDisabled() throws Exception {
+        verifyBluetoothOnOrOff(false);
+        MetricsAsserts.assertHasActionLog("missing bluetooth toggle log",
+                mMetricsReader, MetricsEvent.ACTION_BLUETOOTH_TOGGLE);
+    }
+
+    @MediumTest
+    public void testRenameOption() throws Exception {
+        launchBluetoothSettings();
+        verifyUiObjectClicked(By.text("Device name"), "Rename preference");
+        verifyUiObjectClicked(By.text("CANCEL"), "CANCEL button");
+
+        MetricsAsserts.assertHasActionLog("missing bluetooth rename device log",
+                mMetricsReader, MetricsEvent.ACTION_BLUETOOTH_RENAME);
+        MetricsAsserts.assertHasVisibilityLog("missing bluetooth rename dialog log",
+                mMetricsReader, MetricsEvent.DIALOG_BLUETOOTH_RENAME, true);
+    }
+
+    @MediumTest
+    public void testReceivedFilesOption() throws Exception {
+        launchBluetoothSettings();
+        verifyUiObjectClicked(By.text("Received files"), "Received files preference");
+
+        MetricsAsserts.assertHasActionLog("missing bluetooth received files log",
+                mMetricsReader, MetricsEvent.ACTION_BLUETOOTH_FILES);
+    }
+
+    @MediumTest
+    public void testHelpFeedbackOverflowOption() throws Exception {
+        launchBluetoothSettings();
+
+        // Verify help & feedback
+        assertNotNull("Help & feedback item not found under Bluetooth Settings",
+                mDevice.wait(Until.findObject(By.desc("Help & feedback")), TIMEOUT));
+    }
+
+    public void launchBluetoothSettings() throws Exception {
+        Intent btIntent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
+        btIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        getInstrumentation().getContext().startActivity(btIntent);
+        Thread.sleep(TIMEOUT * 2);
+    }
+
+    /**
+     * Find the {@link UiObject2} by {@code itemSelector} and try to click it if possible.
+     *
+     * If not find, throw assertion error
+     * @param itemSelector used to find the {@link UiObject2}
+     * @param text the description of the {@link UiObject2}
+     */
+    private void verifyUiObjectClicked(BySelector itemSelector, String text) throws Exception {
+        UiObject2 uiObject2 = mDevice.wait(Until.findObject(itemSelector), TIMEOUT);
+        assertNotNull(text + "is not present in bluetooth settings page", uiObject2);
+        uiObject2.click();
+    }
+
+    /**
+     * Toggles the Bluetooth switch and verifies that the change is reflected in Settings
+     *
+     * @param verifyOn set to whether you want the setting turned On or Off
+     */
+    private void verifyBluetoothOnOrOff(boolean verifyOn) throws Exception {
+        String switchText = "ON";
+        BluetoothAdapter bluetoothAdapter = ((BluetoothManager) getInstrumentation().getContext()
+                .getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
+        if (verifyOn) {
+            switchText = "OFF";
+            bluetoothAdapter.disable();
+        } else {
+            bluetoothAdapter.enable();
+        }
+        launchBluetoothSettings();
+        mDevice.wait(Until
+                .findObject(By.res(SETTINGS_PACKAGE, "switch_widget").text(switchText)), TIMEOUT)
+                .click();
+        Thread.sleep(TIMEOUT);
+        String bluetoothValue =
+                Settings.Global.getString(getInstrumentation().getContext().getContentResolver(),
+                        Settings.Global.BLUETOOTH_ON);
+        if (verifyOn) {
+            assertEquals("1", bluetoothValue);
+        } else {
+            assertEquals("0", bluetoothValue);
+        }
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/ConnectedDeviceTests.java b/tests/uitests/src/com/android/settings/ui/ConnectedDeviceTests.java
new file mode 100644
index 0000000..971d724
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/ConnectedDeviceTests.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.content.Context;
+import android.content.Intent;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcManager;
+import android.os.RemoteException;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class ConnectedDeviceTests {
+
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
+    private static final int TIMEOUT = 2000;
+    private UiDevice mDevice;
+
+    @Before
+    public void setUp() throws Exception {
+        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientation", e);
+        }
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        mDevice.pressBack();
+        mDevice.pressHome();
+    }
+
+    // This NFC toggle test is set up this way since there's no way to set
+    // the NFC flag to enabled or disabled without touching UI.
+    // This way, we get coverage for whether or not the toggle button works.
+    @Test
+    public void testNFCToggle() throws Exception {
+        NfcManager manager = (NfcManager) InstrumentationRegistry.getTargetContext()
+                .getSystemService(Context.NFC_SERVICE);
+        NfcAdapter nfcAdapter = manager.getDefaultAdapter();
+        boolean nfcInitiallyEnabled = nfcAdapter.isEnabled();
+        InstrumentationRegistry.getContext().startActivity(new Intent()
+                .setClassName(
+                        SETTINGS_PACKAGE,
+                        "com.android.settings.Settings$ConnectedDeviceDashboardActivity"));
+        UiObject2 nfcSetting = mDevice.wait(Until.findObject(By.text("NFC")), TIMEOUT);
+        nfcSetting.click();
+        Thread.sleep(TIMEOUT * 2);
+        if (nfcInitiallyEnabled) {
+            assertFalse("NFC wasn't disabled on toggle", nfcAdapter.isEnabled());
+            nfcSetting.click();
+            Thread.sleep(TIMEOUT * 2);
+            assertTrue("NFC wasn't enabled on toggle", nfcAdapter.isEnabled());
+        } else {
+            assertTrue("NFC wasn't enabled on toggle", nfcAdapter.isEnabled());
+            nfcSetting.click();
+            Thread.sleep(TIMEOUT * 2);
+            assertFalse("NFC wasn't disabled on toggle", nfcAdapter.isEnabled());
+        }
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/DataUsageSettingsTests.java b/tests/uitests/src/com/android/settings/ui/DataUsageSettingsTests.java
new file mode 100644
index 0000000..725ba5c
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/DataUsageSettingsTests.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.SettingsHelper;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+public class DataUsageSettingsTests extends InstrumentationTestCase {
+
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
+    private static final int TIMEOUT = 2000;
+    private UiDevice mDevice;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientaion", e);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Need to finish settings activity
+        mDevice.pressBack();
+        mDevice.pressHome();
+        super.tearDown();
+    }
+
+    @MediumTest
+    public void testElementsOnDataUsageScreen() throws Exception {
+        launchDataUsageSettings();
+        assertNotNull("Data usage element not found",
+                mDevice.wait(Until.findObject(By.text("Usage")),
+                TIMEOUT));
+        assertNotNull("Data usage bar not found",
+                mDevice.wait(Until.findObject(By.res(SETTINGS_PACKAGE,
+                "color_bar")), TIMEOUT));
+        assertNotNull("WiFi Data usage element not found",
+                mDevice.wait(Until.findObject(By.text("Wi-Fi data usage")),
+                TIMEOUT));
+        assertNotNull("Network restrictions element not found",
+                mDevice.wait(Until.findObject(By.text("Network restrictions")),
+                TIMEOUT));
+    }
+
+    public void launchDataUsageSettings() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                Settings.ACTION_SETTINGS);
+        mDevice.wait(Until
+                .findObject(By.text("Network & Internet")), TIMEOUT)
+                .click();
+        Thread.sleep(TIMEOUT * 2);
+        assertNotNull("Network & internet screen not loaded", mDevice.wait(
+                Until.findObject(By.text("Data usage")), TIMEOUT));
+        mDevice.wait(Until
+                .findObject(By.text("Data usage")), TIMEOUT)
+                .click();
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/DisplaySettingsTest.java b/tests/uitests/src/com/android/settings/ui/DisplaySettingsTest.java
new file mode 100644
index 0000000..0b7402d
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/DisplaySettingsTest.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.content.ContentResolver;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.SettingsHelper;
+import android.system.helpers.SettingsHelper.SettingsType;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.util.regex.Pattern;
+
+public class DisplaySettingsTest extends InstrumentationTestCase {
+
+    private static final String PAGE = Settings.ACTION_DISPLAY_SETTINGS;
+    private static final int TIMEOUT = 2000;
+    private static final FontSetting FONT_SMALL = new FontSetting("Small", 0.85f);
+    private static final FontSetting FONT_NORMAL = new FontSetting("Default", 1.00f);
+    private static final FontSetting FONT_LARGE = new FontSetting("Large", 1.15f);
+    private static final FontSetting FONT_HUGE = new FontSetting("Largest", 1.30f);
+
+    private UiDevice mDevice;
+    private ContentResolver mResolver;
+    private SettingsHelper mHelper;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mDevice.setOrientationNatural();
+        mResolver = getInstrumentation().getContext().getContentResolver();
+        mHelper = new SettingsHelper();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        // reset settings we touched that may impact others
+        Settings.System.putFloat(mResolver, Settings.System.FONT_SCALE, 1.00f);
+        mDevice.waitForIdle();
+        super.tearDown();
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testAdaptiveBrightness() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        mHelper.scrollVert(true);
+        Thread.sleep(1000);
+
+        assertTrue(mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE, "Adaptive brightness",
+                Settings.System.SCREEN_BRIGHTNESS_MODE));
+        assertTrue(mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE, "Adaptive brightness",
+                Settings.System.SCREEN_BRIGHTNESS_MODE));
+    }
+
+
+    // blocked on b/27487224
+    @MediumTest
+    @Suppress
+    public void testDaydreamToggle() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        clickMore();
+        Pattern p = Pattern.compile("On|Off");
+        mHelper.clickSetting("Screen saver");
+        Thread.sleep(1000);
+        try {
+            assertTrue(mHelper.verifyToggleSetting(SettingsType.SECURE, PAGE, p,
+                    Settings.Secure.SCREENSAVER_ENABLED, false));
+            assertTrue(mHelper.verifyToggleSetting(SettingsType.SECURE, PAGE, p,
+                    Settings.Secure.SCREENSAVER_ENABLED, false));
+        } finally {
+            mDevice.pressBack();
+        }
+    }
+
+    @MediumTest
+    public void testAccelRotation() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        mHelper.scrollVert(true);
+        clickMore();
+        Thread.sleep(4000);
+        int currentAccelSetting = Settings.System.getInt(
+                mResolver, Settings.System.ACCELEROMETER_ROTATION);
+        mHelper.clickSetting("Auto-rotate screen");
+        int newAccelSetting = Settings.System.getInt(
+                mResolver, Settings.System.ACCELEROMETER_ROTATION);
+        assertTrue("Accelorometer setting unchanged after toggle", currentAccelSetting != newAccelSetting);
+        mHelper.clickSetting("Auto-rotate screen");
+        int revertedAccelSetting = Settings.System.getInt(
+                mResolver, Settings.System.ACCELEROMETER_ROTATION);
+        assertTrue("Accelorometer setting unchanged after toggle", revertedAccelSetting != newAccelSetting);
+    }
+
+    @MediumTest
+    public void testDaydream() throws Exception {
+        Settings.Secure.putInt(mResolver, Settings.Secure.SCREENSAVER_ENABLED, 1);
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        clickMore();
+        mHelper.scrollVert(false);
+        mDevice.wait(Until.findObject(By.text("Screen saver")), TIMEOUT).click();
+        try {
+            assertTrue(mHelper.verifyRadioSetting(SettingsType.SECURE, PAGE,
+                    "Current screen saver", "Clock", Settings.Secure.SCREENSAVER_COMPONENTS,
+                    "com.google.android.deskclock/com.android.deskclock.Screensaver"));
+            assertTrue(mHelper.verifyRadioSetting(SettingsType.SECURE, PAGE,
+                    "Current screen saver", "Colors", Settings.Secure.SCREENSAVER_COMPONENTS,
+                    "com.android.dreams.basic/com.android.dreams.basic.Colors"));
+            assertTrue(mHelper.verifyRadioSetting(SettingsType.SECURE, PAGE,
+                    "Current screen saver", "Photos", Settings.Secure.SCREENSAVER_COMPONENTS,
+                    "com.google.android.apps.photos/com.google.android.apps.photos.daydream"
+                            + ".PhotosDreamService"));
+        } finally {
+            mDevice.pressBack();
+            Thread.sleep(2000);
+        }
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testSleep15Seconds() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        mHelper.scrollVert(true);
+        assertTrue(mHelper.verifyRadioSetting(SettingsType.SYSTEM, PAGE,
+                "Sleep", "15 seconds", Settings.System.SCREEN_OFF_TIMEOUT, "15000"));
+    }
+
+    @MediumTest
+    public void testSleep30Seconds() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        mHelper.scrollVert(true);
+        assertTrue(mHelper.verifyRadioSetting(SettingsType.SYSTEM, PAGE,
+                "Sleep", "30 seconds", Settings.System.SCREEN_OFF_TIMEOUT, "30000"));
+    }
+
+    @MediumTest
+    public void testSleep1Minute() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        mHelper.scrollVert(true);
+        assertTrue(mHelper.verifyRadioSetting(SettingsType.SYSTEM, PAGE,
+                "Sleep", "1 minute", Settings.System.SCREEN_OFF_TIMEOUT, "60000"));
+    }
+
+    @MediumTest
+    public void testSleep2Minutes() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        mHelper.scrollVert(true);
+        assertTrue(mHelper.verifyRadioSetting(SettingsType.SYSTEM, PAGE,
+                "Sleep", "2 minutes", Settings.System.SCREEN_OFF_TIMEOUT, "120000"));
+    }
+
+    @MediumTest
+    public void testSleep5Minutes() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        mHelper.scrollVert(true);
+        assertTrue(mHelper.verifyRadioSetting(SettingsType.SYSTEM, PAGE,
+                "Sleep", "5 minutes", Settings.System.SCREEN_OFF_TIMEOUT, "300000"));
+    }
+
+    @MediumTest
+    public void testSleep10Minutes() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        mHelper.scrollVert(true);
+        assertTrue(mHelper.verifyRadioSetting(SettingsType.SYSTEM, PAGE,
+                "Sleep", "10 minutes", Settings.System.SCREEN_OFF_TIMEOUT, "600000"));
+    }
+
+    @MediumTest
+    public void testSleep30Minutes() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        mHelper.scrollVert(true);
+        assertTrue(mHelper.verifyRadioSetting(SettingsType.SYSTEM, PAGE,
+                "Sleep", "30 minutes", Settings.System.SCREEN_OFF_TIMEOUT, "1800000"));
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testFontSizeLarge() throws Exception {
+        verifyFontSizeSetting(1.00f, FONT_LARGE);
+        // Leaving the font size at large can make later tests fail, so reset it
+        Settings.System.putFloat(mResolver, Settings.System.FONT_SCALE, 1.00f);
+        // It takes a second for the new font size to be picked up
+        Thread.sleep(2000);
+    }
+
+    @MediumTest
+    public void testFontSizeDefault() throws Exception {
+        verifyFontSizeSetting(1.15f, FONT_NORMAL);
+    }
+
+    @MediumTest
+    public void testFontSizeLargest() throws Exception {
+        verifyFontSizeSetting(1.00f, FONT_HUGE);
+        // Leaving the font size at huge can make later tests fail, so reset it
+        Settings.System.putFloat(mResolver, Settings.System.FONT_SCALE, 1.00f);
+        // It takes a second for the new font size to be picked up
+        Thread.sleep(2000);
+    }
+
+    @MediumTest
+    public void testFontSizeSmall() throws Exception {
+        verifyFontSizeSetting(1.00f, FONT_SMALL);
+    }
+
+    private void verifyFontSizeSetting(float resetValue, FontSetting setting)
+            throws Exception {
+        Settings.System.putFloat(mResolver, Settings.System.FONT_SCALE, resetValue);
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        clickMore();
+        mHelper.clickSetting("Font size");
+        try {
+            mDevice.wait(Until.findObject(By.desc(setting.getName())), TIMEOUT).click();
+            Thread.sleep(1000);
+            float changedValue = Settings.System.getFloat(
+                    mResolver, Settings.System.FONT_SCALE);
+            assertEquals(setting.getSize(), changedValue, 0.0001);
+        } finally {
+            // Make sure to back out of the font menu
+            mDevice.pressBack();
+        }
+    }
+
+    private void clickMore() throws InterruptedException {
+        UiObject2 more = mDevice.wait(Until.findObject(By.text("Advanced")), TIMEOUT);
+        if (more != null) {
+            more.click();
+            Thread.sleep(TIMEOUT);
+        }
+    }
+
+    private static class FontSetting {
+        private final String mSizeName;
+        private final float mSizeVal;
+
+        public FontSetting(String sizeName, float sizeVal) {
+            mSizeName = sizeName;
+            mSizeVal = sizeVal;
+        }
+
+        public String getName() {
+            return mSizeName;
+        }
+
+        public float getSize() {
+            return mSizeVal;
+        }
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java b/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java
new file mode 100644
index 0000000..7931d30
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.SettingsHelper;
+
+import com.android.settings.ui.testutils.SettingsTestUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static com.android.settings.ui.testutils.SettingsTestUtils.SETTINGS_PACKAGE;
+import static com.android.settings.ui.testutils.SettingsTestUtils.TIMEOUT;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class HomepageDisplayTests {
+
+    private static final String[] HOMEPAGE_ITEMS = {
+            "Network & internet",
+            "Connected devices",
+            "Apps & notifications",
+            "Battery",
+            "Display",
+            "Sound",
+            "Storage",
+            "Security & location",
+            "Users & accounts",
+            "Accessibility",
+            "System",
+            "Support & tips"
+    };
+
+    private UiDevice mDevice;
+    private SettingsHelper mSettingsHelper;
+
+    @Before
+    public void setUp() throws Exception {
+        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mSettingsHelper = new SettingsHelper();
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientaion", e);
+        }
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        // Need to finish settings activity
+        mDevice.pressHome();
+    }
+
+    @Presubmit
+    @Test
+    public void testHomepageCategory() throws Exception {
+        // Launch Settings
+        SettingsHelper.launchSettingsPage(
+                InstrumentationRegistry.getContext(), Settings.ACTION_SETTINGS);
+
+        // Scroll to top
+        final UiObject2 view = mDevice.wait(
+                Until.findObject(By.res(SETTINGS_PACKAGE, "main_content")),
+                TIMEOUT);
+        view.scroll(Direction.UP, 100f);
+
+        // Inspect each item
+        for (String item : HOMEPAGE_ITEMS) {
+            SettingsTestUtils.assertTitleMatch(mDevice, item);
+        }
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/LocationSettingsTests.java b/tests/uitests/src/com/android/settings/ui/LocationSettingsTests.java
new file mode 100644
index 0000000..b4a1baa
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/LocationSettingsTests.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.SettingsHelper;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+
+public class LocationSettingsTests extends InstrumentationTestCase {
+
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
+    private static final int TIMEOUT = 2000;
+    private UiDevice mDevice;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientaion", e);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDevice.pressBack();
+        mDevice.pressHome();
+        super.tearDown();
+    }
+
+    @MediumTest
+    public void testLoadingLocationSettings () throws Exception {
+        // Load Security
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                Settings.ACTION_SECURITY_SETTINGS);
+
+        SettingsHelper helper = new SettingsHelper();
+        helper.scrollVert(true);
+        // Tap on location
+        UiObject2 settingsPanel = mDevice.wait(Until.findObject
+                (By.res(SETTINGS_PACKAGE, "main_content")), TIMEOUT);
+        int count = 0;
+        UiObject2 locationTitle = null;
+        while(count < 6 && locationTitle == null) {
+            locationTitle = mDevice.wait(Until.findObject(By.text("Location")), TIMEOUT);
+            if (locationTitle == null) {
+                settingsPanel.scroll(Direction.DOWN, 1.0f);
+            }
+            count++;
+        }
+        // Verify location settings loads.
+        locationTitle.click();
+        Thread.sleep(TIMEOUT);
+        assertNotNull("Location screen has not loaded correctly",
+                mDevice.wait(Until.findObject(By.text("Location services")), TIMEOUT));
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testLocationSettingOn() throws Exception {
+        verifyLocationSettingsOnOrOff(true);
+    }
+
+    @MediumTest
+    public void testLocationSettingOff() throws Exception {
+        verifyLocationSettingsOnOrOff(false);
+    }
+
+    @MediumTest
+    public void testLocationDeviceOnlyMode() throws Exception {
+        // Changing the value from default before testing the toggle to Device only mode
+        Settings.Secure.putInt(getInstrumentation().getContext().getContentResolver(),
+                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
+        dismissAlertDialogs();
+        Thread.sleep(TIMEOUT);
+        verifyLocationSettingsMode(Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
+    }
+
+    @MediumTest
+    public void testLocationBatterySavingMode() throws Exception {
+        Settings.Secure.putInt(getInstrumentation().getContext().getContentResolver(),
+                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
+        Thread.sleep(TIMEOUT);
+        verifyLocationSettingsMode(Settings.Secure.LOCATION_MODE_BATTERY_SAVING);
+    }
+
+    @MediumTest
+    public void testLocationHighAccuracyMode() throws Exception {
+        Settings.Secure.putInt(getInstrumentation().getContext().getContentResolver(),
+                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
+        Thread.sleep(TIMEOUT);
+        verifyLocationSettingsMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
+    }
+
+    @MediumTest
+    public void testLocationSettingsElements() throws Exception {
+        String[] textElements = {"Location", "Mode", "Recent location requests",
+                "Location services"};
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+        Thread.sleep(TIMEOUT);
+        for (String element : textElements) {
+            assertNotNull(element + " item not found under Location Settings",
+                    mDevice.wait(Until.findObject(By.text(element)), TIMEOUT));
+        }
+    }
+
+    @MediumTest
+    public void testLocationSettingsOverflowMenuElements() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                            Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+        // Verify help & feedback
+        assertNotNull("Help & feedback item not found under Location Settings",
+                mDevice.wait(Until.findObject(By.desc("Help & feedback")), TIMEOUT));
+        // Verify scanning
+        assertNotNull("Scanning item not found under Location Settings",
+                mDevice.wait(Until.findObject(By.text("Scanning")), TIMEOUT));
+    }
+
+    private void verifyLocationSettingsMode(int mode) throws Exception {
+        int modeIntValue = 1;
+        String textMode = "Device only";
+        if (mode == Settings.Secure.LOCATION_MODE_HIGH_ACCURACY) {
+            modeIntValue = 3;
+            textMode = "High accuracy";
+        }
+        else if (mode == Settings.Secure.LOCATION_MODE_BATTERY_SAVING) {
+            modeIntValue = 2;
+            textMode = "Battery saving";
+        }
+        // Load location settings
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+        // Tap on mode
+        dismissAlertDialogs();
+        // Load location settings
+        mDevice.wait(Until.findObject(By.text("Mode")), TIMEOUT).click();
+        Thread.sleep(TIMEOUT);
+        assertNotNull("Location mode screen not loaded", mDevice.wait(Until.findObject
+                (By.text("Location mode")), TIMEOUT));
+        // Choose said mode
+        mDevice.wait(Until.findObject(By.text(textMode)), TIMEOUT).click();
+        Thread.sleep(TIMEOUT);
+        dismissAlertDialogs();
+        mDevice.wait(Until.findObject(By.desc("Navigate up")), TIMEOUT).click();
+        Thread.sleep(TIMEOUT);
+        if (mode == Settings.Secure.LOCATION_MODE_HIGH_ACCURACY ||
+                mode == Settings.Secure.LOCATION_MODE_BATTERY_SAVING) {
+            dismissAlertDialogs();
+        }
+        // get setting and verify value
+        // Verify change of mode
+        int locationSettingMode =
+                Settings.Secure.getInt(getInstrumentation().getContext().getContentResolver(),
+                Settings.Secure.LOCATION_MODE);
+        assertEquals(mode + " value not set correctly for location.", modeIntValue,
+                locationSettingMode);
+    }
+
+    private void verifyLocationSettingsOnOrOff(boolean verifyOn) throws Exception {
+        // Set location flag
+        if (verifyOn) {
+            Settings.Secure.putInt(getInstrumentation().getContext().getContentResolver(),
+                    Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
+        }
+        else {
+            Settings.Secure.putInt(getInstrumentation().getContext().getContentResolver(),
+                    Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
+        }
+        dismissAlertDialogs();
+        // Load location settings
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+        dismissAlertDialogs();
+        // Toggle UI
+        mDevice.wait(Until.findObject(By.res(SETTINGS_PACKAGE, "switch_widget")), TIMEOUT).click();
+        dismissAlertDialogs();
+        Thread.sleep(TIMEOUT);
+        // Verify change in setting
+        int locationEnabled = Settings.Secure.getInt(getInstrumentation()
+                 .getContext().getContentResolver(),
+                 Settings.Secure.LOCATION_MODE);
+        if (verifyOn) {
+            assertFalse("Location not enabled correctly", locationEnabled == 0);
+        }
+        else {
+            assertEquals("Location not disabled correctly", 0, locationEnabled);
+        }
+    }
+
+    // This method dismisses both alert dialogs that might popup and
+    // interfere with the test. Since the order in which the dialog
+    // shows up changes in no specific known way, we're checking for
+    // both dialogs in any order for a robust test. Bug b/36233151
+    // filed against Location team for specifications. This is a
+    // workaround in the meantime to ensure coverage.
+    private void dismissAlertDialogs() throws Exception {
+        for (int count = 0; count < 2; count++) {
+            UiObject2 agreeDialog = mDevice.wait(Until.findObject
+                    (By.text("Improve location accuracy?")), TIMEOUT);
+            UiObject2 previousChoiceYesButton = mDevice.wait(Until.findObject
+                    (By.text("YES")), TIMEOUT);
+            if (agreeDialog != null) {
+                mDevice.wait(Until.findObject
+                        (By.text("AGREE")), TIMEOUT).click();
+                Thread.sleep(TIMEOUT);
+                assertNull("Improve location dialog not dismissed",
+                        mDevice.wait(Until.findObject
+                        (By.text("Improve location accuracy?")), TIMEOUT));
+            }
+            if (previousChoiceYesButton != null) {
+                previousChoiceYesButton.click();
+                // Short sleep to wait for the new screen
+                Thread.sleep(TIMEOUT);
+            }
+        }
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/MoreWirelessSettingsTests.java b/tests/uitests/src/com/android/settings/ui/MoreWirelessSettingsTests.java
new file mode 100644
index 0000000..2523686
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/MoreWirelessSettingsTests.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.SettingsHelper;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+
+public class MoreWirelessSettingsTests extends InstrumentationTestCase {
+
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
+    private static final int TIMEOUT = 2000;
+    private UiDevice mDevice;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientaion", e);
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDevice.pressBack();
+        mDevice.pressHome();
+        super.tearDown();
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testAirplaneModeEnabled() throws Exception {
+        verifyAirplaneModeOnOrOff(true);
+        // Toggling this via the wifi network settings page
+        // because of bug b/34858716. Once that is fixed,
+        // we should be able to set this via Settings putString.
+        toggleAirplaneModeSwitch();
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testAirplaneModeDisabled() throws Exception {
+        verifyAirplaneModeOnOrOff(false);
+    }
+
+    @MediumTest
+    public void testTetheringMenuLoad() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                Settings.ACTION_WIRELESS_SETTINGS);
+        mDevice.wait(Until
+                 .findObject(By.text("Hotspot & tethering")), TIMEOUT)
+                 .click();
+        Thread.sleep(TIMEOUT);
+        UiObject2 usbTethering = mDevice.wait(Until
+                 .findObject(By.text("USB tethering")), TIMEOUT);
+        assertNotNull("Tethering screen did not load correctly", usbTethering);
+    }
+
+    @MediumTest
+    public void testVPNMenuLoad() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                Settings.ACTION_WIRELESS_SETTINGS);
+        mDevice.wait(Until
+                 .findObject(By.text("VPN")), TIMEOUT)
+                 .click();
+        Thread.sleep(TIMEOUT);
+        UiObject2 usbTethering = mDevice.wait(Until
+                 .findObject(By.res(SETTINGS_PACKAGE, "vpn_create")), TIMEOUT);
+        assertNotNull("VPN screen did not load correctly", usbTethering);
+    }
+
+    private void verifyAirplaneModeOnOrOff(boolean verifyOn) throws Exception {
+        if (verifyOn) {
+            Settings.Global.putString(getInstrumentation().getContext().getContentResolver(),
+                    Settings.Global.AIRPLANE_MODE_ON, "0");
+        }
+        else {
+            Settings.Global.putString(getInstrumentation().getContext().getContentResolver(),
+                    Settings.Global.AIRPLANE_MODE_ON, "1");
+        }
+        toggleAirplaneModeSwitch();
+        String airplaneModeValue = Settings.Global
+                .getString(getInstrumentation().getContext().getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON);
+        if (verifyOn) {
+            assertEquals("1", airplaneModeValue);
+        }
+        else {
+            assertEquals("0", airplaneModeValue);
+        }
+    }
+
+    private void toggleAirplaneModeSwitch() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                Settings.ACTION_WIRELESS_SETTINGS);
+        mDevice.wait(Until
+                .findObject(By.text("Airplane mode")), TIMEOUT)
+                .click();
+        Thread.sleep(TIMEOUT);
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/NotificationSettingsTests.java b/tests/uitests/src/com/android/settings/ui/NotificationSettingsTests.java
new file mode 100644
index 0000000..133332c
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/NotificationSettingsTests.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.content.Intent;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.ActivityHelper;
+import android.system.helpers.SettingsHelper;
+import android.widget.ListView;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.util.Log;
+
+/** Verifies that you can get to the notification app listing page from the apps & notifications
+ * page */
+public class NotificationSettingsTests extends InstrumentationTestCase {
+    private static final boolean LOCAL_LOGV = false;
+    private static final String TAG = "NotifiSettingsTests";
+    private static final int TIMEOUT = 2000;
+    private ActivityHelper mActivityHelper = null;
+    private SettingsHelper mSettingsHelper = null;
+
+    private UiDevice mDevice;
+    @Override
+    public void setUp() throws Exception {
+        if (LOCAL_LOGV) {
+            Log.d(TAG, "-------");
+        }
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mActivityHelper = ActivityHelper.getInstance();
+        mSettingsHelper = SettingsHelper.getInstance();
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("Failed to freeze device orientaion", e);
+        }
+
+        // make sure we are in a clean state before starting the test
+        mDevice.pressHome();
+        Thread.sleep(TIMEOUT * 2);
+        launchAppsSettings();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDevice.pressBack();
+        mDevice.pressHome(); // finish settings activity
+        mDevice.waitForIdle(TIMEOUT * 2); // give UI time to finish animating
+        super.tearDown();
+    }
+
+    @MediumTest
+    public void testNotificationsSettingsListForCalculator() {
+        UiObject2 configureNotifications = mDevice.wait(
+                Until.findObject(By.text("Notifications")), TIMEOUT);
+        configureNotifications.click();
+        mDevice.wait(Until.findObject(By.text("Blink light")), TIMEOUT);
+        UiObject2 appNotifications = mDevice.wait(
+                Until.findObject(By.text("On for all apps")), TIMEOUT);
+        appNotifications.click();
+        UiObject2 view =
+                mDevice.wait(
+                        Until.findObject(By.text("All apps")), TIMEOUT);
+        assertNotNull("Could not find Settings > Apps screen", view);
+        UiObject2 app = mDevice.wait(Until.findObject(By.text("Calculator")), TIMEOUT);
+        assertNotNull("Could not find Calculator notification settings", app);
+    }
+
+
+    @MediumTest
+    public void testNotificationsSettingsListForPhone() {
+        UiObject2 configureNotifications = mDevice.wait(
+                Until.findObject(By.text("Notifications")), TIMEOUT);
+        configureNotifications.click();
+        mDevice.wait(Until.findObject(By.text("Blink light")), TIMEOUT);
+        UiObject2 appNotifications = mDevice.wait(
+                Until.findObject(By.text("On for all apps")), TIMEOUT);
+        appNotifications.click();
+        UiObject2 view =
+                mDevice.wait(
+                        Until.findObject(By.text("All apps")), TIMEOUT);
+        assertNotNull("Could not find Settings > Apps screen", view);
+
+        final BySelector preferenceListSelector = By.clazz(ListView.class).res("android:id/list");
+        UiObject2 apps = mDevice.wait(Until.findObject(preferenceListSelector), TIMEOUT);
+
+        UiObject2 phone = scrollTo(mDevice, apps, By.text("Phone"), Direction.DOWN);
+        assertNotNull("Could not find Phone notification settings", phone);
+        phone.click();
+        UiObject2 incomingCalls = mDevice.wait(Until.findObject(By.text("Incoming calls")), TIMEOUT);
+        assertNotNull("Could not find incoming calls channel", incomingCalls);
+        incomingCalls.click();
+
+        // here's the meat of this test: make sure that you cannot change
+        // most settings for this channel
+
+        UiObject2 importance = mDevice.wait(Until.findObject(By.text("Importance")), TIMEOUT);
+        assertNotNull("Could not find importance toggle", importance);
+        assertFalse(importance.isEnabled());
+        assertFalse(mDevice.wait(Until.findObject(By.text("Sound")), TIMEOUT).isEnabled());;
+        assertFalse(mDevice.wait(Until.findObject(By.text("Vibrate")), TIMEOUT).isEnabled());
+        assertFalse(mDevice.wait(Until.findObject(By.text("Override Do Not Disturb")), TIMEOUT).isEnabled());
+
+
+
+
+
+
+    }
+
+    private UiObject2 scrollTo(UiDevice device, UiObject2 scrollable,
+                                          BySelector target, Direction direction) {
+        while (!device.hasObject(target) && scrollable.scroll(direction, 1.0f)) {
+            // continue
+        }
+        if (!device.hasObject(target)) {
+            // Scroll once more if not found; in some cases UiObject2.scroll can return false when
+            // the last item is not fully visible yet for list views.
+            scrollable.scroll(direction, 1.0f);
+        }
+        return device.findObject(target);
+    }
+
+
+    private void launchAppsSettings() throws Exception {
+        Intent appsSettingsIntent = new Intent(Settings.ACTION_SETTINGS);
+        mActivityHelper.launchIntent(appsSettingsIntent);
+        mSettingsHelper.flingSettingsToStart();
+        UiObject2 view = mDevice.wait(
+                Until.findObject(By.text("Apps & notifications")), TIMEOUT);
+        view.click();
+        UiObject2 title = mDevice.wait(
+                Until.findObject(By.text("Apps & notifications")), TIMEOUT);
+        assertNotNull("Could not find Settings > Apps & notifications screen", title);
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/SecuritySettingsLaunchTest.java b/tests/uitests/src/com/android/settings/ui/SecuritySettingsLaunchTest.java
new file mode 100644
index 0000000..b730690
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/SecuritySettingsLaunchTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.UiDevice;
+import android.system.helpers.SettingsHelper;
+
+import com.android.settings.ui.testutils.SettingsTestUtils;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class SecuritySettingsLaunchTest {
+
+    // Items we really want to always show
+    private static final String[] CATEGORIES = new String[]{
+            "Security status",
+            "Device security",
+            "Privacy",
+    };
+
+    private UiDevice mDevice;
+    private SettingsHelper mHelper;
+
+    @Before
+    public void setUp() throws Exception {
+        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+        mHelper = SettingsHelper.getInstance();
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientaion", e);
+        }
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        // Go back to home for next test.
+        mDevice.pressHome();
+    }
+
+    @Test
+    public void launchSecuritySettings() throws Exception {
+        // Launch Settings
+        SettingsHelper.launchSettingsPage(
+                InstrumentationRegistry.getContext(), Settings.ACTION_SECURITY_SETTINGS);
+        mHelper.scrollVert(false);
+        for (String category : CATEGORIES) {
+            SettingsTestUtils.assertTitleMatch(mDevice, category);
+        }
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/SoundSettingsTest.java b/tests/uitests/src/com/android/settings/ui/SoundSettingsTest.java
new file mode 100644
index 0000000..0aec505
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/SoundSettingsTest.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.app.NotificationManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.Handler;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.service.notification.ZenModeConfig;
+import android.support.test.uiautomator.UiObject2;
+import android.system.helpers.SettingsHelper;
+import android.system.helpers.SettingsHelper.SettingsType;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.Until;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+
+import java.util.HashMap;
+
+public class SoundSettingsTest extends InstrumentationTestCase {
+    private static final String PAGE = Settings.ACTION_SOUND_SETTINGS;
+    private static final int TIMEOUT = 2000;
+
+    private UiDevice mDevice;
+    private ContentResolver mResolver;
+    private SettingsHelper mHelper;
+
+
+    private HashMap ringtoneSounds = new HashMap<String, String>() {{
+        put("angler","Dione");
+        put("bullhead","Dione");
+        put("marlin","Spaceship");
+        put("sailfish","Spaceship");
+        put("walleye","Copycat");
+        put("taimen","Copycat");
+    }};
+
+    private HashMap ringtoneCodes = new HashMap<String, String>() {{
+        put("angler","38");
+        put("bullhead","38");
+        put("marlin","37");
+        put("sailfish","37");
+        put("walleye","26");
+        put("taimen","26");
+    }};
+
+    private HashMap alarmSounds = new HashMap<String, String>() {{
+        put("angler","Awaken");
+        put("bullhead","Awaken");
+        put("marlin","Bounce");
+        put("sailfish","Bounce");
+        put("walleye","Cuckoo clock");
+        put("taimen","Cuckoo clock");
+    }};
+
+    private HashMap alarmCodes = new HashMap<String, String>() {{
+        put("angler","6");
+        put("bullhead","6");
+        put("marlin","49");
+        put("sailfish","49");
+        put("walleye","15");
+        put("taimen","15");
+    }};
+
+    private HashMap notificationSounds = new HashMap<String, String>() {{
+        put("angler","Ceres");
+        put("bullhead","Ceres");
+        put("marlin","Trill");
+        put("sailfish","Trill");
+        put("walleye","Pipes");
+        put("taimen","Pipes");
+    }};
+
+
+    private HashMap notificationCodes = new HashMap<String, String>() {{
+        put("angler","26");
+        put("bullhead","26");
+        put("marlin","57");
+        put("sailfish","57");
+        put("walleye","69");
+        put("taimen","69");
+    }};
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mDevice.setOrientationNatural();
+        mResolver = getInstrumentation().getContext().getContentResolver();
+        mHelper = new SettingsHelper();
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        mDevice.pressBack();
+        mDevice.pressHome();
+        mDevice.waitForIdle();
+        mDevice.unfreezeRotation();
+        super.tearDown();
+    }
+
+    @MediumTest
+    public void testCallVibrate() throws Exception {
+        assertTrue(mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE,
+                "Also vibrate for calls", Settings.System.VIBRATE_WHEN_RINGING));
+        assertTrue(mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE,
+                "Also vibrate for calls", Settings.System.VIBRATE_WHEN_RINGING));
+    }
+
+    @MediumTest
+    public void testOtherSoundsDialPadTones() throws Exception {
+        loadOtherSoundsPage();
+        assertTrue("Dial pad tones not toggled", mHelper.verifyToggleSetting(
+                SettingsType.SYSTEM, PAGE, "Dial pad tones",
+                Settings.System.DTMF_TONE_WHEN_DIALING));
+    }
+
+    @MediumTest
+    public void testOtherSoundsScreenLocking() throws Exception {
+        loadOtherSoundsPage();
+        assertTrue("Screen locking sounds not toggled",
+                    mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE,
+                    "Screen locking sounds", Settings.System.LOCKSCREEN_SOUNDS_ENABLED));
+    }
+
+    @MediumTest
+    public void testOtherSoundsCharging() throws Exception {
+        loadOtherSoundsPage();
+        assertTrue("Charging sounds not toggled",
+                    mHelper.verifyToggleSetting(SettingsType.GLOBAL, PAGE,
+                    "Charging sounds", Settings.Global.CHARGING_SOUNDS_ENABLED));
+    }
+
+    @MediumTest
+    public void testOtherSoundsTouch() throws Exception {
+        loadOtherSoundsPage();
+        assertTrue("Touch sounds not toggled",
+                    mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE,
+                    "Touch sounds", Settings.System.SOUND_EFFECTS_ENABLED));
+    }
+
+    @MediumTest
+    public void testOtherSoundsVibrateOnTap() throws Exception {
+        loadOtherSoundsPage();
+        assertTrue("Vibrate on tap not toggled",
+                    mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE,
+                    "Vibrate on tap", Settings.System.HAPTIC_FEEDBACK_ENABLED));
+    }
+
+    private void loadOtherSoundsPage() throws Exception {
+        launchSoundSettings();
+        mHelper.scrollVert(false);
+        Thread.sleep(1000);
+    }
+
+    private void launchSoundSettings() throws Exception {
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
+        mHelper.scrollVert(false);
+        clickMore();
+        Thread.sleep(1000);
+        mHelper.scrollVert(true);
+        Thread.sleep(1000);
+    }
+
+    /*
+     * Rather than verifying every ringtone, verify the ones least likely to change
+     * (None and Hangouts) and an arbitrary one from the ringtone pool.
+     */
+    @MediumTest
+    public void testPhoneRingtoneNone() throws Exception {
+        launchSoundSettings();
+        mHelper.clickSetting("Phone ringtone");
+        verifyRingtone(new RingtoneSetting("None", "null"),
+                Settings.System.RINGTONE);
+    }
+
+    @MediumTest
+    @Suppress
+    public void testPhoneRingtoneHangouts() throws Exception {
+        launchSoundSettings();
+        mHelper.clickSetting("Phone ringtone");
+        verifyRingtone(new RingtoneSetting("Hangouts Call", "31"), Settings.System.RINGTONE);
+    }
+
+    @MediumTest
+    public void testPhoneRingtone() throws Exception {
+        launchSoundSettings();
+        mHelper.clickSetting("Phone ringtone");
+        String ringtone = ringtoneSounds.get(mDevice.getProductName()).toString();
+        String ringtoneSettingValue = ringtoneCodes.get(mDevice.getProductName()).toString();
+        verifyRingtone(new RingtoneSetting(ringtone, ringtoneSettingValue),
+                Settings.System.RINGTONE);
+    }
+
+    @MediumTest
+    public void testNotificationRingtoneNone() throws Exception {
+        launchSoundSettings();
+        mHelper.clickSetting("Default notification sound");
+        verifyRingtone(new RingtoneSetting("None", "null"),
+                Settings.System.NOTIFICATION_SOUND);
+    }
+
+    @MediumTest
+    @Suppress
+    public void testNotificationRingtoneHangouts() throws Exception {
+        launchSoundSettings();
+        mHelper.clickSetting("Default notification sound");
+        verifyRingtone(new RingtoneSetting("Hangouts Message", "30"),
+                Settings.System.NOTIFICATION_SOUND);
+    }
+
+    @MediumTest
+    public void testNotificationRingtone() throws Exception {
+        launchSoundSettings();
+        mHelper.clickSetting("Default notification sound");
+        String notificationRingtone = notificationSounds.get(mDevice.getProductName()).toString();
+        String notificationSettingValue = notificationCodes.get(mDevice.getProductName()).toString();
+        verifyRingtone(new RingtoneSetting(notificationRingtone, notificationSettingValue),
+                Settings.System.NOTIFICATION_SOUND);
+    }
+
+    @MediumTest
+    public void testAlarmRingtoneNone() throws Exception {
+        launchSoundSettings();
+        mHelper.clickSetting("Default alarm sound");
+        verifyRingtone(new RingtoneSetting("None", "null"),
+                Settings.System.ALARM_ALERT);
+    }
+
+    @MediumTest
+    public void testAlarmRingtone() throws Exception {
+        launchSoundSettings();
+        String alarmRingtone = alarmSounds.get(mDevice.getProductName()).toString();
+        String alarmSettingValue = alarmCodes.get(mDevice.getProductName()).toString();
+        mHelper.clickSetting("Default alarm sound");
+        verifyRingtone(new RingtoneSetting(alarmRingtone, alarmSettingValue),
+                Settings.System.ALARM_ALERT);
+    }
+
+    /*
+     * This method verifies that setting a custom ringtone changes the
+     * ringtone code setting on the system. Each ringtone sound corresponds
+     * to an arbitrary code. To see which ringtone code this is on your device, run
+     * adb shell settings get system ringtone
+     * The number you see at the end of the file path is the one you need.
+     * To see alarms and notifications ringtone codes, run the following:
+     * adb shell settings get system alarm_alert
+     * adb shell settings get system notification_sound
+     * @param r Ringtone setting - the name of the ringtone as displayed on device
+     * @param settingName - the code of the ringtone as explained above
+     * @param dir - the direction in which to scroll
+     */
+    private void verifyRingtone(RingtoneSetting r, String settingName) throws Exception {
+        findRingtoneInList(r.getName()).click();
+        if (mDevice.getProductName().equals("walleye") || mDevice.getProductName().equals("taimen")) {
+            mDevice.wait(Until.findObject(By.text("SAVE")), TIMEOUT).click();
+        }
+        else {
+            mDevice.wait(Until.findObject(By.text("OK")), TIMEOUT).click();
+        }
+        SystemClock.sleep(1000);
+        if (r.getVal().equals("null")) {
+            assertEquals(null,
+                    Settings.System.getString(mResolver, settingName));
+        } else if (r.getName().contains("Hangouts")) {
+            assertEquals("content://media/external/audio/media/" + r.getVal(),
+                    Settings.System.getString(mResolver, settingName));
+        } else {
+            assertEquals("content://media/internal/audio/media/" + r.getVal(),
+                    Settings.System.getString(mResolver, settingName));
+        }
+    }
+
+    private enum ScrollDir {
+        UP,
+        DOWN,
+        NOSCROLL
+    }
+
+    class RingtoneSetting {
+        private final String mName;
+        private final String mMediaVal;
+        public RingtoneSetting(String name, String fname) {
+            mName = name;
+            mMediaVal = fname;
+        }
+        public String getName() {
+            return mName;
+        }
+        public String getVal() {
+            return mMediaVal;
+        }
+    }
+
+    private void clickMore() throws InterruptedException {
+        UiObject2 more = mDevice.wait(Until.findObject(By.text("Advanced")), TIMEOUT);
+        if (more != null) {
+            more.click();
+            Thread.sleep(TIMEOUT);
+        }
+    }
+
+    private UiObject2 findRingtoneInList(String ringtone) throws Exception {
+        mHelper.scrollVert(false);
+        SystemClock.sleep(1000);
+        UiObject2 ringToneObject = mDevice.wait(Until.findObject(By.text(ringtone)), TIMEOUT);
+        int count = 0;
+        while (ringToneObject == null && count < 5) {
+            mHelper.scrollVert(true);
+            SystemClock.sleep(1000);
+            ringToneObject = mDevice.wait(Until.findObject(By.text(ringtone)), TIMEOUT);
+            count++;
+        }
+        return ringToneObject;
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/SyncSettingsTest.java b/tests/uitests/src/com/android/settings/ui/SyncSettingsTest.java
new file mode 100644
index 0000000..3dca424
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/SyncSettingsTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.system.helpers.SettingsHelper;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static junit.framework.Assert.assertTrue;
+
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class SyncSettingsTest {
+    private static final int TIMEOUT = 2000;
+
+    private UiDevice mDevice;
+
+    @Before
+    public void setUp() throws Exception {
+        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientaion", e);
+        }
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        // Need to finish settings activity
+        mDevice.pressHome();
+    }
+
+    @Test
+    public void syncPageShouldHaveAddAccountButton() throws Exception {
+        // Launch Settings
+        SettingsHelper.launchSettingsPage(
+                InstrumentationRegistry.getContext(), Settings.ACTION_SYNC_SETTINGS);
+        UiObject2 addAccount = mDevice.wait(
+                Until.findObject(By.text("Add account")), TIMEOUT);
+        assertTrue(addAccount != null);
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/WirelessNetworkSettingsTests.java b/tests/uitests/src/com/android/settings/ui/WirelessNetworkSettingsTests.java
new file mode 100644
index 0000000..1e3b978
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/WirelessNetworkSettingsTests.java
@@ -0,0 +1,777 @@
+/*
+ * Copyright (C) 2018 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.settings.ui;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.wifi.WifiManager;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.provider.Settings;
+import android.system.helpers.CommandsHelper;
+import android.system.helpers.SettingsHelper;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.StaleObjectException;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.util.Log;
+import junit.framework.AssertionFailedError;
+
+public class WirelessNetworkSettingsTests extends InstrumentationTestCase {
+    // These back button presses are performed in tearDown() to exit Wifi
+    // Settings sub-menus that a test might finish in. This number should be
+    // high enough to account for the deepest sub-menu a test might enter.
+    private static final int NUM_BACK_BUTTON_PRESSES = 5;
+    private static final int TIMEOUT = 2000;
+    private static final int SLEEP_TIME = 500;
+    private static final String AIRPLANE_MODE_BROADCAST =
+            "am broadcast -a android.intent.action.AIRPLANE_MODE";
+    private static final String TAG="WirelessNetworkSettingsTests";
+
+    // Note: The values of these variables might affect flakiness in tests that involve
+    // scrolling. Adjust where necessary.
+    private static final float SCROLL_UP_PERCENT = 10.0f;
+    private static final float SCROLL_DOWN_PERCENT = 0.5f;
+    private static final int MAX_SCROLL_ATTEMPTS = 10;
+    private static final int MAX_ADD_NETWORK_BUTTON_ATTEMPTS = 3;
+    private static final int SCROLL_SPEED = 2000;
+
+    private static final String TEST_SSID = "testSsid";
+    private static final String TEST_PW_GE_8_CHAR = "testPasswordGreaterThan8Char";
+    private static final String TEST_PW_LT_8_CHAR = "lt8Char";
+    private static final String TEST_DOMAIN = "testDomain.com";
+
+    private static final String SETTINGS_PACKAGE = "com.android.settings";
+
+    private static final String CHECKBOX_CLASS = "android.widget.CheckBox";
+    private static final String SPINNER_CLASS = "android.widget.Spinner";
+    private static final String EDIT_TEXT_CLASS = "android.widget.EditText";
+    private static final String SCROLLVIEW_CLASS = "android.widget.ScrollView";
+    private static final String LISTVIEW_CLASS = "android.widget.ListView";
+
+    private static final String ADD_NETWORK_MENU_CANCEL_BUTTON_TEXT = "CANCEL";
+    private static final String ADD_NETWORK_MENU_SAVE_BUTTON_TEXT = "SAVE";
+    private static final String ADD_NETWORK_PREFERENCE_TEXT = "Add network";
+    private static final String CONFIGURE_WIFI_PREFERENCE_TEXT = "Wi‑Fi preferences";
+    private static final String CONFIGURE_WIFI_ADVANCED_PREFERENCE_TEXT = "Advanced";
+    private static final String CACERT_MENU_PLEASE_SELECT_TEXT = "Please select";
+    private static final String CACERT_MENU_USE_SYSTEM_CERTS_TEXT = "Use system certificates";
+    private static final String CACERT_MENU_DO_NOT_VALIDATE_TEXT = "Do not validate";
+    private static final String USERCERT_MENU_PLEASE_SELECT_TEXT = "Please select";
+    private static final String USERCERT_MENU_DO_NOT_PROVIDE_TEXT = "Do not provide";
+    private static final String SECURITY_OPTION_NONE_TEXT = "None";
+    private static final String SECURITY_OPTION_WEP_TEXT = "WEP";
+    private static final String SECURITY_OPTION_PSK_TEXT = "WPA/WPA2 PSK";
+    private static final String SECURITY_OPTION_EAP_TEXT = "802.1x EAP";
+    private static final String EAP_METHOD_PEAP_TEXT = "PEAP";
+    private static final String EAP_METHOD_TLS_TEXT = "TLS";
+    private static final String EAP_METHOD_TTLS_TEXT = "TTLS";
+    private static final String EAP_METHOD_PWD_TEXT = "PWD";
+    private static final String EAP_METHOD_SIM_TEXT = "SIM";
+    private static final String EAP_METHOD_AKA_TEXT = "AKA";
+    private static final String EAP_METHOD_AKA_PRIME_TEXT = "AKA'";
+    private static final String PHASE2_MENU_NONE_TEXT = "None";
+    private static final String PHASE2_MENU_MSCHAPV2_TEXT = "MSCHAPV2";
+    private static final String PHASE2_MENU_GTC_TEXT = "GTC";
+
+    private static final String ADD_NETWORK_MENU_ADV_TOGGLE_RES_ID = "wifi_advanced_togglebox";
+    private static final String ADD_NETWORK_MENU_IP_SETTINGS_RES_ID = "ip_settings";
+    private static final String ADD_NETWORK_MENU_PROXY_SETTINGS_RES_ID = "proxy_settings";
+    private static final String ADD_NETWORK_MENU_SECURITY_OPTION_RES_ID = "security";
+    private static final String ADD_NETWORK_MENU_EAP_METHOD_RES_ID = "method";
+    private static final String ADD_NETWORK_MENU_SSID_RES_ID = "ssid";
+    private static final String ADD_NETWORK_MENU_PHASE2_RES_ID = "phase2";
+    private static final String ADD_NETWORK_MENU_CACERT_RES_ID = "ca_cert";
+    private static final String ADD_NETWORK_MENU_USERCERT_RES_ID = "user_cert";
+    private static final String ADD_NETWORK_MENU_NO_DOMAIN_WARNING_RES_ID = "no_domain_warning";
+    private static final String ADD_NETWORK_MENU_NO_CACERT_WARNING_RES_ID = "no_ca_cert_warning";
+    private static final String ADD_NETWORK_MENU_DOMAIN_LAYOUT_RES_ID = "l_domain";
+    private static final String ADD_NETWORK_MENU_DOMAIN_RES_ID = "domain";
+    private static final String ADD_NETWORK_MENU_IDENTITY_LAYOUT_RES_ID = "l_identity";
+    private static final String ADD_NETWORK_MENU_ANONYMOUS_LAYOUT_RES_ID = "l_anonymous";
+    private static final String ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID = "password_layout";
+    private static final String ADD_NETWORK_MENU_SHOW_PASSWORD_LAYOUT_RES_ID =
+            "show_password_layout";
+    private static final String ADD_NETWORK_MENU_PASSWORD_RES_ID = "password";
+
+    private static final BySelector ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR =
+            By.scrollable(true).clazz(SCROLLVIEW_CLASS);
+    private static final BySelector SPINNER_OPTIONS_SCROLLABLE_BY_SELECTOR =
+            By.scrollable(true).clazz(LISTVIEW_CLASS);
+
+    private UiDevice mDevice;
+    private CommandsHelper mCommandsHelper;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        try {
+            mDevice.setOrientationNatural();
+        } catch (RemoteException e) {
+            throw new RuntimeException("failed to freeze device orientation", e);
+        }
+        // Ensure airplane mode is OFF so that wifi can be enabled using WiFiManager.
+        Settings.Global.putString(getInstrumentation().getContext().getContentResolver(),
+                Settings.Global.AIRPLANE_MODE_ON, "0");
+        Log.d(TAG, "sending airplane mode broadcast to device");
+        mCommandsHelper = CommandsHelper.getInstance();
+        mCommandsHelper.executeShellCommand(AIRPLANE_MODE_BROADCAST);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Exit all settings sub-menus.
+        for (int i = 0; i < NUM_BACK_BUTTON_PRESSES; ++i) {
+            mDevice.pressBack();
+        }
+        mDevice.pressHome();
+        super.tearDown();
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testWiFiEnabled() throws Exception {
+        verifyWiFiOnOrOff(true);
+    }
+
+    @Presubmit
+    @MediumTest
+    public void testWiFiDisabled() throws Exception {
+        verifyWiFiOnOrOff(false);
+    }
+
+    @MediumTest
+    public void testWifiMenuLoadConfigure() throws Exception {
+        loadWiFiConfigureMenu();
+        Thread.sleep(SLEEP_TIME);
+        UiObject2 configureWiFiHeading = mDevice.wait(Until.findObject
+                (By.text(CONFIGURE_WIFI_PREFERENCE_TEXT)), TIMEOUT);
+        assertNotNull("Configure WiFi menu has not loaded correctly", configureWiFiHeading);
+    }
+
+    @MediumTest
+    public void testNetworkNotificationsOn() throws Exception {
+        verifyNetworkNotificationsOnOrOff(true);
+    }
+
+    @MediumTest
+    public void testNetworkNotificationsOff() throws Exception {
+        verifyNetworkNotificationsOnOrOff(false);
+    }
+
+    @MediumTest
+    public void testAddNetworkMenu_Default() throws Exception {
+        loadAddNetworkMenu();
+
+        // Submit button should be disabled by default, while cancel button should be enabled.
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+        assertTrue(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_CANCEL_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        // Check that the SSID field is defaults to the hint.
+        assertEquals("Enter the SSID", mDevice.wait(Until.findObject(By
+                .res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SSID_RES_ID)
+                .clazz(EDIT_TEXT_CLASS)), TIMEOUT*2)
+                .getText());
+
+        // Check Security defaults to None.
+        assertEquals("None", mDevice.wait(Until.findObject(By
+                .res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SECURITY_OPTION_RES_ID)
+                .clazz(SPINNER_CLASS)), TIMEOUT)
+                .getChildren().get(0).getText());
+
+        // Check advanced options are collapsed by default.
+        assertFalse(mDevice.wait(Until.findObject(By
+                .res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_ADV_TOGGLE_RES_ID)
+                .clazz(CHECKBOX_CLASS)), TIMEOUT).isChecked());
+
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetworkMenu_Proxy() throws Exception {
+        loadAddNetworkMenu();
+
+        // Toggle advanced options.
+        mDevice.wait(Until.findObject(By
+                .res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_ADV_TOGGLE_RES_ID)
+                .clazz(CHECKBOX_CLASS)), TIMEOUT).click();
+
+        // Verify Proxy defaults to None.
+        BySelector proxySettingsBySelector =
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PROXY_SETTINGS_RES_ID)
+                .clazz(SPINNER_CLASS);
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, proxySettingsBySelector);
+        assertEquals("None", mDevice.wait(Until.findObject(proxySettingsBySelector), TIMEOUT)
+                .getChildren().get(0).getText());
+
+        // Verify that Proxy Manual fields appear.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, proxySettingsBySelector);
+        mDevice.wait(Until.findObject(proxySettingsBySelector), TIMEOUT).click();
+        mDevice.wait(Until.findObject(By.text("Manual")), TIMEOUT).click();
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, "proxy_warning_limited_support"));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, "proxy_hostname"));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, "proxy_exclusionlist"));
+
+        // Verify that Proxy Auto-Config options appear.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, proxySettingsBySelector);
+        mDevice.wait(Until.findObject(proxySettingsBySelector), TIMEOUT).click();
+        mDevice.wait(Until.findObject(By.text("Proxy Auto-Config")), TIMEOUT).click();
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, "proxy_pac"));
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetworkMenu_IpSettings() throws Exception {
+        loadAddNetworkMenu();
+
+        // Toggle advanced options.
+        mDevice.wait(Until.findObject(By
+                .res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_ADV_TOGGLE_RES_ID)
+                .clazz(CHECKBOX_CLASS)), TIMEOUT).click();
+
+        // Verify IP settings defaults to DHCP.
+        BySelector ipSettingsBySelector =
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_IP_SETTINGS_RES_ID).clazz(SPINNER_CLASS);
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, ipSettingsBySelector);
+        assertEquals("DHCP", mDevice.wait(Until.findObject(ipSettingsBySelector), TIMEOUT)
+                .getChildren().get(0).getText());
+
+        // Verify that Static IP settings options appear.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, ipSettingsBySelector).click();
+        mDevice.wait(Until.findObject(By.text("Static")), TIMEOUT).click();
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, "ipaddress"));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, "gateway"));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, "network_prefix_length"));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, "dns1"));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, "dns2"));
+    }
+
+    @Suppress
+    @MediumTest
+    public void testPhase2Settings() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
+
+        BySelector phase2SettingsBySelector =
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PHASE2_RES_ID).clazz(SPINNER_CLASS);
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, phase2SettingsBySelector);
+        assertEquals(PHASE2_MENU_NONE_TEXT, mDevice.wait(Until
+                .findObject(phase2SettingsBySelector), TIMEOUT).getChildren().get(0).getText());
+        mDevice.wait(Until.findObject(phase2SettingsBySelector), TIMEOUT).click();
+        Thread.sleep(SLEEP_TIME);
+
+        // Verify Phase 2 authentication spinner options.
+        assertNotNull(mDevice.wait(Until.findObject(By.text(PHASE2_MENU_NONE_TEXT)), TIMEOUT));
+        assertNotNull(mDevice.wait(Until.findObject(By.text(PHASE2_MENU_MSCHAPV2_TEXT)), TIMEOUT));
+        assertNotNull(mDevice.wait(Until.findObject(By.text(PHASE2_MENU_GTC_TEXT)), TIMEOUT));
+    }
+
+    @Suppress
+    @MediumTest
+    public void testCaCertSettings() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
+
+        BySelector caCertSettingsBySelector =
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_CACERT_RES_ID).clazz(SPINNER_CLASS);
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, caCertSettingsBySelector);
+        assertEquals(CACERT_MENU_PLEASE_SELECT_TEXT, mDevice.wait(Until
+                .findObject(caCertSettingsBySelector), TIMEOUT).getChildren().get(0).getText());
+        mDevice.wait(Until.findObject(caCertSettingsBySelector), TIMEOUT).click();
+        Thread.sleep(SLEEP_TIME);
+
+        // Verify CA certificate spinner options.
+        assertNotNull(mDevice.wait(Until.findObject(
+                By.text(CACERT_MENU_PLEASE_SELECT_TEXT)), TIMEOUT));
+        assertNotNull(mDevice.wait(Until.findObject(
+                By.text(CACERT_MENU_USE_SYSTEM_CERTS_TEXT)), TIMEOUT));
+        assertNotNull(mDevice.wait(Until.findObject(
+                By.text(CACERT_MENU_DO_NOT_VALIDATE_TEXT)), TIMEOUT));
+
+        // Verify that a domain field and warning appear when the user selects the
+        // "Use system certificates" option.
+        mDevice.wait(Until.findObject(By.text(CACERT_MENU_USE_SYSTEM_CERTS_TEXT)), TIMEOUT).click();
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_DOMAIN_LAYOUT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_NO_DOMAIN_WARNING_RES_ID));
+
+        // Verify that a warning appears when the user chooses the "Do Not Validate" option.
+        mDevice.wait(Until.findObject(caCertSettingsBySelector), TIMEOUT).click();
+        mDevice.wait(Until.findObject(By.text(CACERT_MENU_DO_NOT_VALIDATE_TEXT)), TIMEOUT).click();
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_NO_CACERT_WARNING_RES_ID));
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetwork_NoSecurity() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_NONE_TEXT);
+
+        // Entering an SSID is enough to enable the submit button. // TODO THIS GUY
+        enterSSID(TEST_SSID);
+        assertTrue(mDevice.wait(Until
+                .findObject(By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetwork_WEP() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_WEP_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        // Verify that WEP fields appear.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SHOW_PASSWORD_LAYOUT_RES_ID));
+
+        // Entering an SSID alone does not enable the submit button.
+        enterSSID(TEST_SSID);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        // Submit button is only enabled after a password is entered.
+        enterPassword(TEST_PW_GE_8_CHAR);
+        assertTrue(mDevice.wait(Until
+                .findObject(By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetwork_PSK() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_PSK_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        // Verify that PSK fields appear.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SHOW_PASSWORD_LAYOUT_RES_ID));
+
+        // Entering an SSID alone does not enable the submit button.
+        enterSSID(TEST_SSID);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        // Entering an password that is too short does not enable submit button.
+        enterPassword(TEST_PW_LT_8_CHAR);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        // Submit button is only enabled after a password of valid length is entered.
+        enterPassword(TEST_PW_GE_8_CHAR);
+        assertTrue(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetwork_EAP_PEAP() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        selectEAPMethod(EAP_METHOD_PEAP_TEXT);
+
+        // Verify that EAP-PEAP fields appear.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PHASE2_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_CACERT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_IDENTITY_LAYOUT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_ANONYMOUS_LAYOUT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SHOW_PASSWORD_LAYOUT_RES_ID));
+
+        // Entering an SSID alone does not enable the submit button.
+        enterSSID(TEST_SSID);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        verifyCaCertificateSubmitConditions();
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetwork_EAP_TLS() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        selectEAPMethod(EAP_METHOD_TLS_TEXT);
+
+        // Verify that EAP-TLS fields appear.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_CACERT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_USERCERT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_IDENTITY_LAYOUT_RES_ID));
+
+        // Entering an SSID alone does not enable the submit button.
+        enterSSID(TEST_SSID);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        // Selecting the User certificate "Do not provide" option alone does not enable the submit
+        // button.
+        selectUserCertificateOption(USERCERT_MENU_DO_NOT_PROVIDE_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        verifyCaCertificateSubmitConditions();
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetwork_EAP_TTLS() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        selectEAPMethod(EAP_METHOD_TTLS_TEXT);
+
+        // Verify that EAP-TLS fields appear.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PHASE2_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_CACERT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_IDENTITY_LAYOUT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_ANONYMOUS_LAYOUT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID));
+
+        // Entering an SSID alone does not enable the submit button.
+        enterSSID(TEST_SSID);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        verifyCaCertificateSubmitConditions();
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetwork_EAP_PWD() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        selectEAPMethod(EAP_METHOD_PWD_TEXT);
+
+        // Verify that EAP-TLS fields appear.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_IDENTITY_LAYOUT_RES_ID));
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID));
+
+        // Entering an SSID alone enables the submit button.
+        enterSSID(TEST_SSID);
+        assertTrue(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetwork_EAP_SIM() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        selectEAPMethod(EAP_METHOD_SIM_TEXT);
+
+        // Entering an SSID alone enables the submit button.
+        enterSSID(TEST_SSID);
+        assertTrue(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetwork_EAP_AKA() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        selectEAPMethod(EAP_METHOD_AKA_TEXT);
+
+        // Entering an SSID alone enables the submit button.
+        enterSSID(TEST_SSID);
+        assertTrue(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+    }
+
+    @Suppress
+    @MediumTest
+    public void testAddNetwork_EAP_AKA_PRIME() throws Exception {
+        loadAddNetworkMenu();
+        selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        selectEAPMethod(EAP_METHOD_AKA_PRIME_TEXT);
+
+        // Entering an SSID alone enables the submit button.
+        enterSSID(TEST_SSID);
+        assertTrue(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+    }
+
+    private void verifyKeepWiFiOnDuringSleep(String settingToBeVerified, int settingValue)
+            throws Exception {
+        loadWiFiConfigureMenu();
+        mDevice.wait(Until.findObject(By.text("Keep Wi‑Fi on during sleep")), TIMEOUT)
+                .click();
+        mDevice.wait(Until.findObject(By.clazz("android.widget.CheckedTextView")
+                .text(settingToBeVerified)), TIMEOUT).click();
+        Thread.sleep(SLEEP_TIME);
+        int keepWiFiOnSetting =
+                Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
+                Settings.Global.WIFI_SLEEP_POLICY);
+        assertEquals(settingValue, keepWiFiOnSetting);
+    }
+
+    private void verifyNetworkNotificationsOnOrOff(boolean verifyOn)
+            throws Exception {
+        // Enable network recommendations to enable the toggle switch for Network
+        // notifications
+        Settings.Global.putString(getInstrumentation().getContext().getContentResolver(),
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, "1");
+        if (verifyOn) {
+            Settings.Global.putString(getInstrumentation().getContext().getContentResolver(),
+                    Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, "0");
+        }
+        else {
+            Settings.Global.putString(getInstrumentation().getContext().getContentResolver(),
+                    Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, "1");
+        }
+        loadWiFiConfigureMenu();
+        mDevice.wait(Until.findObject(By.text("Open network notification")), TIMEOUT)
+                .click();
+        Thread.sleep(SLEEP_TIME);
+        String wifiNotificationValue =
+                Settings.Global.getString(getInstrumentation().getContext().getContentResolver(),
+                Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
+        if (verifyOn) {
+            assertEquals("1", wifiNotificationValue);
+        }
+        else {
+            assertEquals("0", wifiNotificationValue);
+        }
+    }
+
+    private void verifyWiFiOnOrOff(boolean verifyOn) throws Exception {
+         String switchText = "On";
+         if (verifyOn) {
+             switchText = "Off";
+         }
+         loadWiFiSettingsPage(!verifyOn);
+         mDevice.wait(Until
+                 .findObject(By.res(SETTINGS_PACKAGE, "switch_bar").text(switchText)), TIMEOUT)
+                 .click();
+         Thread.sleep(SLEEP_TIME);
+         String wifiValue =
+                 Settings.Global.getString(getInstrumentation().getContext().getContentResolver(),
+                 Settings.Global.WIFI_ON);
+         if (verifyOn) {
+             // 1 is Enabled, 2 is Enabled while airplane mode is ON.
+             assertTrue(wifiValue.equals("1") || wifiValue.equals("2"));
+         }
+         else {
+             assertEquals("0", wifiValue);
+         }
+    }
+
+    private void verifyCaCertificateSubmitConditions() throws Exception {
+        // Selecting the CA certificate "Do not validate" option enables the submit button.
+        selectCaCertificateOption(CACERT_MENU_DO_NOT_VALIDATE_TEXT);
+        assertTrue(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        // However, selecting the CA certificate "Use system certificates option" is not enough to
+        // enable the submit button.
+        selectCaCertificateOption(CACERT_MENU_USE_SYSTEM_CERTS_TEXT);
+        assertFalse(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+
+        // Submit button is only enabled after a domain is entered as well.
+        enterDomain(TEST_DOMAIN);
+        assertTrue(mDevice.wait(Until.findObject(
+                By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
+    }
+
+    private void loadWiFiSettingsPage(boolean wifiEnabled) throws Exception {
+        WifiManager wifiManager = (WifiManager)getInstrumentation().getContext()
+                .getSystemService(Context.WIFI_SERVICE);
+        wifiManager.setWifiEnabled(wifiEnabled);
+        SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
+                Settings.ACTION_WIFI_SETTINGS);
+    }
+
+    private void loadWiFiConfigureMenu() throws Exception {
+        loadWiFiSettingsPage(false);
+        Thread.sleep(TIMEOUT);
+        mDevice.wait(Until.findObject(By.text(CONFIGURE_WIFI_PREFERENCE_TEXT)), TIMEOUT).click();
+        mDevice.wait(Until.findObject(
+                By.text(CONFIGURE_WIFI_ADVANCED_PREFERENCE_TEXT)), TIMEOUT).click();
+    }
+
+    private void loadAddNetworkMenu() throws Exception {
+        loadWiFiSettingsPage(true);
+        for (int attempts = 0; attempts < MAX_ADD_NETWORK_BUTTON_ATTEMPTS; ++attempts) {
+            try {
+                findOrScrollToObject(By.scrollable(true), By.text(ADD_NETWORK_PREFERENCE_TEXT))
+                        .click();
+            } catch (StaleObjectException e) {
+                // The network list might have been updated between when the Add network button was
+                // found, and when it UI automator attempted to click on it. Retry.
+                continue;
+            }
+            // If we get here, we successfully clicked on the Add network button, so we are done.
+            Thread.sleep(SLEEP_TIME*5);
+            return;
+        }
+
+        fail("Failed to load Add Network Menu after " + MAX_ADD_NETWORK_BUTTON_ATTEMPTS
+                + " retries");
+    }
+
+    private void selectSecurityOption(String securityOption) throws Exception {
+        // We might not need to scroll to the security options if not enough add network menu
+        // options are visible.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SECURITY_OPTION_RES_ID)
+                .clazz(SPINNER_CLASS)).click();
+        Thread.sleep(SLEEP_TIME);
+        mDevice.wait(Until.findObject(By.text(securityOption)), TIMEOUT).click();
+    }
+
+    private void selectEAPMethod(String eapMethod) throws Exception {
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_EAP_METHOD_RES_ID).clazz(SPINNER_CLASS))
+                .click();
+        Thread.sleep(SLEEP_TIME);
+        findOrScrollToObject(SPINNER_OPTIONS_SCROLLABLE_BY_SELECTOR, By.text(eapMethod)).click();
+    }
+
+    private void selectUserCertificateOption(String userCertificateOption) throws Exception {
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_USERCERT_RES_ID).clazz(SPINNER_CLASS))
+                .click();
+        mDevice.wait(Until.findObject(By.text(userCertificateOption)), TIMEOUT).click();
+    }
+
+    private void selectCaCertificateOption(String caCertificateOption) throws Exception {
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_CACERT_RES_ID).clazz(SPINNER_CLASS))
+                .click();
+        mDevice.wait(Until.findObject(By.text(caCertificateOption)), TIMEOUT).click();
+    }
+
+    private void enterSSID(String ssid) throws Exception {
+        // We might not need to scroll to the SSID option if not enough add network menu options
+        // are visible.
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SSID_RES_ID).clazz(EDIT_TEXT_CLASS))
+                .setText(ssid);
+    }
+
+    private void enterPassword(String password) throws Exception {
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_RES_ID).clazz(EDIT_TEXT_CLASS))
+                .setText(password);
+    }
+
+    private void enterDomain(String domain) throws Exception {
+        findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
+                By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_DOMAIN_RES_ID)).setText(domain);
+    }
+
+    // Use this if the UI object might or might not need to be scrolled to.
+    private UiObject2 findOrScrollToObject(BySelector scrollableSelector, BySelector objectSelector)
+            throws Exception {
+        UiObject2 object = mDevice.wait(Until.findObject(objectSelector), TIMEOUT);
+        if (object == null) {
+            object = scrollToObject(scrollableSelector, objectSelector);
+        }
+        return object;
+    }
+
+    private UiObject2 scrollToObject(BySelector scrollableSelector, BySelector objectSelector)
+            throws Exception {
+        UiObject2 scrollable = mDevice.wait(Until.findObject(scrollableSelector), TIMEOUT);
+        if (scrollable == null) {
+            fail("Could not find scrollable UI object identified by " + scrollableSelector);
+        }
+        UiObject2 found = null;
+        // Scroll all the way up first, then all the way down.
+        while (true) {
+            // Optimization: terminate if we find the object while scrolling up to reset, so
+            // we save the time spent scrolling down again.
+            boolean canScrollAgain = scrollable.scroll(Direction.UP, SCROLL_UP_PERCENT,
+                    SCROLL_SPEED);
+            found = mDevice.findObject(objectSelector);
+            if (found != null) return found;
+            if (!canScrollAgain) break;
+        }
+        for (int attempts = 0; found == null && attempts < MAX_SCROLL_ATTEMPTS; ++attempts) {
+            // Return value of UiObject2.scroll() is not reliable, so do not use it in loop
+            // condition, in case it causes this loop to terminate prematurely.
+            scrollable.scroll(Direction.DOWN, SCROLL_DOWN_PERCENT, SCROLL_SPEED);
+            found = mDevice.findObject(objectSelector);
+        }
+        if (found == null) {
+            fail("Could not scroll to UI object identified by " + objectSelector);
+        }
+        return found;
+    }
+}
diff --git a/tests/uitests/src/com/android/settings/ui/testutils/SettingsTestUtils.java b/tests/uitests/src/com/android/settings/ui/testutils/SettingsTestUtils.java
new file mode 100644
index 0000000..9b1be14
--- /dev/null
+++ b/tests/uitests/src/com/android/settings/ui/testutils/SettingsTestUtils.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 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.settings.ui.testutils;
+
+import static org.junit.Assert.assertNotNull;
+
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+
+public class SettingsTestUtils {
+
+    public static final String SETTINGS_PACKAGE = "com.android.settings";
+    public static final int TIMEOUT = 2000;
+
+    private void scrollToTop(UiDevice device) throws Exception {
+        int count = 5;
+        UiObject2 view = null;
+        while (count >= 0) {
+            view = device.wait(
+                    Until.findObject(By.res(SETTINGS_PACKAGE, "main_content")),
+                    TIMEOUT);
+            view.scroll(Direction.UP, 1.0f);
+            count--;
+        }
+    }
+
+    public static void assertTitleMatch(UiDevice device, String title) {
+        int maxAttempt = 5;
+        UiObject2 item = null;
+        UiObject2 view = null;
+        while (maxAttempt-- > 0) {
+            item = device.wait(Until.findObject(By.res("android:id/title").text(title)), TIMEOUT);
+            if (item == null) {
+                view = device.wait(
+                        Until.findObject(By.res(SETTINGS_PACKAGE, "main_content")),
+                        TIMEOUT);
+                view.scroll(Direction.DOWN, 1.0f);
+            } else {
+                return;
+            }
+        }
+        assertNotNull(String.format("%s in Setting has not been loaded correctly", title), item);
+    }
+}