fix: 引入Settings的Module

This commit is contained in:
2024-12-10 14:57:24 +08:00
parent ad8fc8731d
commit df105485bd
6934 changed files with 896168 additions and 2 deletions

View File

@@ -0,0 +1,56 @@
// 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 {
default_team: "trendy_team_android_settings_app",
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "packages_apps_Settings_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["packages_apps_Settings_license"],
}
android_test {
name: "SettingsUITests",
platform_apis: true,
certificate: "platform",
test_suites: ["device-tests"],
srcs: [
"src/**/*.java",
"src/**/*.kt",
],
libs: [
"android.test.runner",
"android.test.base",
],
static_libs: [
"androidx.test.ext.junit",
"androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
"app-helpers-core",
"launcher-helper-lib",
"metrics-helper-lib",
"platform-test-annotations",
"settings-helper",
"sysui-helper",
"timeresult-helper-lib",
"truth",
"flag-junit",
],
//sdk_version: "current",
}

View File

@@ -0,0 +1,39 @@
<?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"
android:sharedUserId="android.uid.systemui">
<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.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.READ_LOGS" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_SEARCH_INDEXABLES"/>
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.settings.ui"
android:label="Android Settings Functional UI Tests" />
</manifest>

View File

@@ -0,0 +1,30 @@
<?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.">
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="apct-instrumentation" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="SettingsUITests.apk" />
</target_preparer>
<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="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
</configuration>

View File

@@ -0,0 +1 @@
include /src/com/android/settings/biometrics/OWNERS

View File

