fix: 引入Settings的Module
This commit is contained in:
@@ -0,0 +1 @@
|
||||
include /src/com/android/settings/biometrics/OWNERS
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
@@ -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 & Wi‑Fi",
|
||||
"Screen time",
|
||||
"App battery usage",
|
||||
"Language",
|
||||
"Unused app settings",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
"Wi‑Fi data usage",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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 = "Wi‑Fi preferences";
|
||||
private static final String CONFIGURE_WIFI_ADVANCED_PREFERENCE_TEXT = "Advanced";
|
||||
private static final String CACERT_MENU_PLEASE_SELECT_TEXT = "Please select";
|
||||
private static final String CACERT_MENU_USE_SYSTEM_CERTS_TEXT = "Use system certificates";
|
||||
private static final String CACERT_MENU_DO_NOT_VALIDATE_TEXT = "Do not validate";
|
||||
private static final String USERCERT_MENU_PLEASE_SELECT_TEXT = "Please select";
|
||||
private static final String USERCERT_MENU_DO_NOT_PROVIDE_TEXT = "Do not provide";
|
||||
private static final String SECURITY_OPTION_NONE_TEXT = "None";
|
||||
private static final String SECURITY_OPTION_WEP_TEXT = "WEP";
|
||||
private static final String SECURITY_OPTION_PSK_TEXT = "WPA/WPA2 PSK";
|
||||
private static final String SECURITY_OPTION_EAP_TEXT = "802.1x EAP";
|
||||
private static final String EAP_METHOD_PEAP_TEXT = "PEAP";
|
||||
private static final String EAP_METHOD_TLS_TEXT = "TLS";
|
||||
private static final String EAP_METHOD_TTLS_TEXT = "TTLS";
|
||||
private static final String EAP_METHOD_PWD_TEXT = "PWD";
|
||||
private static final String EAP_METHOD_SIM_TEXT = "SIM";
|
||||
private static final String EAP_METHOD_AKA_TEXT = "AKA";
|
||||
private static final String EAP_METHOD_AKA_PRIME_TEXT = "AKA'";
|
||||
private static final String PHASE2_MENU_NONE_TEXT = "None";
|
||||
private static final String PHASE2_MENU_MSCHAPV2_TEXT = "MSCHAPV2";
|
||||
private static final String PHASE2_MENU_GTC_TEXT = "GTC";
|
||||
|
||||
private static final String ADD_NETWORK_MENU_ADV_TOGGLE_RES_ID = "wifi_advanced_togglebox";
|
||||
private static final String ADD_NETWORK_MENU_IP_SETTINGS_RES_ID = "ip_settings";
|
||||
private static final String ADD_NETWORK_MENU_PROXY_SETTINGS_RES_ID = "proxy_settings";
|
||||
private static final String ADD_NETWORK_MENU_SECURITY_OPTION_RES_ID = "security";
|
||||
private static final String ADD_NETWORK_MENU_EAP_METHOD_RES_ID = "method";
|
||||
private static final String ADD_NETWORK_MENU_SSID_RES_ID = "ssid";
|
||||
private static final String ADD_NETWORK_MENU_PHASE2_RES_ID = "phase2";
|
||||
private static final String ADD_NETWORK_MENU_CACERT_RES_ID = "ca_cert";
|
||||
private static final String ADD_NETWORK_MENU_USERCERT_RES_ID = "user_cert";
|
||||
private static final String ADD_NETWORK_MENU_NO_DOMAIN_WARNING_RES_ID = "no_domain_warning";
|
||||
private static final String ADD_NETWORK_MENU_NO_CACERT_WARNING_RES_ID = "no_ca_cert_warning";
|
||||
private static final String ADD_NETWORK_MENU_DOMAIN_LAYOUT_RES_ID = "l_domain";
|
||||
private static final String ADD_NETWORK_MENU_DOMAIN_RES_ID = "domain";
|
||||
private static final String ADD_NETWORK_MENU_IDENTITY_LAYOUT_RES_ID = "l_identity";
|
||||
private static final String ADD_NETWORK_MENU_ANONYMOUS_LAYOUT_RES_ID = "l_anonymous";
|
||||
private static final String ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID = "password_layout";
|
||||
private static final String ADD_NETWORK_MENU_SHOW_PASSWORD_LAYOUT_RES_ID =
|
||||
"show_password_layout";
|
||||
private static final String ADD_NETWORK_MENU_PASSWORD_RES_ID = "password";
|
||||
|
||||
private static final BySelector ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR =
|
||||
By.scrollable(true).clazz(SCROLLVIEW_CLASS);
|
||||
private static final BySelector SPINNER_OPTIONS_SCROLLABLE_BY_SELECTOR =
|
||||
By.scrollable(true).clazz(LISTVIEW_CLASS);
|
||||
|
||||
private UiDevice mDevice;
|
||||
private CommandsHelper mCommandsHelper;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mDevice = UiDevice.getInstance(getInstrumentation());
|
||||
try {
|
||||
mDevice.setOrientationNatural();
|
||||
} catch (RemoteException e) {
|
||||
throw new RuntimeException("failed to freeze device orientation", e);
|
||||
}
|
||||
// Ensure airplane mode is OFF so that wifi can be enabled using WiFiManager.
|
||||
Settings.Global.putString(getInstrumentation().getContext().getContentResolver(),
|
||||
Settings.Global.AIRPLANE_MODE_ON, "0");
|
||||
Log.d(TAG, "sending airplane mode broadcast to device");
|
||||
mCommandsHelper = CommandsHelper.getInstance();
|
||||
mCommandsHelper.executeShellCommand(AIRPLANE_MODE_BROADCAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
// Exit all settings sub-menus.
|
||||
for (int i = 0; i < NUM_BACK_BUTTON_PRESSES; ++i) {
|
||||
mDevice.pressBack();
|
||||
}
|
||||
mDevice.pressHome();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testWifiMenuLoadConfigure() throws Exception {
|
||||
loadWiFiConfigureMenu();
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
UiObject2 configureWiFiHeading = mDevice.wait(Until.findObject
|
||||
(By.text(CONFIGURE_WIFI_PREFERENCE_TEXT)), TIMEOUT);
|
||||
assertNotNull("Configure WiFi menu has not loaded correctly", configureWiFiHeading);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testNetworkNotificationsOn() throws Exception {
|
||||
verifyNetworkNotificationsOnOrOff(true);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testNetworkNotificationsOff() throws Exception {
|
||||
verifyNetworkNotificationsOnOrOff(false);
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
public void testAddNetworkMenu_Default() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
|
||||
// Submit button should be disabled by default, while cancel button should be enabled.
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
assertTrue(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_CANCEL_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
// Check that the SSID field is defaults to the hint.
|
||||
assertEquals("Enter the SSID", mDevice.wait(Until.findObject(By
|
||||
.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SSID_RES_ID)
|
||||
.clazz(EDIT_TEXT_CLASS)), TIMEOUT*2)
|
||||
.getText());
|
||||
|
||||
// Check Security defaults to None.
|
||||
assertEquals("None", mDevice.wait(Until.findObject(By
|
||||
.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SECURITY_OPTION_RES_ID)
|
||||
.clazz(SPINNER_CLASS)), TIMEOUT)
|
||||
.getChildren().get(0).getText());
|
||||
|
||||
// Check advanced options are collapsed by default.
|
||||
assertFalse(mDevice.wait(Until.findObject(By
|
||||
.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_ADV_TOGGLE_RES_ID)
|
||||
.clazz(CHECKBOX_CLASS)), TIMEOUT).isChecked());
|
||||
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetworkMenu_Proxy() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
|
||||
// Toggle advanced options.
|
||||
mDevice.wait(Until.findObject(By
|
||||
.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_ADV_TOGGLE_RES_ID)
|
||||
.clazz(CHECKBOX_CLASS)), TIMEOUT).click();
|
||||
|
||||
// Verify Proxy defaults to None.
|
||||
BySelector proxySettingsBySelector =
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PROXY_SETTINGS_RES_ID)
|
||||
.clazz(SPINNER_CLASS);
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, proxySettingsBySelector);
|
||||
assertEquals("None", mDevice.wait(Until.findObject(proxySettingsBySelector), TIMEOUT)
|
||||
.getChildren().get(0).getText());
|
||||
|
||||
// Verify that Proxy Manual fields appear.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, proxySettingsBySelector);
|
||||
mDevice.wait(Until.findObject(proxySettingsBySelector), TIMEOUT).click();
|
||||
mDevice.wait(Until.findObject(By.text("Manual")), TIMEOUT).click();
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, "proxy_warning_limited_support"));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, "proxy_hostname"));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, "proxy_exclusionlist"));
|
||||
|
||||
// Verify that Proxy Auto-Config options appear.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, proxySettingsBySelector);
|
||||
mDevice.wait(Until.findObject(proxySettingsBySelector), TIMEOUT).click();
|
||||
mDevice.wait(Until.findObject(By.text("Proxy Auto-Config")), TIMEOUT).click();
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, "proxy_pac"));
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetworkMenu_IpSettings() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
|
||||
// Toggle advanced options.
|
||||
mDevice.wait(Until.findObject(By
|
||||
.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_ADV_TOGGLE_RES_ID)
|
||||
.clazz(CHECKBOX_CLASS)), TIMEOUT).click();
|
||||
|
||||
// Verify IP settings defaults to DHCP.
|
||||
BySelector ipSettingsBySelector =
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_IP_SETTINGS_RES_ID).clazz(SPINNER_CLASS);
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, ipSettingsBySelector);
|
||||
assertEquals("DHCP", mDevice.wait(Until.findObject(ipSettingsBySelector), TIMEOUT)
|
||||
.getChildren().get(0).getText());
|
||||
|
||||
// Verify that Static IP settings options appear.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, ipSettingsBySelector).click();
|
||||
mDevice.wait(Until.findObject(By.text("Static")), TIMEOUT).click();
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, "ipaddress"));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, "gateway"));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, "network_prefix_length"));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, "dns1"));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, "dns2"));
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testPhase2Settings() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
|
||||
|
||||
BySelector phase2SettingsBySelector =
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PHASE2_RES_ID).clazz(SPINNER_CLASS);
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, phase2SettingsBySelector);
|
||||
assertEquals(PHASE2_MENU_NONE_TEXT, mDevice.wait(Until
|
||||
.findObject(phase2SettingsBySelector), TIMEOUT).getChildren().get(0).getText());
|
||||
mDevice.wait(Until.findObject(phase2SettingsBySelector), TIMEOUT).click();
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
|
||||
// Verify Phase 2 authentication spinner options.
|
||||
assertNotNull(mDevice.wait(Until.findObject(By.text(PHASE2_MENU_NONE_TEXT)), TIMEOUT));
|
||||
assertNotNull(mDevice.wait(Until.findObject(By.text(PHASE2_MENU_MSCHAPV2_TEXT)), TIMEOUT));
|
||||
assertNotNull(mDevice.wait(Until.findObject(By.text(PHASE2_MENU_GTC_TEXT)), TIMEOUT));
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testCaCertSettings() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
|
||||
|
||||
BySelector caCertSettingsBySelector =
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_CACERT_RES_ID).clazz(SPINNER_CLASS);
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR, caCertSettingsBySelector);
|
||||
assertEquals(CACERT_MENU_PLEASE_SELECT_TEXT, mDevice.wait(Until
|
||||
.findObject(caCertSettingsBySelector), TIMEOUT).getChildren().get(0).getText());
|
||||
mDevice.wait(Until.findObject(caCertSettingsBySelector), TIMEOUT).click();
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
|
||||
// Verify CA certificate spinner options.
|
||||
assertNotNull(mDevice.wait(Until.findObject(
|
||||
By.text(CACERT_MENU_PLEASE_SELECT_TEXT)), TIMEOUT));
|
||||
assertNotNull(mDevice.wait(Until.findObject(
|
||||
By.text(CACERT_MENU_USE_SYSTEM_CERTS_TEXT)), TIMEOUT));
|
||||
assertNotNull(mDevice.wait(Until.findObject(
|
||||
By.text(CACERT_MENU_DO_NOT_VALIDATE_TEXT)), TIMEOUT));
|
||||
|
||||
// Verify that a domain field and warning appear when the user selects the
|
||||
// "Use system certificates" option.
|
||||
mDevice.wait(Until.findObject(By.text(CACERT_MENU_USE_SYSTEM_CERTS_TEXT)), TIMEOUT).click();
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_DOMAIN_LAYOUT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_NO_DOMAIN_WARNING_RES_ID));
|
||||
|
||||
// Verify that a warning appears when the user chooses the "Do Not Validate" option.
|
||||
mDevice.wait(Until.findObject(caCertSettingsBySelector), TIMEOUT).click();
|
||||
mDevice.wait(Until.findObject(By.text(CACERT_MENU_DO_NOT_VALIDATE_TEXT)), TIMEOUT).click();
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_NO_CACERT_WARNING_RES_ID));
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetwork_NoSecurity() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_NONE_TEXT);
|
||||
|
||||
// Entering an SSID is enough to enable the submit button. // TODO THIS GUY
|
||||
enterSSID(TEST_SSID);
|
||||
assertTrue(mDevice.wait(Until
|
||||
.findObject(By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetwork_WEP() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_WEP_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
// Verify that WEP fields appear.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SHOW_PASSWORD_LAYOUT_RES_ID));
|
||||
|
||||
// Entering an SSID alone does not enable the submit button.
|
||||
enterSSID(TEST_SSID);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
// Submit button is only enabled after a password is entered.
|
||||
enterPassword(TEST_PW_GE_8_CHAR);
|
||||
assertTrue(mDevice.wait(Until
|
||||
.findObject(By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetwork_PSK() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_PSK_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
// Verify that PSK fields appear.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SHOW_PASSWORD_LAYOUT_RES_ID));
|
||||
|
||||
// Entering an SSID alone does not enable the submit button.
|
||||
enterSSID(TEST_SSID);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
// Entering an password that is too short does not enable submit button.
|
||||
enterPassword(TEST_PW_LT_8_CHAR);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
// Submit button is only enabled after a password of valid length is entered.
|
||||
enterPassword(TEST_PW_GE_8_CHAR);
|
||||
assertTrue(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetwork_EAP_PEAP() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
selectEAPMethod(EAP_METHOD_PEAP_TEXT);
|
||||
|
||||
// Verify that EAP-PEAP fields appear.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PHASE2_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_CACERT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_IDENTITY_LAYOUT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_ANONYMOUS_LAYOUT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SHOW_PASSWORD_LAYOUT_RES_ID));
|
||||
|
||||
// Entering an SSID alone does not enable the submit button.
|
||||
enterSSID(TEST_SSID);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
verifyCaCertificateSubmitConditions();
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetwork_EAP_TLS() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
selectEAPMethod(EAP_METHOD_TLS_TEXT);
|
||||
|
||||
// Verify that EAP-TLS fields appear.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_CACERT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_USERCERT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_IDENTITY_LAYOUT_RES_ID));
|
||||
|
||||
// Entering an SSID alone does not enable the submit button.
|
||||
enterSSID(TEST_SSID);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
// Selecting the User certificate "Do not provide" option alone does not enable the submit
|
||||
// button.
|
||||
selectUserCertificateOption(USERCERT_MENU_DO_NOT_PROVIDE_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
verifyCaCertificateSubmitConditions();
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetwork_EAP_TTLS() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
selectEAPMethod(EAP_METHOD_TTLS_TEXT);
|
||||
|
||||
// Verify that EAP-TLS fields appear.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PHASE2_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_CACERT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_IDENTITY_LAYOUT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_ANONYMOUS_LAYOUT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID));
|
||||
|
||||
// Entering an SSID alone does not enable the submit button.
|
||||
enterSSID(TEST_SSID);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
verifyCaCertificateSubmitConditions();
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetwork_EAP_PWD() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
selectEAPMethod(EAP_METHOD_PWD_TEXT);
|
||||
|
||||
// Verify that EAP-TLS fields appear.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_IDENTITY_LAYOUT_RES_ID));
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_LAYOUT_RES_ID));
|
||||
|
||||
// Entering an SSID alone enables the submit button.
|
||||
enterSSID(TEST_SSID);
|
||||
assertTrue(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetwork_EAP_SIM() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
selectEAPMethod(EAP_METHOD_SIM_TEXT);
|
||||
|
||||
// Entering an SSID alone enables the submit button.
|
||||
enterSSID(TEST_SSID);
|
||||
assertTrue(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetwork_EAP_AKA() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
selectEAPMethod(EAP_METHOD_AKA_TEXT);
|
||||
|
||||
// Entering an SSID alone enables the submit button.
|
||||
enterSSID(TEST_SSID);
|
||||
assertTrue(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
}
|
||||
|
||||
@Suppress
|
||||
@MediumTest
|
||||
public void testAddNetwork_EAP_AKA_PRIME() throws Exception {
|
||||
loadAddNetworkMenu();
|
||||
selectSecurityOption(SECURITY_OPTION_EAP_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
selectEAPMethod(EAP_METHOD_AKA_PRIME_TEXT);
|
||||
|
||||
// Entering an SSID alone enables the submit button.
|
||||
enterSSID(TEST_SSID);
|
||||
assertTrue(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
}
|
||||
|
||||
private void verifyKeepWiFiOnDuringSleep(String settingToBeVerified, int settingValue)
|
||||
throws Exception {
|
||||
loadWiFiConfigureMenu();
|
||||
mDevice.wait(Until.findObject(By.text("Keep Wi‑Fi on during sleep")), TIMEOUT)
|
||||
.click();
|
||||
mDevice.wait(Until.findObject(By.clazz("android.widget.CheckedTextView")
|
||||
.text(settingToBeVerified)), TIMEOUT).click();
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
int keepWiFiOnSetting =
|
||||
Settings.Global.getInt(getInstrumentation().getContext().getContentResolver(),
|
||||
Settings.Global.WIFI_SLEEP_POLICY);
|
||||
assertEquals(settingValue, keepWiFiOnSetting);
|
||||
}
|
||||
|
||||
private void verifyNetworkNotificationsOnOrOff(boolean verifyOn)
|
||||
throws Exception {
|
||||
// Enable network recommendations to enable the toggle switch for Network
|
||||
// notifications
|
||||
Settings.Global.putString(getInstrumentation().getContext().getContentResolver(),
|
||||
Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, "1");
|
||||
if (verifyOn) {
|
||||
Settings.Global.putString(getInstrumentation().getContext().getContentResolver(),
|
||||
Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, "0");
|
||||
}
|
||||
else {
|
||||
Settings.Global.putString(getInstrumentation().getContext().getContentResolver(),
|
||||
Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, "1");
|
||||
}
|
||||
loadWiFiConfigureMenu();
|
||||
mDevice.wait(Until.findObject(By.text("Open network notification")), TIMEOUT)
|
||||
.click();
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
String wifiNotificationValue =
|
||||
Settings.Global.getString(getInstrumentation().getContext().getContentResolver(),
|
||||
Settings.Global.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON);
|
||||
if (verifyOn) {
|
||||
assertEquals("1", wifiNotificationValue);
|
||||
}
|
||||
else {
|
||||
assertEquals("0", wifiNotificationValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyWiFiOnOrOff(boolean verifyOn) throws Exception {
|
||||
String switchText = "On";
|
||||
if (verifyOn) {
|
||||
switchText = "Off";
|
||||
}
|
||||
loadWiFiSettingsPage(!verifyOn);
|
||||
mDevice.wait(Until
|
||||
.findObject(By.res(SETTINGS_PACKAGE, "switch_bar").text(switchText)), TIMEOUT)
|
||||
.click();
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
String wifiValue =
|
||||
Settings.Global.getString(getInstrumentation().getContext().getContentResolver(),
|
||||
Settings.Global.WIFI_ON);
|
||||
if (verifyOn) {
|
||||
// 1 is Enabled, 2 is Enabled while airplane mode is ON.
|
||||
assertTrue(wifiValue.equals("1") || wifiValue.equals("2"));
|
||||
}
|
||||
else {
|
||||
assertEquals("0", wifiValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyCaCertificateSubmitConditions() throws Exception {
|
||||
// Selecting the CA certificate "Do not validate" option enables the submit button.
|
||||
selectCaCertificateOption(CACERT_MENU_DO_NOT_VALIDATE_TEXT);
|
||||
assertTrue(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
// However, selecting the CA certificate "Use system certificates option" is not enough to
|
||||
// enable the submit button.
|
||||
selectCaCertificateOption(CACERT_MENU_USE_SYSTEM_CERTS_TEXT);
|
||||
assertFalse(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
|
||||
// Submit button is only enabled after a domain is entered as well.
|
||||
enterDomain(TEST_DOMAIN);
|
||||
assertTrue(mDevice.wait(Until.findObject(
|
||||
By.text(ADD_NETWORK_MENU_SAVE_BUTTON_TEXT)), TIMEOUT).isEnabled());
|
||||
}
|
||||
|
||||
private void loadWiFiSettingsPage(boolean wifiEnabled) throws Exception {
|
||||
WifiManager wifiManager = (WifiManager)getInstrumentation().getContext()
|
||||
.getSystemService(Context.WIFI_SERVICE);
|
||||
wifiManager.setWifiEnabled(wifiEnabled);
|
||||
SettingsHelper.launchSettingsPage(getInstrumentation().getContext(),
|
||||
Settings.ACTION_WIFI_SETTINGS);
|
||||
}
|
||||
|
||||
private void loadWiFiConfigureMenu() throws Exception {
|
||||
loadWiFiSettingsPage(false);
|
||||
Thread.sleep(TIMEOUT);
|
||||
mDevice.wait(Until.findObject(By.text(CONFIGURE_WIFI_PREFERENCE_TEXT)), TIMEOUT).click();
|
||||
mDevice.wait(Until.findObject(
|
||||
By.text(CONFIGURE_WIFI_ADVANCED_PREFERENCE_TEXT)), TIMEOUT).click();
|
||||
}
|
||||
|
||||
private void loadAddNetworkMenu() throws Exception {
|
||||
loadWiFiSettingsPage(true);
|
||||
for (int attempts = 0; attempts < MAX_ADD_NETWORK_BUTTON_ATTEMPTS; ++attempts) {
|
||||
try {
|
||||
findOrScrollToObject(By.scrollable(true), By.text(ADD_NETWORK_PREFERENCE_TEXT))
|
||||
.click();
|
||||
} catch (StaleObjectException e) {
|
||||
// The network list might have been updated between when the Add network button was
|
||||
// found, and when it UI automator attempted to click on it. Retry.
|
||||
continue;
|
||||
}
|
||||
// If we get here, we successfully clicked on the Add network button, so we are done.
|
||||
Thread.sleep(SLEEP_TIME*5);
|
||||
return;
|
||||
}
|
||||
|
||||
fail("Failed to load Add Network Menu after " + MAX_ADD_NETWORK_BUTTON_ATTEMPTS
|
||||
+ " retries");
|
||||
}
|
||||
|
||||
private void selectSecurityOption(String securityOption) throws Exception {
|
||||
// We might not need to scroll to the security options if not enough add network menu
|
||||
// options are visible.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SECURITY_OPTION_RES_ID)
|
||||
.clazz(SPINNER_CLASS)).click();
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
mDevice.wait(Until.findObject(By.text(securityOption)), TIMEOUT).click();
|
||||
}
|
||||
|
||||
private void selectEAPMethod(String eapMethod) throws Exception {
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_EAP_METHOD_RES_ID).clazz(SPINNER_CLASS))
|
||||
.click();
|
||||
Thread.sleep(SLEEP_TIME);
|
||||
findOrScrollToObject(SPINNER_OPTIONS_SCROLLABLE_BY_SELECTOR, By.text(eapMethod)).click();
|
||||
}
|
||||
|
||||
private void selectUserCertificateOption(String userCertificateOption) throws Exception {
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_USERCERT_RES_ID).clazz(SPINNER_CLASS))
|
||||
.click();
|
||||
mDevice.wait(Until.findObject(By.text(userCertificateOption)), TIMEOUT).click();
|
||||
}
|
||||
|
||||
private void selectCaCertificateOption(String caCertificateOption) throws Exception {
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_CACERT_RES_ID).clazz(SPINNER_CLASS))
|
||||
.click();
|
||||
mDevice.wait(Until.findObject(By.text(caCertificateOption)), TIMEOUT).click();
|
||||
}
|
||||
|
||||
private void enterSSID(String ssid) throws Exception {
|
||||
// We might not need to scroll to the SSID option if not enough add network menu options
|
||||
// are visible.
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_SSID_RES_ID).clazz(EDIT_TEXT_CLASS))
|
||||
.setText(ssid);
|
||||
}
|
||||
|
||||
private void enterPassword(String password) throws Exception {
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_PASSWORD_RES_ID).clazz(EDIT_TEXT_CLASS))
|
||||
.setText(password);
|
||||
}
|
||||
|
||||
private void enterDomain(String domain) throws Exception {
|
||||
findOrScrollToObject(ADD_NETWORK_MENU_SCROLLABLE_BY_SELECTOR,
|
||||
By.res(SETTINGS_PACKAGE, ADD_NETWORK_MENU_DOMAIN_RES_ID)).setText(domain);
|
||||
}
|
||||
|
||||
// Use this if the UI object might or might not need to be scrolled to.
|
||||
private UiObject2 findOrScrollToObject(BySelector scrollableSelector, BySelector objectSelector)
|
||||
throws Exception {
|
||||
UiObject2 object = mDevice.wait(Until.findObject(objectSelector), TIMEOUT);
|
||||
if (object == null) {
|
||||
object = scrollToObject(scrollableSelector, objectSelector);
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
private UiObject2 scrollToObject(BySelector scrollableSelector, BySelector objectSelector)
|
||||
throws Exception {
|
||||
UiObject2 scrollable = mDevice.wait(Until.findObject(scrollableSelector), TIMEOUT);
|
||||
if (scrollable == null) {
|
||||
fail("Could not find scrollable UI object identified by " + scrollableSelector);
|
||||
}
|
||||
UiObject2 found = null;
|
||||
// Scroll all the way up first, then all the way down.
|
||||
while (true) {
|
||||
// Optimization: terminate if we find the object while scrolling up to reset, so
|
||||
// we save the time spent scrolling down again.
|
||||
boolean canScrollAgain = scrollable.scroll(Direction.UP, SCROLL_UP_PERCENT,
|
||||
SCROLL_SPEED);
|
||||
found = mDevice.findObject(objectSelector);
|
||||
if (found != null) return found;
|
||||
if (!canScrollAgain) break;
|
||||
}
|
||||
for (int attempts = 0; found == null && attempts < MAX_SCROLL_ATTEMPTS; ++attempts) {
|
||||
// Return value of UiObject2.scroll() is not reliable, so do not use it in loop
|
||||
// condition, in case it causes this loop to terminate prematurely.
|
||||
scrollable.scroll(Direction.DOWN, SCROLL_DOWN_PERCENT, SCROLL_SPEED);
|
||||
found = mDevice.findObject(objectSelector);
|
||||
}
|
||||
if (found == null) {
|
||||
fail("Could not scroll to UI object identified by " + objectSelector);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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 + ".*$");
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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()));
|
||||
}
|
||||
}
|
||||
@@ -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"))
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user