@@ -0,0 +1,825 @@
/*
* Copyright (C) 2023 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.biometrics2.ui.view
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager.FEATURE_FINGERPRINT
import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback
import android.os.UserHandle
import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.internal.widget.LockPatternChecker
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockscreenCredential
import com.android.internal.widget.VerifyCredentialResponse
import com.android.settings.biometrics2.utils.LockScreenUtil
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Assume
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import java.io.IOException
@Ignore
@RunWith(AndroidJUnit4::class)
class FingerprintEnrollmentActivityTest {
private val context: Context by lazy {
InstrumentationRegistry.getInstrumentation().context
}
private val fingerprintManager: FingerprintManager by lazy {
context.getSystemService(FingerprintManager::class.java)!!
}
private var fingerprintPropCallbackLaunched = false
private var canAssumeUdfps = false
private var canAssumeSfps = false
private var enrollingPageTitle: String = ""
private var runAsLandscape = false
private val device: UiDevice by lazy {
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
}
@Before
@Throws(InterruptedException::class)
fun setUp() {
// Stop every test if it is not a fingerprint device
Assume.assumeTrue(context.packageManager.hasSystemFeature(FEATURE_FINGERPRINT))
fingerprintPropCallbackLaunched = false
fingerprintManager.addAuthenticatorsRegisteredCallback(
object : IFingerprintAuthenticatorsRegisteredCallback.Stub() {
override fun onAllAuthenticatorsRegistered(
list: List<FingerprintSensorPropertiesInternal>
) {
fingerprintPropCallbackLaunched = true
assertThat(list).isNotNull()
assertThat(list).isNotEmpty()
val prop = list[0]
canAssumeUdfps = prop.isAnyUdfpsType
canAssumeSfps = prop.isAnySidefpsType
enrollingPageTitle = if (canAssumeUdfps) {
UDFPS_ENROLLING_TITLE
} else if (canAssumeSfps) {
SFPS_ENROLLING_TITLE
} else {
RFPS_ENROLLING_TITLE
}
}
})
var i: Long = 0
while (i < IDLE_TIMEOUT && !fingerprintPropCallbackLaunched) {
Thread.sleep(100L)
i += 100L
}
assertThat(fingerprintPropCallbackLaunched).isTrue()
device.pressHome()
// Stop settings before performing test
try {
device.executeShellCommand("am force-stop $SETTINGS_PACKAGE_NAME")
} catch (e: IOException) {
Log.e(TAG, "Fail to stop settings app", e)
}
}
@After
@Throws(Exception::class)
fun tearDown() {
runAsLandscape = false
setDeviceOrientation()
LockScreenUtil.resetLockscreen(TEST_PIN)
device.pressHome()
}
@Test
fun testIntroChooseLock() {
setDeviceOrientation()
val intent = newActivityIntent(false)
context.startActivity(intent)
assertThat(
device.wait(
Until.hasObject(By.text("Choose your backup screen lock method")),
IDLE_TIMEOUT
)
).isTrue()
}
@Test
fun testIntroChooseLock_runAslandscape() {
runAsLandscape = true
testIntroChooseLock()
}
private fun verifyIntroPage() {
device.waitForIdle()
run {
var i: Long = 0
while (i < IDLE_TIMEOUT) {
if (device.wait(Until.hasObject(By.text("More")), 50L)) {
break
} else if (device.wait(Until.hasObject(By.text("I agree")), 50L)) {
break
}
i += 100L
}
}
// Click more btn at most twice and the introduction should stay in the last page
var moreBtn: UiObject2? = null
var i = 0
val more = if (runAsLandscape) 5 else 2
while (i < more && device.findObject(By.text("More")).also { moreBtn = it } != null) {
moreBtn!!.click()
device.waitForIdle()
device.wait(Until.hasObject(By.text("More")), IDLE_TIMEOUT)
++i
}
assertThat(device.wait(Until.hasObject(By.text("No thanks")), IDLE_TIMEOUT)).isTrue()
assertThat(device.wait(Until.hasObject(By.text("I agree")), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testIntroWithGkPwHandle_withUdfps_clickStart() {
Assume.assumeTrue(canAssumeUdfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchIntroWithGkPwHandle(false)
// Intro page
verifyIntroPage()
val agreeBtn = device.findObject(By.text("I agree"))
assertThat(agreeBtn).isNotNull()
agreeBtn.click()
// FindUdfps page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(
By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie")
)
assertThat(lottie).isNotNull()
assertThat(lottie.isClickable).isTrue()
val startBtn = device.findObject(By.text("Start"))
assertThat(startBtn.isClickable).isTrue()
startBtn.click()
// Enrolling page
assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testIntroWithGkPwHandle_withUdfps_clickStart_runAslandscape() {
runAsLandscape = true
testIntroWithGkPwHandle_withUdfps_clickStart()
}
@Test
fun testIntroWithGkPwHandle_withUdfps_clickLottie() {
Assume.assumeTrue(canAssumeUdfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchIntroWithGkPwHandle(false)
// Intro page
verifyIntroPage()
val agreeBtn = device.findObject(By.text("I agree"))
assertThat(agreeBtn).isNotNull()
agreeBtn.click()
// FindUdfps page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie"))
assertThat(lottie).isNotNull()
assertThat(lottie.isClickable).isTrue()
val startBtn = device.findObject(By.text("Start"))
assertThat(startBtn.isClickable).isTrue()
lottie.click()
// Enrolling page
assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testIntroWithGkPwHandle_withUdfps_clickLottie_runAslandscape() {
runAsLandscape = true
testIntroWithGkPwHandle_withUdfps_clickLottie()
}
@Test
fun testIntroWithGkPwHandle_withSfps() {
Assume.assumeTrue(canAssumeSfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchIntroWithGkPwHandle(false)
// Intro page
verifyIntroPage()
val agreeBtn = device.findObject(By.text("I agree"))
assertThat(agreeBtn).isNotNull()
agreeBtn.click()
// FindSfps page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(
By.res(SETTINGS_PACKAGE_NAME,"illustration_lottie")
)
assertThat(lottie).isNotNull()
// We don't have view which can be clicked to run to next page, stop at here.
}
@Test
fun testIntroWithGkPwHandle_withSfps_runAslandscape() {
runAsLandscape = true
testIntroWithGkPwHandle_withSfps()
}
@Test
fun testIntroWithGkPwHandle_withRfps() {
Assume.assumeFalse(canAssumeUdfps || canAssumeSfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchIntroWithGkPwHandle(false)
// Intro page
verifyIntroPage()
val agreeBtn = device.findObject(By.text("I agree"))
assertThat(agreeBtn).isNotNull()
agreeBtn.click()
// FindRfps page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(
By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie")
)
if (lottie == null) {
// FindSfps page shall have an animation view if no lottie view
assertThat(
device.findObject(
By.res(SETTINGS_PACKAGE_NAME, "fingerprint_sensor_location_animation")
)
).isNotNull()
}
}
@Test
fun testIntroWithGkPwHandle_withRfps_runAslandscape() {
runAsLandscape = true
testIntroWithGkPwHandle_withRfps()
}
@Test
fun testIntroWithGkPwHandle_clickNoThanksInIntroPage() {
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchIntroWithGkPwHandle(false)
// Intro page
verifyIntroPage()
val noThanksBtn = device.findObject(By.text("No thanks"))
assertThat(noThanksBtn).isNotNull()
noThanksBtn.click()
// Back to home
device.waitForWindowUpdate(SETTINGS_PACKAGE_NAME, IDLE_TIMEOUT)
assertThat(device.findObject(By.text("No thanks"))).isNull()
}
@Test
fun testIntroWithGkPwHandle_clickNoThanksInIntroPage_runAslandscape() {
runAsLandscape = true
testIntroWithGkPwHandle_clickNoThanksInIntroPage()
}
@Test
fun testIntroWithGkPwHandle_clickSkipInFindSensor() {
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchIntroWithGkPwHandle(false)
// Intro page
verifyIntroPage()
val agreeBtn = device.findObject(By.text("I agree"))
assertThat(agreeBtn).isNotNull()
agreeBtn.click()
// FindSensor page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val doItLaterBtn = device.findObject(By.text(DO_IT_LATER))
assertThat(doItLaterBtn).isNotNull()
assertThat(doItLaterBtn.isClickable).isTrue()
doItLaterBtn.click()
// Back to home
device.waitForWindowUpdate(SETTINGS_PACKAGE_NAME, IDLE_TIMEOUT)
assertThat(device.findObject(By.text(DO_IT_LATER))).isNull()
}
@Test
fun testIntroWithGkPwHandle_clickSkipInFindSensor_runAslandscape() {
runAsLandscape = true
testIntroWithGkPwHandle_clickSkipInFindSensor()
}
@Test
fun testIntroWithGkPwHandle_clickSkipAnywayInFindFpsDialog_whenIsSuw() {
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchIntroWithGkPwHandle(true)
// Intro page
verifyIntroPage()
val agreeBtn = device.findObject(By.text("I agree"))
assertThat(agreeBtn).isNotNull()
agreeBtn.click()
// FindSensor page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val doItLaterBtn = device.findObject(By.text(DO_IT_LATER))
assertThat(doItLaterBtn).isNotNull()
assertThat(doItLaterBtn.isClickable).isTrue()
doItLaterBtn.click()
// SkipSetupFindFpsDialog
assertThat(device.wait(Until.hasObject(By.text("Skip fingerprint?")), IDLE_TIMEOUT)).isTrue()
val skipAnywayBtn = device.findObject(By.text("Skip anyway"))
assertThat(skipAnywayBtn).isNotNull()
assertThat(skipAnywayBtn.isClickable).isTrue()
skipAnywayBtn.click()
// Back to home
device.waitForWindowUpdate(SETTINGS_PACKAGE_NAME, IDLE_TIMEOUT)
assertThat(device.findObject(By.text("Skip anyway"))).isNull()
assertThat(device.findObject(By.text(DO_IT_LATER))).isNull()
}
@Test
fun testIntroWithGkPwHandle_clickSkipAnywayInFindFpsDialog_whenIsSuw_runAslandscape() {
runAsLandscape = true
testIntroWithGkPwHandle_clickSkipAnywayInFindFpsDialog_whenIsSuw()
}
@Test
fun testIntroWithGkPwHandle_clickGoBackInFindFpsDialog_whenIsSuw() {
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchIntroWithGkPwHandle(true)
// Intro page
verifyIntroPage()
val agreeBtn = device.findObject(By.text("I agree"))
assertThat(agreeBtn).isNotNull()
agreeBtn.click()
// FindSensor page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val doItLaterBtn = device.findObject(By.text(DO_IT_LATER))
assertThat(doItLaterBtn).isNotNull()
assertThat(doItLaterBtn.isClickable).isTrue()
doItLaterBtn.click()
// SkipSetupFindFpsDialog
assertThat(device.wait(Until.hasObject(By.text("Skip fingerprint?")), IDLE_TIMEOUT)).isTrue()
val goBackBtn = device.findObject(By.text("Go back"))
assertThat(goBackBtn).isNotNull()
assertThat(goBackBtn.isClickable).isTrue()
goBackBtn.click()
// FindSensor page again
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testIntroWithGkPwHandle_clickGoBackInFindFpsDialog_whenIsSuw_runAslandscape() {
runAsLandscape = true
testIntroWithGkPwHandle_clickGoBackInFindFpsDialog_whenIsSuw()
}
@Test
fun testIntroCheckPin() {
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
val intent = newActivityIntent(false)
context.startActivity(intent)
assertThat(
device.wait(
Until.hasObject(By.text("Enter your device PIN to continue")),
IDLE_TIMEOUT
)
).isTrue()
}
@Test
fun testEnrollingWithGkPwHandle() {
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchEnrollingWithGkPwHandle()
// Enrolling screen
device.waitForIdle()
assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testEnrollingWithGkPwHandle_runAslandscape() {
runAsLandscape = true
testEnrollingWithGkPwHandle()
}
@Test
fun testEnrollingIconTouchDialog_withSfps() {
Assume.assumeTrue(canAssumeSfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchEnrollingWithGkPwHandle()
// Enrolling screen
device.waitForIdle()
assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(
By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie")
)
assertThat(lottie).isNotNull()
lottie.click()
lottie.click()
lottie.click()
// IconTouchDialog
device.waitForIdle()
assertThat(
device.wait(
Until.hasObject(By.text("Touch the sensor instead")),
IDLE_TIMEOUT
)
)
.isTrue()
val okButton = device.findObject(By.text("OK"))
assertThat(okButton).isNotNull()
okButton.click()
// Enrolling screen again
device.waitForIdle()
assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testEnrollingIconTouchDialog_withSfps_runAslandscape() {
runAsLandscape = true
testEnrollingIconTouchDialog_withSfps()
}
@Test
fun testEnrollingIconTouchDialog_withRfps() {
Assume.assumeFalse(canAssumeUdfps || canAssumeSfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchEnrollingWithGkPwHandle()
// Enrolling screen
device.waitForIdle()
assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(
By.res(SETTINGS_PACKAGE_NAME, "fingerprint_progress_bar")
)
assertThat(lottie).isNotNull()
lottie.click()
lottie.click()
lottie.click()
// IconTouchDialog
device.waitForIdle()
assertThat(
device.wait(
Until.hasObject(By.text("Whoops, that\u2019s not the sensor")),
IDLE_TIMEOUT
)
).isTrue()
val okButton = device.findObject(By.text("OK"))
assertThat(okButton).isNotNull()
okButton.click()
// Enrolling screen again
device.waitForIdle()
assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testEnrollingIconTouchDialog_withRfps_runAslandscape() {
runAsLandscape = true
testEnrollingIconTouchDialog_withRfps()
}
@Test
fun testFindUdfpsWithGkPwHandle_clickStart() {
Assume.assumeTrue(canAssumeUdfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchFindSensorWithGkPwHandle()
// FindUdfps page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(
By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie")
)
assertThat(lottie).isNotNull()
assertThat(lottie.isClickable).isTrue()
val startBtn = device.findObject(By.text("Start"))
assertThat(startBtn.isClickable).isTrue()
startBtn.click()
// Enrolling page
assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testFindUdfpsWithGkPwHandle_clickStart_runAslandscape() {
runAsLandscape = true
testFindUdfpsWithGkPwHandle_clickStart()
}
@Test
fun testFindUdfpsLandscapeWithGkPwHandle_clickStartThenBack() {
Assume.assumeTrue(canAssumeUdfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchFindSensorWithGkPwHandle()
// FindUdfps page (portrait)
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
// rotate device
if (runAsLandscape) {
device.setOrientationPortrait()
} else {
device.setOrientationLandscape()
}
device.waitForIdle()
// FindUdfps page (landscape)
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(
By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie")
)
assertThat(lottie).isNotNull()
assertThat(lottie.isClickable).isTrue()
val startBtn = device.findObject(By.text("Start"))
assertThat(startBtn.isClickable).isTrue()
startBtn.click()
// Enrolling page
assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue()
// Press back
device.pressBack()
device.waitForIdle()
// FindUdfps page (landscape-again)
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testFindUdfpsLandscapeWithGkPwHandle_clickStartThenBack_runAslandscape() {
runAsLandscape = true
testFindUdfpsLandscapeWithGkPwHandle_clickStartThenBack()
}
@Test
fun testFindUdfpsWithGkPwHandle_clickLottie() {
Assume.assumeTrue(canAssumeUdfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchFindSensorWithGkPwHandle()
// FindUdfps page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(
By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie")
)
assertThat(lottie).isNotNull()
assertThat(lottie.isClickable).isTrue()
val startBtn = device.findObject(By.text("Start"))
assertThat(startBtn.isClickable).isTrue()
lottie.click()
// Enrolling page
assertThat(device.wait(Until.hasObject(By.text(enrollingPageTitle)), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testFindUdfpsWithGkPwHandle_clickLottie_runAslandscape() {
runAsLandscape = true
testFindUdfpsWithGkPwHandle_clickLottie()
}
@Test
fun testFindSfpsWithGkPwHandle() {
Assume.assumeTrue(canAssumeSfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchFindSensorWithGkPwHandle()
// FindSfps page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(
By.res(SETTINGS_PACKAGE_NAME, "illustration_lottie")
)
assertThat(lottie).isNotNull()
// We don't have view which can be clicked to run to next page, stop at here.
}
@Test
fun testFindSfpsWithGkPwHandle_runAslandscape() {
runAsLandscape = true
testFindSfpsWithGkPwHandle()
}
@Test
fun testFindRfpsWithGkPwHandle() {
Assume.assumeFalse(canAssumeUdfps || canAssumeSfps)
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchFindSensorWithGkPwHandle()
// FindRfps page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val lottie = device.findObject(
By.res(
SETTINGS_PACKAGE_NAME,
"illustration_lottie"
)
)
if (lottie == null) {
// FindSfps page shall have an animation view if no lottie view
assertThat(
device.findObject(
By.res(
SETTINGS_PACKAGE_NAME,
"fingerprint_sensor_location_animation"
)
)
).isNotNull()
}
}
@Test
fun testFindRfpsWithGkPwHandle_runAslandscape() {
runAsLandscape = true
testFindRfpsWithGkPwHandle()
}
@Test
fun testFindSensorWithGkPwHandle_clickSkipInFindSensor() {
setDeviceOrientation()
LockScreenUtil.setLockscreen(LockScreenUtil.LockscreenType.PIN, TEST_PIN, true)
launchFindSensorWithGkPwHandle()
// FindSensor page
assertThat(device.wait(Until.hasObject(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
val doItLaterBtn = device.findObject(By.text(DO_IT_LATER))
assertThat(doItLaterBtn).isNotNull()
assertThat(doItLaterBtn.isClickable).isTrue()
doItLaterBtn.click()
// Back to home
device.waitForWindowUpdate(SETTINGS_PACKAGE_NAME, IDLE_TIMEOUT)
assertThat(device.wait(Until.gone(By.text(DO_IT_LATER)), IDLE_TIMEOUT)).isTrue()
}
@Test
fun testFindSensorWithGkPwHandle_clickSkipInFindSensor_runAslandscape() {
runAsLandscape = true
testFindSensorWithGkPwHandle_clickSkipInFindSensor()
}
private fun launchIntroWithGkPwHandle(isSuw: Boolean) {
val lockPatternUtils = LockPatternUtils(context)
val lockscreenCredential = LockscreenCredential.createPin(TEST_PIN)
val userId = UserHandle.myUserId()
val onVerifyCallback =
LockPatternChecker.OnVerifyCallback { response: VerifyCredentialResponse, _: Int ->
val intent = newActivityIntent(isSuw)
intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, response.gatekeeperPasswordHandle)
context.startActivity(intent)
}
LockPatternChecker.verifyCredential(
lockPatternUtils, lockscreenCredential,
userId, LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE, onVerifyCallback
)
}
private fun launchFindSensorWithGkPwHandle() {
val lockPatternUtils = LockPatternUtils(context)
val lockscreenCredential = LockscreenCredential.createPin(TEST_PIN)
val userId = UserHandle.myUserId()
val onVerifyCallback =
LockPatternChecker.OnVerifyCallback { response: VerifyCredentialResponse, _: Int ->
val intent = newActivityIntent(false)
intent.putExtra(EXTRA_SKIP_INTRO, true)
intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, response.gatekeeperPasswordHandle)
context.startActivity(intent)
}
LockPatternChecker.verifyCredential(
lockPatternUtils, lockscreenCredential,
userId, LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE, onVerifyCallback
)
}
private fun launchEnrollingWithGkPwHandle() {
val lockPatternUtils = LockPatternUtils(context)
val lockscreenCredential = LockscreenCredential.createPin(TEST_PIN)
val userId = UserHandle.myUserId()
val onVerifyCallback =
LockPatternChecker.OnVerifyCallback { response: VerifyCredentialResponse, _: Int ->
val intent = newActivityIntent(false)
intent.putExtra(EXTRA_SKIP_FIND_SENSOR, true)
intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, response.gatekeeperPasswordHandle)
context.startActivity(intent)
}
LockPatternChecker.verifyCredential(
lockPatternUtils, lockscreenCredential,
userId, LockPatternUtils.VERIFY_FLAG_REQUEST_GK_PW_HANDLE, onVerifyCallback
)
}
private fun newActivityIntent(isSuw: Boolean): Intent {
val intent = Intent()
intent.setClassName(
SETTINGS_PACKAGE_NAME,
if (isSuw) SUW_ACTIVITY_CLASS_NAME else ACTIVITY_CLASS_NAME
)
if (isSuw) {
intent.putExtra(EXTRA_IS_SETUP_FLOW, true)
}
intent.putExtra(EXTRA_PAGE_TRANSITION_TYPE, 1)
intent.putExtra(Intent.EXTRA_USER_ID, context.userId)
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK)
return intent
}
private fun setDeviceOrientation() {
if (runAsLandscape) {
device.setOrientationLandscape()
} else {
device.setOrientationPortrait()
}
device.waitForIdle()
}
companion object {
private const val TAG = "FingerprintEnrollmentActivityTest"
const val SETTINGS_PACKAGE_NAME = "com.android.settings"
private const val ACTIVITY_CLASS_NAME =
"com.android.settings.biometrics2.ui.view.FingerprintEnrollmentActivity"
private const val SUW_ACTIVITY_CLASS_NAME = "$ACTIVITY_CLASS_NAME\$SetupActivity"
private const val EXTRA_IS_SETUP_FLOW = "isSetupFlow"
private const val EXTRA_SKIP_INTRO = "skip_intro"
private const val EXTRA_SKIP_FIND_SENSOR = "skip_find_sensor"
private const val EXTRA_PAGE_TRANSITION_TYPE = "page_transition_type"
private const val EXTRA_KEY_GK_PW_HANDLE = "gk_pw_handle"
private const val TEST_PIN = "1234"
private const val DO_IT_LATER = "Do it later"
private const val UDFPS_ENROLLING_TITLE = "Touch & hold the fingerprint sensor"
private const val SFPS_ENROLLING_TITLE =
"Lift, then touch. Move your finger slightly each time."
private const val RFPS_ENROLLING_TITLE = "Lift, then touch again"
private const val IDLE_TIMEOUT = 10000L
}
}

View File

@@ -0,0 +1,183 @@
/*
* Copyright (C) 2022 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.biometrics2.utils;
import static java.lang.String.format;
import android.app.KeyguardManager;
import android.content.Context;
import android.os.SystemClock;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
import org.junit.Assert;
import java.io.IOException;
import java.util.function.Supplier;
public class LockScreenUtil {
private static final String TAG = LockScreenUtil.class.getSimpleName();
private static final int SLEEP_MS = 100;
private static final int WAIT_TIME_MS = 10000;
private static final String SET_PATTERN_COMMAND = "locksettings set-pattern";
private static final String SET_PASSWORD_COMMAND = "locksettings set-password";
private static final String SET_PIN_COMMAND = "locksettings set-pin";
private static final String RESET_LOCKSCREEN_SHELL_COMMAND = "locksettings clear --old";
/**
* Different way to set the Lockscreen for Android device. Currently we only support PIN,
* PATTERN and PASSWORD
*
* @param lockscreenType it enum with list of supported lockscreen type
* @param lockscreenCode code[PIN or PATTERN or PASSWORD] which needs to be set.
* @param expectedResult expected result after setting the lockscreen because for lock type
* Swipe and None Keygaurd#isKeyguardSecure remain unlocked i.e. false
*/
public static void setLockscreen(LockscreenType lockscreenType, String lockscreenCode,
boolean expectedResult) {
Log.d(TAG, format("Setting Lockscreen [%s(%s)]", lockscreenType, lockscreenCode));
switch (lockscreenType) {
case PIN:
executeShellCommand(format("%s %s", SET_PIN_COMMAND, lockscreenCode));
break;
case PASSWORD:
executeShellCommand(format("%s %s", SET_PASSWORD_COMMAND, lockscreenCode));
break;
case PATTERN:
executeShellCommand(format("%s %s", SET_PATTERN_COMMAND, lockscreenCode));
break;
default:
throw new AssertionError("Non-supported Lockscreen Type: " + lockscreenType);
}
assertKeyguardSecure(expectedResult);
}
/**
* Resets the give lockscreen.
*
* @param lockscreenCode old code which is currently set.
*/
public static void resetLockscreen(String lockscreenCode) {
Log.d(TAG, String.format("Re-Setting Lockscreen %s", lockscreenCode));
executeShellCommand(
format("%s %s", RESET_LOCKSCREEN_SHELL_COMMAND, lockscreenCode));
assertKeyguardSecure(/* expectedSecure= */ false);
}
/**
* This method help you execute you shell command.
* Example: adb shell pm list packages -f
* Here you just need to provide executeShellCommand("pm list packages -f")
*
* @param command command need to executed.
*/
private static void executeShellCommand(String command) {
Log.d(TAG, format("Executing Shell Command: %s", command));
try {
getUiDevice().executeShellCommand(command);
} catch (IOException e) {
Log.d(TAG, format("IOException Occurred: %s", e));
}
}
/**
* Enum for different types of Lockscreen, PIN, PATTERN and PASSWORD.
*/
public enum LockscreenType {
PIN,
PASSWORD,
PATTERN
}
private static UiDevice getUiDevice() {
return UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
}
private static void assertKeyguardSecure(boolean expectedSecure) {
waitForCondition(
() -> String.format("Assert that keyguard %s secure, but failed.",
expectedSecure ? "is" : "isn't"),
() -> getKeyguardManager().isKeyguardSecure() == expectedSecure);
}
/**
* Waits for a condition and fails if it doesn't become true within 10 sec.
*
* @param message Supplier of the error message.
* @param condition Condition.
*/
private static void waitForCondition(
Supplier<String> message, Condition condition) {
waitForCondition(message, condition, WAIT_TIME_MS);
}
/**
* Waits for a condition and fails if it doesn't become true within specified time period.
*
* @param message Supplier of the error message.
* @param condition Condition.
* @param timeoutMs Timeout.
*/
private static void waitForCondition(
Supplier<String> message, Condition condition, long timeoutMs) {
final long startTime = SystemClock.uptimeMillis();
while (SystemClock.uptimeMillis() < startTime + timeoutMs) {
try {
if (condition.isTrue()) {
return;
}
} catch (Throwable t) {
throw new RuntimeException(t);
}
SystemClock.sleep(SLEEP_MS);
}
// Check once more before failing.
try {
if (condition.isTrue()) {
return;
}
} catch (Throwable t) {
throw new RuntimeException(t);
}
Assert.fail(message.get());
}
/**
* To get an instance of class that can be used to lock and unlock the keygaurd.
*
* @return an instance of class that can be used to lock and unlock the screen.
*/
private static KeyguardManager getKeyguardManager() {
return (KeyguardManager) InstrumentationRegistry.getContext().getSystemService(
Context.KEYGUARD_SERVICE);
}
/** Supplier of a boolean that can throw an exception. */
private interface Condition {
boolean isTrue() throws Throwable;
}
}

View File

@@ -0,0 +1,53 @@
/*
* Copyright (C) 2023 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.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
/** Verifies basic functionality of the About Phone screen */
@RunWith(AndroidJUnit4::class)
@SmallTest
class AboutPhoneSettingsTests {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_DEVICE_INFO_SETTINGS)
}
@Test
fun testAllMenuEntriesExist() {
device.assertHasTexts(ON_SCREEN_TEXTS)
}
private companion object {
val ON_SCREEN_TEXTS = listOf(
"Device name",
"Legal information",
"Regulatory labels"
)
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2023 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.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertObject
import com.android.settings.ui.testutils.SettingsTestUtils.clickObject
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class AppsSettingsRetainFilterTests {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS)
}
@Test
fun testDisablingSystemAppAndRotateDevice() {
device.clickObject(By.text("Calculator"))
device.clickObject(By.text("Disable"))
device.clickObject(By.text("Disable app")) // Click on "Disable App" on dialog.
device.assertObject(By.text("Enable"))
device.pressBack()
device.clickObject(By.text("All apps"))
device.clickObject(By.text("Disabled apps"))
device.setOrientationLeft()
device.assertObject(By.text("Disabled apps"))
device.setOrientationNatural()
device.assertObject(By.text("Disabled apps"))
device.clickObject(By.text("Calculator"))
device.clickObject(By.text("Enable"))
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2023 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.provider.Settings
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.assertObject
import com.android.settings.ui.testutils.SettingsTestUtils.clickObject
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import com.android.settings.ui.testutils.SettingsTestUtils.waitObject
import org.junit.Before
import org.junit.Test
/** Verifies basic functionality of the About Phone screen */
class AppsSettingsTests {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS)
device.assertObject(By.text("All apps"))
}
@Test
fun testAppSettingsListForCalculator() {
device.clickObject(By.text("Calculator"))
device.waitObject(By.text("Open"))
device.assertHasTexts(ON_SCREEN_TEXTS)
}
@Test
fun testDisablingAndEnablingSystemApp() {
device.clickObject(By.text("Calculator"))
device.clickObject(By.text("Disable"))
device.clickObject(By.text("Disable app")) // Click on "Disable app" on dialog.
device.clickObject(By.text("Enable"))
device.assertObject(By.text("Disable"))
}
private companion object {
val ON_SCREEN_TEXTS = listOf(
"Notifications",
"Permissions",
"Storage & cache",
"Mobile data & WiFi",
"Screen time",
"App battery usage",
"Language",
"Unused app settings",
)
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2023 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 androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class BatterySettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Intent.ACTION_POWER_USAGE_SUMMARY)
}
@Test
fun hasTexts() {
device.assertHasTexts(ON_SCREEN_TEXTS)
}
private companion object {
// Items we really want to always show
val ON_SCREEN_TEXTS = listOf(
"Battery usage",
"Battery Saver",
"Battery percentage",
"Remaining battery life is approximate and can change based on usage"
)
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2023 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.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertObject
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class DataSaverSettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_DATA_SAVER_SETTINGS)
}
@Test
fun hasSwitchBar() {
device.assertObject(By.text("Use Data Saver"))
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2023 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.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class DataUsageSettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_DATA_USAGE_SETTINGS)
}
@Test
fun hasTexts() {
device.assertHasTexts(ON_SCREEN_TEXTS)
}
private companion object {
val ON_SCREEN_TEXTS = listOf(
"0 B",
"Data Saver",
"WiFi data usage",
)
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2023 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.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.clickObject
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@SmallTest
class DevelopmentSettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_DEVICE_INFO_SETTINGS)
device.assertHasTexts(listOf(BUILD_NUMBER))
repeat(7) { // Enable development mode
device.clickObject(By.text(BUILD_NUMBER))
}
device.startMainActivityFromHomeScreen(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)
}
@Test
fun hasTexts() {
device.assertHasTexts(ON_SCREEN_TEXTS)
}
private companion object {
private const val BUILD_NUMBER = "Build number"
val ON_SCREEN_TEXTS = listOf(
"Use developer options",
"Memory",
"Stay awake",
"USB debugging",
"App Compatibility Changes",
)
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2023 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.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class HomepageDisplayTests {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_SETTINGS)
}
@Test
fun hasHomepageItems() {
device.assertHasTexts(HOMEPAGE_ITEMS)
}
private companion object {
val HOMEPAGE_ITEMS = listOf(
"Network & internet",
"Connected devices",
"Apps",
"Notifications",
"Battery",
"Storage",
"Sound & vibration",
"Display",
"Accessibility",
"Security & privacy",
"Location",
"Passwords & accounts",
"System",
)
}
}

View File

@@ -0,0 +1,246 @@
/*
* 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.system.helpers.SettingsHelper;
import android.test.InstrumentationTestCase;
import androidx.test.filters.MediumTest;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
import org.junit.Ignore;
@Ignore
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_ON);
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_ON);
}
@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_ON) {
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_ON ||
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_ON);
}
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);
}
}
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2023 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.Flags
import android.platform.test.annotations.RequiresFlagsDisabled
import android.platform.test.annotations.RequiresFlagsEnabled
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.clickObject
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@SmallTest
class MemorySettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_DEVICE_INFO_SETTINGS)
device.assertHasTexts(listOf(BUILD_NUMBER))
repeat(7) { // Enable development mode
device.clickObject(By.text(BUILD_NUMBER))
}
device.startMainActivityFromHomeScreen(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)
device.clickObject(By.text(MEMORY_PAGE))
}
@Test
@RequiresFlagsDisabled(Flags.FLAG_REMOVE_APP_PROFILER_PSS_COLLECTION)
fun memoryPageIfPssFlagDisabled() {
device.assertHasTexts(ON_SCREEN_TEXTS_DEFAULT)
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_REMOVE_APP_PROFILER_PSS_COLLECTION)
fun memoryPageIfPssFlagEnabled() {
device.assertHasTexts(ON_SCREEN_TEXTS_PSS_PROFILING_DISABLED)
}
private companion object {
private const val BUILD_NUMBER = "Build number"
private const val MEMORY_PAGE = "Memory"
val ON_SCREEN_TEXTS_DEFAULT = listOf(
"Performance",
"Total memory",
"Average used (%)",
"Free",
)
val ON_SCREEN_TEXTS_PSS_PROFILING_DISABLED = listOf(
"Enable memory usage profiling",
)
}
}

View File

@@ -0,0 +1,769 @@
/*
* 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.provider.Settings;
import android.system.helpers.CommandsHelper;
import android.system.helpers.SettingsHelper;
import android.test.InstrumentationTestCase;
import android.util.Log;
import androidx.test.filters.MediumTest;
import androidx.test.filters.Suppress;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.StaleObjectException;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
import org.junit.Ignore;
/**
* Additional tests for Wifi Settings.
*/
@Ignore
public class MoreWirelessSettingsTest2 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 = "WiFi 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();
}
@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 WiFi 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;
}
}

View File

@@ -0,0 +1,127 @@
/*
* 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.system.helpers.SettingsHelper;
import android.test.InstrumentationTestCase;
import androidx.test.filters.MediumTest;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
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.findObject(By.res(SETTINGS_PACKAGE, "main_content"))
.scrollUntil(Direction.DOWN, Until.findObject(By.text("VPN")))
.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);
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2023 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.provider.Settings
import android.telephony.SubscriptionManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import com.google.common.truth.TruthJUnit.assume
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class NetworkOperatorSettingsTest {
private val instrumentation = InstrumentationRegistry.getInstrumentation()
private val device = UiDevice.getInstance(instrumentation)
@Before
fun setUp() {
assume().that(
instrumentation.context.getSystemService(SubscriptionManager::class.java)!!
.availableSubscriptionInfoList
).isNotEmpty()
device.startMainActivityFromHomeScreen(Settings.ACTION_NETWORK_OPERATOR_SETTINGS)
}
@Test
fun hasTexts() {
device.assertHasTexts(ON_SCREEN_TEXTS)
}
private companion object {
val ON_SCREEN_TEXTS = listOf(
"Use SIM",
"0 B",
"Calls preference",
"SMS preference",
"Mobile data",
"Roaming",
"App data usage",
"Data warning & limit",
"Preferred network type",
"Carrier settings version",
"Automatically select network",
"Choose network",
"Access Point Names",
)
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2023 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.nfc.NfcAdapter
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import com.google.common.truth.TruthJUnit.assume
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class NfcSettingsTest {
private val instrumentation = InstrumentationRegistry.getInstrumentation()
private val device = UiDevice.getInstance(instrumentation)
@Before
fun setUp() {
assume().that(NfcAdapter.getDefaultAdapter(instrumentation.context)).isNotNull()
device.startMainActivityFromHomeScreen(Settings.ACTION_NFC_SETTINGS)
}
@Test
fun hasTexts() {
device.assertHasTexts(ON_SCREEN_TEXTS)
}
private companion object {
val ON_SCREEN_TEXTS = listOf(
"Use NFC",
"Require device unlock for NFC",
"Contactless payments",
)
}
}

View File

@@ -0,0 +1,162 @@
/*
* 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.system.helpers.ActivityHelper;
import android.system.helpers.SettingsHelper;
import android.test.InstrumentationTestCase;
import android.util.Log;
import android.widget.ListView;
import androidx.test.filters.MediumTest;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
import org.junit.Ignore;
/** Verifies that you can get to the notification app listing page from the apps & notifications
* page */
@Ignore
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);
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2023 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.Flags
import android.platform.test.annotations.RequiresFlagsEnabled
import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SecuritySettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@get:Rule
public val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_SECURITY_SETTINGS)
}
@Test
fun hasTexts() {
device.assertHasTexts(ON_SCREEN_TEXTS)
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
fun privateSpace_ifFlagON() {
device.assertHasTexts(listOf("Private Space"))
}
private companion object {
// Items we really want to always show
val ON_SCREEN_TEXTS = listOf(
"Device unlock",
"Privacy",
"More security & privacy",
)
}
}

View File

@@ -0,0 +1,320 @@
/*
* 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.os.SystemClock;
import android.provider.Settings;
import android.system.helpers.SettingsHelper;
import android.system.helpers.SettingsHelper.SettingsType;
import android.test.InstrumentationTestCase;
import androidx.test.filters.MediumTest;
import androidx.test.filters.Suppress;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
import org.junit.Ignore;
import java.util.Map;
@Ignore
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 final Map<String, String> ringtoneSounds = Map.of(
"angler", "Dione",
"bullhead", "Dione",
"marlin", "Spaceship",
"sailfish", "Spaceship",
"walleye", "Copycat",
"taimen", "Copycat");
private final Map<String, String> ringtoneCodes = Map.of(
"angler", "38",
"bullhead", "38",
"marlin", "37",
"sailfish", "37",
"walleye", "26",
"taimen", "26");
private final Map<String, String> alarmSounds = Map.of(
"angler", "Awaken",
"bullhead", "Awaken",
"marlin", "Bounce",
"sailfish", "Bounce",
"walleye", "Cuckoo clock",
"taimen", "Cuckoo clock");
private final Map<String, String> alarmCodes = Map.of(
"angler", "6",
"bullhead", "6",
"marlin", "49",
"sailfish", "49",
"walleye", "15",
"taimen", "15");
private final Map<String, String> notificationSounds = Map.of(
"angler", "Ceres",
"bullhead", "Ceres",
"marlin", "Trill",
"sailfish", "Trill",
"walleye", "Pipes",
"taimen", "Pipes");
private final Map<String, String> notificationCodes = Map.of(
"angler", "26",
"bullhead", "26",
"marlin", "57",
"sailfish", "57",
"walleye", "69",
"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));
}
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;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2023 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.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class StorageSettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_INTERNAL_STORAGE_SETTINGS)
}
@Test
fun hasTexts() {
device.assertHasTexts(ON_SCREEN_TEXTS)
}
private companion object {
val ON_SCREEN_TEXTS = listOf(
"System",
"Documents & other",
"Games",
"Apps",
"Audio",
"Videos",
"Images",
)
}
}

View File

@@ -0,0 +1,194 @@
/*
* 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.SystemClock;
import android.os.storage.DiskInfo;
import android.os.storage.VolumeInfo;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.Until;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.util.regex.Pattern;
/**
* Verify storage wizard flows. Temporarily enables a virtual disk which enables
* testing on all devices, regardless of physical SD card support.
*/
@Ignore
@RunWith(AndroidJUnit4.class)
public class StorageWizardTest {
private static final String ANDROID_PACKAGE = "android";
private static final String PACKAGE = "com.android.settings";
private static final int TIMEOUT = 5000;
private static final int TIMEOUT_LONG = 30000;
private UiDevice mDevice;
private String mDisk;
private String mVolume;
@Before
public void setUp() throws Exception {
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mDevice.executeShellCommand("setprop sys.debug.storage_slow 1");
mDevice.executeShellCommand("sm set-virtual-disk true");
mDisk = getAdoptableDisk();
mDevice.executeShellCommand("sm partition " + mDisk + " public");
mVolume = getPublicVolume();
}
@After
public void tearDown() throws Exception {
// Go back to home for next test.
mDevice.pressBack();
mDevice.pressBack();
mDevice.pressHome();
mDevice.waitForIdle(TIMEOUT);
mDevice.executeShellCommand("setprop sys.debug.storage_slow 0");
mDevice.executeShellCommand("sm set-virtual-disk false");
mDevice.executeShellCommand("sm forget all");
}
/**
* Test flow for adopting a storage device as internal/adopted.
*/
@Test
public void testInternal() throws Exception {
InstrumentationRegistry.getContext().startActivity(buildInitIntent());
// Activity: pick option to use as internal
waitFor(By.res(PACKAGE, "suc_layout_title").text(containsIgnoringCase("How will you use")));
waitFor(By.res(PACKAGE, "storage_wizard_init_internal")).click();
// Dialog: acknowledge that we're formatting the card
waitFor(By.res(ANDROID_PACKAGE, "alertTitle").textContains("Format"));
waitFor(By.clickable(true).text(containsIgnoringCase("Format"))).click();
// Activity: ack storage device is slow
waitForLong(By.res(PACKAGE, "suc_layout_title").textContains("Slow"));
waitFor(By.res(PACKAGE, "storage_next_button")).click();
// Activity: choose to move content
waitForLong(By.res(PACKAGE, "suc_layout_title").textContains("Move content"));
waitFor(By.res(PACKAGE, "storage_next_button")).click();
// Activity: yay, we're done!
waitForLong(By.res(PACKAGE, "suc_layout_title").textContains("ready to use"));
waitFor(By.res(PACKAGE, "storage_next_button")).click();
}
/**
* Test flow for adopting a storage device as external/portable.
*/
@Test
public void testExternal() throws Exception {
InstrumentationRegistry.getContext().startActivity(buildInitIntent());
// Activity: pick option to use as external
waitFor(By.res(PACKAGE, "suc_layout_title").textContains("How will you use"));
waitFor(By.res(PACKAGE, "storage_wizard_init_external")).click();
// Activity: yay, we're done!
waitFor(By.res(PACKAGE, "suc_layout_title").textContains("ready to use"));
waitFor(By.res(PACKAGE, "storage_next_button")).click();
}
private UiObject2 waitFor(BySelector selector) throws UiObjectNotFoundException {
return waitFor(selector, TIMEOUT);
}
private UiObject2 waitForLong(BySelector selector) throws UiObjectNotFoundException {
return waitFor(selector, TIMEOUT_LONG);
}
private UiObject2 waitFor(BySelector selector, long timeout) throws UiObjectNotFoundException {
final UiObject2 item = mDevice.wait(Until.findObject(selector), timeout);
if (item != null) {
return item;
} else {
throw new UiObjectNotFoundException(selector.toString());
}
}
/**
* Shamelessly borrowed from AdoptableHostTest in CTS.
*/
private String getAdoptableDisk() throws IOException {
// In the case where we run multiple test we cleanup the state of the device. This
// results in the execution of sm forget all which causes the MountService to "reset"
// all its knowledge about available drives. This can cause the adoptable drive to
// become temporarily unavailable.
int attempt = 0;
String disks = mDevice.executeShellCommand("sm list-disks adoptable");
while ((disks == null || disks.isEmpty()) && attempt++ < 15) {
SystemClock.sleep(1000);
disks = mDevice.executeShellCommand("sm list-disks adoptable");
}
if (disks == null || disks.isEmpty()) {
throw new AssertionError("Devices that claim to support adoptable storage must have "
+ "adoptable media inserted during CTS to verify correct behavior");
}
return disks.split("\n")[0].trim();
}
private String getPublicVolume() throws IOException {
int attempt = 0;
String volumes = mDevice.executeShellCommand("sm list-volumes public");
while ((volumes == null || volumes.isEmpty() || !volumes.contains("mounted"))
&& attempt++ < 15) {
SystemClock.sleep(1000);
volumes = mDevice.executeShellCommand("sm list-volumes public");
}
if (volumes == null || volumes.isEmpty()) {
throw new AssertionError("Devices that claim to support adoptable storage must have "
+ "adoptable media inserted during CTS to verify correct behavior");
}
return volumes.split("[\n ]")[0].trim();
}
private Intent buildInitIntent() {
final Intent intent = new Intent().setClassName(PACKAGE,
PACKAGE + ".deviceinfo.StorageWizardInit");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(DiskInfo.EXTRA_DISK_ID, mDisk);
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, mVolume);
return intent;
}
private Pattern containsIgnoringCase(String text) {
return Pattern.compile("(?i)^.*" + text + ".*$");
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2023 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.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SyncSettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_SYNC_SETTINGS)
}
@Test
fun hasTexts() {
device.assertHasTexts(ON_SCREEN_TEXTS)
}
private companion object {
val ON_SCREEN_TEXTS = listOf("Add account")
}
}

View File

@@ -0,0 +1,127 @@
/*
* 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 static com.android.settings.ui.testutils.SettingsTestUtils.SETTINGS_PACKAGE;
import static com.google.common.truth.Truth.assertThat;
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.system.helpers.CommandsHelper;
import android.system.helpers.SettingsHelper;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Core tests for Wifi Settings.
*/
@Ignore
@RunWith(AndroidJUnit4.class)
@MediumTest
public class WirelessNetworkSettingsTests {
// 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 = 20000;
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 = "WirelessNetworkTests";
private UiDevice mDevice;
private CommandsHelper mCommandsHelper;
@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);
}
// Ensure airplane mode is OFF so that wifi can be enabled using WiFiManager.
Settings.Global.putString(InstrumentationRegistry.getTargetContext().getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, "0");
Log.d(TAG, "sending airplane mode broadcast to device");
mCommandsHelper = CommandsHelper.getInstance(InstrumentationRegistry.getInstrumentation());
mCommandsHelper.executeShellCommand(AIRPLANE_MODE_BROADCAST);
}
@After
public void tearDown() {
// Exit all settings sub-menus.
for (int i = 0; i < NUM_BACK_BUTTON_PRESSES; ++i) {
mDevice.pressBack();
}
mDevice.pressHome();
}
@Presubmit
@Test
public void testWiFiEnabled() throws Exception {
verifyWiFiOnOrOff(true);
}
@Presubmit
@Test
public void testWiFiDisabled() throws Exception {
verifyWiFiOnOrOff(false);
}
private void verifyWiFiOnOrOff(boolean verifyOn) throws Exception {
loadWiFiSettingsPage(!verifyOn);
mDevice.wait(Until.findObject(By.res(SETTINGS_PACKAGE, "switch_widget")), TIMEOUT)
.click();
Thread.sleep(SLEEP_TIME);
final String wifiValue = Settings.Global.getString(
InstrumentationRegistry.getTargetContext().getContentResolver(),
Settings.Global.WIFI_ON);
if (verifyOn) {
// 1 is Enabled, 2 is Enabled while airplane mode is ON.
assertThat(wifiValue).isAnyOf("1", "2");
} else {
assertThat(wifiValue).isEqualTo("0");
}
}
private void loadWiFiSettingsPage(boolean wifiEnabled) throws Exception {
WifiManager wifiManager = (WifiManager) InstrumentationRegistry.getTargetContext()
.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(wifiEnabled);
SettingsHelper.launchSettingsPage(InstrumentationRegistry.getTargetContext(),
Settings.ACTION_WIFI_SETTINGS);
}
}

View File

@@ -0,0 +1,222 @@
/*
* 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 static com.android.settings.ui.testutils.SettingsTestUtils.SETTINGS_PACKAGE;
import static com.android.settings.ui.testutils.SettingsTestUtils.TIMEOUT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings;
import android.system.helpers.SettingsHelper;
import android.system.helpers.SettingsHelper.SettingsType;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.MediumTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiScrollable;
import androidx.test.uiautomator.UiSelector;
import androidx.test.uiautomator.Until;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.TimeZone;
@Ignore
@MediumTest
@RunWith(AndroidJUnit4.class)
public class ZonePickerSettingsTest {
private static final BySelector SELECTOR_SELECT_TIME_ZONE =
By.hasChild(By.text("Select time zone"));
private UiDevice mDevice;
private SettingsHelper mHelper;
private String mIsV2EnabledByDefault;
private int mIsAutoZoneEnabled;
@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 orientation", e);
}
mIsV2EnabledByDefault = mHelper.getStringSetting(SettingsType.GLOBAL,
"settings_zone_picker_v2");
mHelper.setStringSetting(SettingsType.GLOBAL, "settings_zone_picker_v2", "true");
mIsAutoZoneEnabled = mHelper.getIntSetting(SettingsType.GLOBAL,
Settings.Global.AUTO_TIME_ZONE);
}
@After
public void tearDown() throws Exception {
// Go back to home for next test.
mDevice.pressBack();
mDevice.pressBack();
mDevice.pressHome();
mDevice.waitForIdle(TIMEOUT * 2);
mHelper.setStringSetting(SettingsType.GLOBAL, "settings_zone_picker_v2",
mIsV2EnabledByDefault);
mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE,
mIsAutoZoneEnabled);
}
@Test
public void zonePickerDisabled() throws Exception {
mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, 1);
SettingsHelper.launchSettingsPage(
InstrumentationRegistry.getContext(), Settings.ACTION_DATE_SETTINGS);
UiObject2 selectTimeZone = wait(SELECTOR_SELECT_TIME_ZONE);
assertFalse(selectTimeZone.isEnabled());
}
// Test 2 time zones with no DST
@Test
public void testSelectReykjavik() throws Exception {
testSelectTimeZone("Iceland", "Reykjavik", "GMT+00:00", "Atlantic/Reykjavik", true);
}
@Test
public void testSelectPhoenix() throws Exception {
testSelectTimeZone("United States", "Phoenix", "GMT-07:00", "America/Phoenix", false);
}
private void testSelectTimeZone(String region, String timezone, String expectedTimeZoneOffset,
String expectedTimeZoneId, boolean assumeOneTimeZoneInRegion) throws Exception {
mHelper.setIntSetting(SettingsType.GLOBAL, Settings.Global.AUTO_TIME_ZONE, 0);
SettingsHelper.launchSettingsPage(
InstrumentationRegistry.getContext(), Settings.ACTION_DATE_SETTINGS);
UiObject2 selectTimeZone = wait(SELECTOR_SELECT_TIME_ZONE);
assertTrue(selectTimeZone.isEnabled());
selectTimeZone.click();
wait(By.text("Region")).click();
// Speed-up the test by searching with the first 2 characters of the region name
wait(By.res("android", "search_src_text")).setText(region.substring(0, 2));
// Select region in the list
selectItemInList(new UiSelector().textContains(region))
.click();
// Only select time zone explicitly if there are more than one time zones in a region
if (!assumeOneTimeZoneInRegion) {
wait(By.text("Time zone"));
selectItemInList(new UiSelector().textContains(timezone))
.click();
}
mDevice.pressBack();
// The select button should include the GMT offset in the summary
BySelector summarySelector = By.res("android:id/summary");
UiObject2 selectedTimeZone = selectTimeZone.findObject(summarySelector);
assertUiObjectFound(selectedTimeZone, summarySelector);
assertTrue("Expect " + expectedTimeZoneOffset + " is shown for " + timezone,
selectedTimeZone.getText().startsWith(expectedTimeZoneOffset));
waitAndAssertTimeGetDefault(expectedTimeZoneId);
assertEquals("Time zone change in Settings should update persist.sys.timezone",
expectedTimeZoneId, SystemProperties.get("persist.sys.timezone"));
}
private static final long CHECK_DEFAULT_TIMEZONE_INTERVAL = 200L;
private static final long CHECK_DEFAULT_TIMEZONE_TIMEOUT = 3000L;
/**
* Wait for the broadcast ACTION_TIMEZONE_CHANGED propagated, and update the default TimeZone
* by ApplicationThread.
*/
private static void waitAndAssertTimeGetDefault(String expectedTimeZoneId)
throws InterruptedException {
for (int i = 0; i < CHECK_DEFAULT_TIMEZONE_TIMEOUT / CHECK_DEFAULT_TIMEZONE_INTERVAL; i++) {
if (expectedTimeZoneId.equals(TimeZone.getDefault().getID())) {
return;
}
Thread.sleep(CHECK_DEFAULT_TIMEZONE_INTERVAL);
}
assertEquals(expectedTimeZoneId, TimeZone.getDefault().getID());
}
private UiObject selectItemInList(UiSelector childSelector) throws UiObjectNotFoundException {
UiScrollable recyclerView = new UiScrollable(
new UiSelector().resourceId(SETTINGS_PACKAGE + ":id/recycler_view"));
return selectScrollableItem(recyclerView, childSelector);
}
/**
* Select the child object in the UiScrollable
* @throws UiObjectNotFoundException if scrollable or child is not found
*/
private UiObject selectScrollableItem(UiScrollable scrollable, UiSelector childSelector)
throws UiObjectNotFoundException {
if (!scrollable.waitForExists(TIMEOUT)) {
throw newUiObjectNotFoundException(scrollable.getSelector());
}
scrollable.scrollIntoView(childSelector);
UiObject child = mDevice.findObject(childSelector);
assertUiObjectFound(child, childSelector);
return child;
}
/**
* @throws UiObjectNotFoundException if UiDevice.wait returns null
*/
private UiObject2 wait(BySelector selector) throws UiObjectNotFoundException {
UiObject2 item = mDevice.wait(Until.findObject(selector), TIMEOUT);
assertUiObjectFound(item, selector);
return item;
}
private static void assertUiObjectFound(UiObject2 obj, BySelector selector)
throws UiObjectNotFoundException {
if (obj == null) {
throw newUiObjectNotFoundException(selector);
}
}
private static void assertUiObjectFound(UiObject obj, UiSelector selector)
throws UiObjectNotFoundException {
if (obj == null) {
throw newUiObjectNotFoundException(selector);
}
}
private static UiObjectNotFoundException newUiObjectNotFoundException(Object selector) {
return new UiObjectNotFoundException(
String.format("UI object not found: %s", selector.toString()));
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2023 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.inputmethods
import android.content.Intent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.SETTINGS_PACKAGE
import com.android.settings.ui.testutils.SettingsTestUtils.assertObject
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SpellCheckerSettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Intent().apply {
setClassName(
SETTINGS_PACKAGE,
"com.android.settings.Settings\$SpellCheckersSettingsActivity",
)
})
}
@Test
fun hasSwitchBar() {
device.assertObject(By.text("Use spell checker"))
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright (C) 2023 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.privatespace
import android.os.Flags
import android.platform.test.annotations.RequiresFlagsDisabled
import android.platform.test.annotations.RequiresFlagsEnabled
import android.platform.test.flag.junit.DeviceFlagsValueProvider
import android.provider.Settings
import android.util.Log
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.clickObject
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import com.android.settings.ui.testutils.SettingsTestUtils.waitObject
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@RequiresFlagsEnabled(Flags.FLAG_ALLOW_PRIVATE_PROFILE)
class PrivateSpaceAuthenticationActivityTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@get:Rule
public val mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_SECURITY_SETTINGS)
device.assertHasTexts(listOf(PRIVATE_SPACE_SETTING))
}
@Test
fun showAuthenticationScreen() {
Thread.sleep(1000)
device.clickObject(By.text(PRIVATE_SPACE_SETTING))
device.waitObject(By.text(DIALOG_TITLE))
Thread.sleep(1000)
device.assertHasTexts(listOf("Set a screen lock","Cancel"))
}
@Test
fun onCancelLockExitSetup() {
Thread.sleep(1000)
device.clickObject(By.text(PRIVATE_SPACE_SETTING))
device.waitObject(By.text(DIALOG_TITLE))
Thread.sleep(1000)
device.assertHasTexts(listOf(SET_LOCK_BUTTON, CANCEL_TEXT))
device.clickObject(By.text(CANCEL_TEXT))
device.assertHasTexts(listOf(PRIVATE_SPACE_SETTING))
}
@Test
fun onSetupSetLock() {
Thread.sleep(1000)
device.clickObject(By.text(PRIVATE_SPACE_SETTING))
device.waitObject(By.text(DIALOG_TITLE))
Thread.sleep(1000)
device.assertHasTexts(listOf(SET_LOCK_BUTTON,CANCEL_TEXT))
device.clickObject(By.text(SET_LOCK_BUTTON))
Thread.sleep(1000)
device.assertHasTexts(listOf(PATTERN_TEXT, PIN_TEXT, PASSWORD_TEXT))
}
private companion object {
// Items we really want to always show
val PRIVATE_SPACE_SETTING = "Private space"
const val SET_LOCK_BUTTON = "Set screen lock"
val CANCEL_TEXT = "Cancel"
val DIALOG_TITLE = "Set a screen lock"
val PATTERN_TEXT = "Pattern"
val PIN_TEXT = "PIN"
val PASSWORD_TEXT = "Password"
}
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2023 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 android.content.Context
import android.content.Intent
import android.view.KeyEvent
import androidx.test.core.app.ApplicationProvider
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.Direction
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.google.common.truth.Truth.assertWithMessage
object SettingsTestUtils {
const val SETTINGS_PACKAGE = "com.android.settings"
const val TIMEOUT = 2000L
fun UiDevice.waitObject(bySelector: BySelector): UiObject2? =
wait(Until.findObject(bySelector), TIMEOUT)
fun UiDevice.assertObject(bySelector: BySelector): UiObject2 =
checkNotNull(waitObject(bySelector)) { "$bySelector not found" }
fun UiDevice.clickObject(bySelector: BySelector) = assertObject(bySelector).click()
fun UiDevice.startMainActivityFromHomeScreen(action: String) {
startMainActivityFromHomeScreen(Intent(action))
}
fun UiDevice.startMainActivityFromHomeScreen(intent: Intent) {
pressKeyCodes(intArrayOf(KeyEvent.KEYCODE_MENU, KeyEvent.KEYCODE_MENU)) // unlock
// Start from the home screen
pressHome()
// Wait for launcher
waitObject(By.pkg(launcherPackageName).depth(0))
// Launch the app
ApplicationProvider.getApplicationContext<Context>().startActivity(Intent(intent).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
})
// Wait for the app to appear
waitObject(By.pkg(SETTINGS_PACKAGE).depth(0))
}
fun UiDevice.assertHasTexts(texts: List<String>) {
val scrollableObj =
findObject(By.res(SETTINGS_PACKAGE, "main_content"))
?: findObject(By.scrollable(true))
for (text in texts) {
val selector = By.text(text)
assertWithMessage("Missing text: $text").that(
findObject(selector)
?: scrollableObj.scrollUntil(Direction.DOWN, Until.findObject(selector))
?: waitObject(selector)
).isNotNull()
}
}
}