Merge changes from topic "testapp-refactor"

* changes:
  4/ Delete flicker test apps from WMShell package
  3/ Update flicker tests to compatibilize with new apps
  2/ Update app helpers for new apps
  1/ Add test apps from WM shell package into flicker
This commit is contained in:
Nataniel Borges
2022-09-22 09:44:45 +00:00
committed by Android (Google) Code Review
92 changed files with 1222 additions and 1725 deletions

View File

@@ -48,6 +48,6 @@ android_test {
"wm-flicker-common-assertions",
"wm-flicker-common-app-helpers",
"platform-test-annotations",
"wmshell-flicker-test-components",
"flickertestapplib",
],
}

View File

@@ -19,7 +19,7 @@
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true"/>
<option name="test-file-name" value="WMShellFlickerTests.apk"/>
<option name="test-file-name" value="WMShellFlickerTestApp.apk" />
<option name="test-file-name" value="FlickerTestApp.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest">
<option name="package" value="com.android.wm.shell.flicker"/>

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2020 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.wm.shell.flicker
import android.app.Instrumentation
import android.content.Context
import android.provider.Settings
import android.util.Log
import com.android.compatibility.common.util.SystemUtil
import java.io.IOException
object MultiWindowUtils {
private fun executeShellCommand(instrumentation: Instrumentation, cmd: String) {
try {
SystemUtil.runShellCommand(instrumentation, cmd)
} catch (e: IOException) {
Log.e(MultiWindowUtils::class.simpleName, "executeShellCommand error! $e")
}
}
fun getDevEnableNonResizableMultiWindow(context: Context): Int =
Settings.Global.getInt(context.contentResolver,
Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW)
fun setDevEnableNonResizableMultiWindow(context: Context, configValue: Int) =
Settings.Global.putInt(context.contentResolver,
Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, configValue)
fun setSupportsNonResizableMultiWindow(instrumentation: Instrumentation, configValue: Int) =
executeShellCommand(
instrumentation,
createConfigSupportsNonResizableMultiWindowCommand(configValue))
fun resetMultiWindowConfig(instrumentation: Instrumentation) =
executeShellCommand(instrumentation, resetMultiWindowConfigCommand)
private fun createConfigSupportsNonResizableMultiWindowCommand(configValue: Int): String =
"wm set-multi-window-config --supportsNonResizable $configValue"
private const val resetMultiWindowConfigCommand: String = "wm reset-multi-window-config"
}

View File

@@ -19,6 +19,7 @@ package com.android.wm.shell.flicker.bubble
import android.app.INotificationManager
import android.app.NotificationManager
import android.content.Context
import android.content.pm.PackageManager
import android.os.ServiceManager
import android.view.Surface
import androidx.test.uiautomator.By
@@ -28,9 +29,9 @@ import com.android.server.wm.flicker.Flicker
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.LaunchBubbleHelper
import com.android.server.wm.flicker.helpers.SYSTEMUI_PACKAGE
import com.android.wm.shell.flicker.BaseTest
import com.android.wm.shell.flicker.helpers.LaunchBubbleHelper
import org.junit.runners.Parameterized
/**
@@ -47,7 +48,7 @@ abstract class BaseBubbleScreen(
ServiceManager.getService(Context.NOTIFICATION_SERVICE))
private val uid = context.packageManager.getApplicationInfo(
testApp.`package`, 0).uid
testApp.`package`, PackageManager.ApplicationInfoFlags.of(0)).uid
@JvmOverloads
protected open fun buildTransition(

View File

@@ -1,67 +0,0 @@
/*
* Copyright (C) 2020 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.wm.shell.flicker.helpers
import android.app.Instrumentation
import android.content.pm.PackageManager.FEATURE_LEANBACK
import android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY
import android.support.test.launcherhelper.LauncherStrategyFactory
import android.util.Log
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.compatibility.common.util.SystemUtil
import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.traces.common.IComponentNameMatcher
import java.io.IOException
abstract class BaseAppHelper(
instrumentation: Instrumentation,
launcherName: String,
component: IComponentNameMatcher
) : StandardAppHelper(
instrumentation,
launcherName,
component,
LauncherStrategyFactory.getInstance(instrumentation).launcherStrategy
) {
private val appSelector = By.pkg(`package`).depth(0)
protected val isTelevision: Boolean
get() = context.packageManager.run {
hasSystemFeature(FEATURE_LEANBACK) || hasSystemFeature(FEATURE_LEANBACK_ONLY)
}
val ui: UiObject2?
get() = uiDevice.findObject(appSelector)
fun waitUntilClosed(): Boolean {
return uiDevice.wait(Until.gone(appSelector), APP_CLOSE_WAIT_TIME_MS)
}
companion object {
private const val APP_CLOSE_WAIT_TIME_MS = 3_000L
fun executeShellCommand(instrumentation: Instrumentation, cmd: String) {
try {
SystemUtil.runShellCommand(instrumentation, cmd)
} catch (e: IOException) {
Log.e("BaseAppHelper", "executeShellCommand error! $e")
}
}
}
}

View File

@@ -1,27 +0,0 @@
/*
* Copyright (C) 2020 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.wm.shell.flicker.helpers
import android.app.Instrumentation
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.wm.shell.flicker.testapp.Components
class FixedAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
instrumentation,
Components.FixedActivity.LABEL,
Components.FixedActivity.COMPONENT.toFlickerComponent()
)

View File

@@ -1,76 +0,0 @@
/*
* Copyright (C) 2020 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.wm.shell.flicker.helpers
import android.app.Instrumentation
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.helpers.FIND_TIMEOUT
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.testapp.Components
open class ImeAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
instrumentation,
Components.ImeActivity.LABEL,
Components.ImeActivity.COMPONENT.toFlickerComponent()
) {
/**
* Opens the IME and wait for it to be displayed
*
* @param wmHelper Helper used to wait for WindowManager states
*/
open fun openIME(wmHelper: WindowManagerStateHelper) {
if (!isTelevision) {
val editText = uiDevice.wait(
Until.findObject(By.res(getPackage(), "plain_text_input")),
FIND_TIMEOUT)
require(editText != null) {
"Text field not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)"
}
editText.click()
wmHelper.StateSyncBuilder()
.withImeShown()
.waitForAndVerify()
} else {
// If we do the same thing as above - editText.click() - on TV, that's going to force TV
// into the touch mode. We really don't want that.
launchViaIntent(action = Components.ImeActivity.ACTION_OPEN_IME)
}
}
/**
* Opens the IME and wait for it to be gone
*
* @param wmHelper Helper used to wait for WindowManager states
*/
open fun closeIME(wmHelper: WindowManagerStateHelper) {
if (!isTelevision) {
uiDevice.pressBack()
// Using only the AccessibilityInfo it is not possible to identify if the IME is active
wmHelper.StateSyncBuilder()
.withImeGone()
.waitForAndVerify()
} else {
// While pressing the back button should close the IME on TV as well, it may also lead
// to the app closing. So let's instead just ask the app to close the IME.
launchViaIntent(action = Components.ImeActivity.ACTION_CLOSE_IME)
}
}
}

View File

@@ -1,32 +0,0 @@
/*
* Copyright (C) 2021 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.wm.shell.flicker.helpers
import android.app.Instrumentation
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.wm.shell.flicker.testapp.Components
class LaunchBubbleHelper(instrumentation: Instrumentation) : BaseAppHelper(
instrumentation,
Components.LaunchBubbleActivity.LABEL,
Components.LaunchBubbleActivity.COMPONENT.toFlickerComponent()
) {
companion object {
const val TIMEOUT_MS = 3_000L
}
}

View File

@@ -1,354 +0,0 @@
/*
* Copyright (C) 2020 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.wm.shell.flicker.helpers
import android.app.Instrumentation
import android.graphics.Point
import android.os.SystemClock
import android.view.InputDevice
import android.view.MotionEvent
import android.view.ViewConfiguration
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import com.android.launcher3.tapl.LauncherInstrumentation
import com.android.server.wm.traces.common.IComponentMatcher
import com.android.server.wm.traces.common.IComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.SPLIT_DECOR_MANAGER
import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
import com.android.wm.shell.flicker.testapp.Components
class SplitScreenHelper(
instrumentation: Instrumentation,
activityLabel: String,
componentInfo: IComponentNameMatcher
) : BaseAppHelper(instrumentation, activityLabel, componentInfo) {
companion object {
const val TIMEOUT_MS = 3_000L
const val DRAG_DURATION_MS = 1_000L
const val NOTIFICATION_SCROLLER = "notification_stack_scroller"
const val DIVIDER_BAR = "docked_divider_handle"
const val GESTURE_STEP_MS = 16L
const val LONG_PRESS_TIME_MS = 100L
private val notificationScrollerSelector: BySelector
get() = By.res(SYSTEM_UI_PACKAGE_NAME, NOTIFICATION_SCROLLER)
private val notificationContentSelector: BySelector
get() = By.text("Notification content")
private val dividerBarSelector: BySelector
get() = By.res(SYSTEM_UI_PACKAGE_NAME, DIVIDER_BAR)
fun getPrimary(instrumentation: Instrumentation): SplitScreenHelper =
SplitScreenHelper(
instrumentation,
Components.SplitScreenActivity.LABEL,
Components.SplitScreenActivity.COMPONENT.toFlickerComponent()
)
fun getSecondary(instrumentation: Instrumentation): SplitScreenHelper =
SplitScreenHelper(
instrumentation,
Components.SplitScreenSecondaryActivity.LABEL,
Components.SplitScreenSecondaryActivity.COMPONENT.toFlickerComponent()
)
fun getNonResizeable(instrumentation: Instrumentation): SplitScreenHelper =
SplitScreenHelper(
instrumentation,
Components.NonResizeableActivity.LABEL,
Components.NonResizeableActivity.COMPONENT.toFlickerComponent()
)
fun getSendNotification(instrumentation: Instrumentation): SplitScreenHelper =
SplitScreenHelper(
instrumentation,
Components.SendNotificationActivity.LABEL,
Components.SendNotificationActivity.COMPONENT.toFlickerComponent()
)
fun getIme(instrumentation: Instrumentation): SplitScreenHelper =
SplitScreenHelper(
instrumentation,
Components.ImeActivity.LABEL,
Components.ImeActivity.COMPONENT.toFlickerComponent()
)
fun waitForSplitComplete(
wmHelper: WindowManagerStateHelper,
primaryApp: IComponentMatcher,
secondaryApp: IComponentMatcher,
) {
wmHelper.StateSyncBuilder()
.withWindowSurfaceAppeared(primaryApp)
.withWindowSurfaceAppeared(secondaryApp)
.withSplitDividerVisible()
.waitForAndVerify()
}
fun enterSplit(
wmHelper: WindowManagerStateHelper,
tapl: LauncherInstrumentation,
primaryApp: SplitScreenHelper,
secondaryApp: SplitScreenHelper
) {
tapl.workspace.switchToOverview().dismissAllTasks()
primaryApp.launchViaIntent(wmHelper)
secondaryApp.launchViaIntent(wmHelper)
tapl.goHome()
wmHelper.StateSyncBuilder()
.withHomeActivityVisible()
.waitForAndVerify()
splitFromOverview(tapl)
waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
fun splitFromOverview(tapl: LauncherInstrumentation) {
// Note: The initial split position in landscape is different between tablet and phone.
// In landscape, tablet will let the first app split to right side, and phone will
// split to left side.
if (tapl.isTablet) {
tapl.workspace.switchToOverview().overviewActions
.clickSplit()
.currentTask
.open()
} else {
tapl.workspace.switchToOverview().currentTask
.tapMenu()
.tapSplitMenuItem()
.currentTask
.open()
}
SystemClock.sleep(TIMEOUT_MS)
}
fun dragFromNotificationToSplit(
instrumentation: Instrumentation,
device: UiDevice,
wmHelper: WindowManagerStateHelper
) {
val displayBounds = wmHelper.currentState.layerState
.displays.firstOrNull { !it.isVirtual }
?.layerStackSpace
?: error("Display not found")
// Pull down the notifications
device.swipe(
displayBounds.centerX(), 5,
displayBounds.centerX(), displayBounds.bottom, 20 /* steps */
)
SystemClock.sleep(TIMEOUT_MS)
// Find the target notification
val notificationScroller = device.wait(
Until.findObject(notificationScrollerSelector), TIMEOUT_MS
)
var notificationContent = notificationScroller.findObject(notificationContentSelector)
while (notificationContent == null) {
device.swipe(
displayBounds.centerX(), displayBounds.centerY(),
displayBounds.centerX(), displayBounds.centerY() - 150, 20 /* steps */
)
notificationContent = notificationScroller.findObject(notificationContentSelector)
}
// Drag to split
val dragStart = notificationContent.visibleCenter
val dragMiddle = Point(dragStart.x + 50, dragStart.y)
val dragEnd = Point(displayBounds.width / 4, displayBounds.width / 4)
val downTime = SystemClock.uptimeMillis()
touch(
instrumentation, MotionEvent.ACTION_DOWN, downTime, downTime,
TIMEOUT_MS, dragStart
)
// It needs a horizontal movement to trigger the drag
touchMove(
instrumentation, downTime, SystemClock.uptimeMillis(),
DRAG_DURATION_MS, dragStart, dragMiddle
)
touchMove(
instrumentation, downTime, SystemClock.uptimeMillis(),
DRAG_DURATION_MS, dragMiddle, dragEnd
)
// Wait for a while to start splitting
SystemClock.sleep(TIMEOUT_MS)
touch(
instrumentation, MotionEvent.ACTION_UP, downTime, SystemClock.uptimeMillis(),
GESTURE_STEP_MS, dragEnd
)
SystemClock.sleep(TIMEOUT_MS)
}
fun touch(
instrumentation: Instrumentation,
action: Int,
downTime: Long,
eventTime: Long,
duration: Long,
point: Point
) {
val motionEvent = MotionEvent.obtain(
downTime, eventTime, action, point.x.toFloat(), point.y.toFloat(), 0
)
motionEvent.source = InputDevice.SOURCE_TOUCHSCREEN
instrumentation.uiAutomation.injectInputEvent(motionEvent, true)
motionEvent.recycle()
SystemClock.sleep(duration)
}
fun touchMove(
instrumentation: Instrumentation,
downTime: Long,
eventTime: Long,
duration: Long,
from: Point,
to: Point
) {
val steps: Long = duration / GESTURE_STEP_MS
var currentTime = eventTime
var currentX = from.x.toFloat()
var currentY = from.y.toFloat()
val stepX = (to.x.toFloat() - from.x.toFloat()) / steps.toFloat()
val stepY = (to.y.toFloat() - from.y.toFloat()) / steps.toFloat()
for (i in 1..steps) {
val motionMove = MotionEvent.obtain(
downTime, currentTime, MotionEvent.ACTION_MOVE, currentX, currentY, 0
)
motionMove.source = InputDevice.SOURCE_TOUCHSCREEN
instrumentation.uiAutomation.injectInputEvent(motionMove, true)
motionMove.recycle()
currentTime += GESTURE_STEP_MS
if (i == steps - 1) {
currentX = to.x.toFloat()
currentY = to.y.toFloat()
} else {
currentX += stepX
currentY += stepY
}
SystemClock.sleep(GESTURE_STEP_MS)
}
}
fun longPress(
instrumentation: Instrumentation,
point: Point
) {
val downTime = SystemClock.uptimeMillis()
touch(instrumentation, MotionEvent.ACTION_DOWN, downTime, downTime, TIMEOUT_MS, point)
SystemClock.sleep(LONG_PRESS_TIME_MS)
touch(instrumentation, MotionEvent.ACTION_UP, downTime, downTime, TIMEOUT_MS, point)
}
fun createShortcutOnHotseatIfNotExist(
tapl: LauncherInstrumentation,
appName: String
) {
tapl.workspace.deleteAppIcon(tapl.workspace.getHotseatAppIcon(0))
val allApps = tapl.workspace.switchToAllApps()
allApps.freeze()
try {
allApps.getAppIcon(appName).dragToHotseat(0)
} finally {
allApps.unfreeze()
}
}
fun dragDividerToResizeAndWait(
device: UiDevice,
wmHelper: WindowManagerStateHelper
) {
val displayBounds = wmHelper.currentState.layerState
.displays.firstOrNull { !it.isVirtual }
?.layerStackSpace
?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
dividerBar.drag(Point(displayBounds.width * 1 / 3, displayBounds.height * 2 / 3))
wmHelper.StateSyncBuilder()
.withWindowSurfaceDisappeared(SPLIT_DECOR_MANAGER)
.waitForAndVerify()
}
fun dragDividerToDismissSplit(
device: UiDevice,
wmHelper: WindowManagerStateHelper,
dragToRight: Boolean,
dragToBottom: Boolean
) {
val displayBounds = wmHelper.currentState.layerState
.displays.firstOrNull { !it.isVirtual }
?.layerStackSpace
?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
dividerBar.drag(Point(
if (dragToRight) {
displayBounds.width * 4 / 5
} else {
displayBounds.width * 1 / 5
},
if (dragToBottom) {
displayBounds.height * 4 / 5
} else {
displayBounds.height * 1 / 5
}))
}
fun doubleTapDividerToSwitch(device: UiDevice) {
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
val interval = (ViewConfiguration.getDoubleTapTimeout() +
ViewConfiguration.getDoubleTapMinTime()) / 2
dividerBar.click()
SystemClock.sleep(interval.toLong())
dividerBar.click()
}
fun copyContentInSplit(
instrumentation: Instrumentation,
device: UiDevice,
sourceApp: IComponentNameMatcher,
destinationApp: IComponentNameMatcher,
) {
// Copy text from sourceApp
val textView = device.wait(Until.findObject(
By.res(sourceApp.packageName, "SplitScreenTest")), TIMEOUT_MS)
longPress(instrumentation, textView.getVisibleCenter())
val copyBtn = device.wait(Until.findObject(By.text("Copy")), TIMEOUT_MS)
copyBtn.click()
// Paste text to destinationApp
val editText = device.wait(Until.findObject(
By.res(destinationApp.packageName, "plain_text_input")), TIMEOUT_MS)
longPress(instrumentation, editText.getVisibleCenter())
val pasteBtn = device.wait(Until.findObject(By.text("Paste")), TIMEOUT_MS)
pasteBtn.click()
// Verify text
if (!textView.getText().contentEquals(editText.getText())) {
error("Fail to copy content in split")
}
}
}
}

View File

@@ -1,20 +0,0 @@
/*
* Copyright (C) 2021 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.
*/
@file:JvmName("CommonAssertions")
package com.android.wm.shell.flicker.pip
internal const val PIP_WINDOW_COMPONENT = "PipMenuActivity"

View File

@@ -28,16 +28,17 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.entireScreenCovered
import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.navBarLayerPositionAtStartAndEnd
import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule
import com.android.wm.shell.flicker.helpers.FixedAppHelper
import com.android.server.wm.flicker.testapp.ActivityOptions.Pip.ACTION_ENTER_PIP
import com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
import com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_ENTER_PIP
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
@@ -72,7 +73,7 @@ import org.junit.runners.Parameterized
class EnterPipToOtherOrientationTest(
testSpec: FlickerTestParameter
) : PipTransition(testSpec) {
private val testApp = FixedAppHelper(instrumentation)
private val testApp = FixedOrientationAppHelper(instrumentation)
private val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
private val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
@@ -127,7 +128,7 @@ class EnterPipToOtherOrientationTest(
}
/**
* Checks that the [ComponentMatcher.NAV_BAR] has the correct position at
* Checks that the [ComponentNameMatcher.NAV_BAR] has the correct position at
* the start and end of the transition
*/
@FlakyTest

View File

@@ -18,14 +18,14 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.wm.shell.flicker.helpers.FixedAppHelper
import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
import org.junit.Test
/**
* Base class for pip expand tests
*/
abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
protected val testApp = FixedAppHelper(instrumentation)
protected val testApp = FixedOrientationAppHelper(instrumentation)
/**
* Checks that the pip app window remains inside the display bounds throughout the whole

View File

@@ -18,9 +18,9 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
import com.android.server.wm.flicker.traces.region.RegionSubject
import com.android.wm.shell.flicker.Direction
import com.android.wm.shell.flicker.helpers.FixedAppHelper
import org.junit.Test
/**
@@ -29,7 +29,7 @@ import org.junit.Test
abstract class MovePipShelfHeightTransition(
testSpec: FlickerTestParameter
) : PipTransition(testSpec) {
protected val testApp = FixedAppHelper(instrumentation)
protected val testApp = FixedOrientationAppHelper(instrumentation)
/**
* Checks [pipApp] window remains visible throughout the animation

View File

@@ -24,11 +24,11 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ImeAppHelper
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.wm.shell.flicker.helpers.ImeAppHelper
import org.junit.Assume.assumeFalse
import org.junit.Before
import org.junit.FixMethodOrder

View File

@@ -25,10 +25,10 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
import com.android.wm.shell.flicker.helpers.FixedAppHelper
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
@@ -62,7 +62,7 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group4
open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
private val fixedApp = FixedAppHelper(instrumentation)
private val testApp = SimpleAppHelper(instrumentation)
private val screenBoundsStart = WindowUtils.getDisplayBounds(testSpec.startRotation)
private val screenBoundsEnd = WindowUtils.getDisplayBounds(testSpec.endRotation)
@@ -74,7 +74,7 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition {
setup {
fixedApp.launchViaIntent(wmHelper)
testApp.launchViaIntent(wmHelper)
setRotation(testSpec.startRotation)
}
transitions {
@@ -90,48 +90,48 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS
override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/**
* Checks that [fixedApp] layer is within [screenBoundsStart] at the start of the transition
* Checks that [testApp] layer is within [screenBoundsStart] at the start of the transition
*/
@Presubmit
@Test
fun fixedAppLayer_StartingBounds() {
testSpec.assertLayersStart {
visibleRegion(fixedApp).coversAtMost(screenBoundsStart)
visibleRegion(testApp).coversAtMost(screenBoundsStart)
}
}
/**
* Checks that [fixedApp] layer is within [screenBoundsEnd] at the end of the transition
* Checks that [testApp] layer is within [screenBoundsEnd] at the end of the transition
*/
@Presubmit
@Test
fun fixedAppLayer_EndingBounds() {
testSpec.assertLayersEnd {
visibleRegion(fixedApp).coversAtMost(screenBoundsEnd)
visibleRegion(testApp).coversAtMost(screenBoundsEnd)
}
}
/**
* Checks that [fixedApp] plus [pipApp] layers are within [screenBoundsEnd] at the start
* Checks that [testApp] plus [pipApp] layers are within [screenBoundsEnd] at the start
* of the transition
*/
@Presubmit
@Test
fun appLayers_StartingBounds() {
testSpec.assertLayersStart {
visibleRegion(fixedApp.or(pipApp)).coversExactly(screenBoundsStart)
visibleRegion(testApp.or(pipApp)).coversExactly(screenBoundsStart)
}
}
/**
* Checks that [fixedApp] plus [pipApp] layers are within [screenBoundsEnd] at the end
* Checks that [testApp] plus [pipApp] layers are within [screenBoundsEnd] at the end
* of the transition
*/
@Presubmit
@Test
fun appLayers_EndingBounds() {
testSpec.assertLayersEnd {
visibleRegion(fixedApp.or(pipApp)).coversExactly(screenBoundsEnd)
visibleRegion(testApp.or(pipApp)).coversExactly(screenBoundsEnd)
}
}
@@ -165,26 +165,26 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS
}
/**
* Ensure that the [pipApp] window does not obscure the [fixedApp] at the start of the
* Ensure that the [pipApp] window does not obscure the [testApp] at the start of the
* transition
*/
@Presubmit
@Test
fun pipIsAboveFixedAppWindow_Start() {
testSpec.assertWmStart {
isAboveWindow(pipApp, fixedApp)
isAboveWindow(pipApp, testApp)
}
}
/**
* Ensure that the [pipApp] window does not obscure the [fixedApp] at the end of the
* Ensure that the [pipApp] window does not obscure the [testApp] at the end of the
* transition
*/
@Presubmit
@Test
fun pipIsAboveFixedAppWindow_End() {
testSpec.assertWmEnd {
isAboveWindow(pipApp, fixedApp)
isAboveWindow(pipApp, testApp)
}
}

View File

@@ -21,12 +21,12 @@ import android.content.Intent
import android.view.Surface
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.PipAppHelper
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.wm.shell.flicker.BaseTest
import com.android.wm.shell.flicker.helpers.PipAppHelper
import com.android.wm.shell.flicker.testapp.Components
abstract class PipTransition(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
protected val pipApp = PipAppHelper(instrumentation)
@@ -61,11 +61,11 @@ abstract class PipTransition(testSpec: FlickerTestParameter) : BaseTest(testSpec
*
* @param eachRun If the pip app should be launched in each run (otherwise only 1x per test)
* @param stringExtras Arguments to pass to the PIP launch intent
* @param extraSpec Addicional segment of flicker specification
* @param extraSpec Additional segment of flicker specification
*/
@JvmOverloads
protected open fun buildTransition(
stringExtras: Map<String, String> = mapOf(Components.PipActivity.EXTRA_ENTER_PIP to "true"),
stringExtras: Map<String, String> = mapOf(ActivityOptions.Pip.EXTRA_ENTER_PIP to "true"),
extraSpec: FlickerBuilder.() -> Unit = {}
): FlickerBuilder.() -> Unit {
return {

View File

@@ -31,9 +31,9 @@ import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
import com.android.wm.shell.flicker.testapp.Components
import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
import org.junit.Assume
import org.junit.Before
import org.junit.FixMethodOrder
@@ -68,7 +68,7 @@ open class SetRequestedOrientationWhilePinnedTest(
pipApp.launchViaIntent(wmHelper, stringExtras = mapOf(
EXTRA_FIXED_ORIENTATION to ORIENTATION_LANDSCAPE.toString()))
// Enter PiP.
broadcastActionTrigger.doAction(Components.PipActivity.ACTION_ENTER_PIP)
broadcastActionTrigger.doAction(ActivityOptions.Pip.ACTION_ENTER_PIP)
// System bar may fade out during fixed rotation.
wmHelper.StateSyncBuilder()
.withPipShown()

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2020 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.wm.shell.flicker.pip.tv
import android.app.Instrumentation
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.helpers.PipAppHelper
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
/**
* Helper class for PIP app on AndroidTV
*/
open class PipAppHelperTv(instrumentation: Instrumentation) : PipAppHelper(instrumentation) {
private val appSelector = By.pkg(`package`).depth(0)
val ui: UiObject2?
get() = uiDevice.findObject(appSelector)
private fun focusOnObject(selector: BySelector): Boolean {
// We expect all the focusable UI elements to be arranged in a way so that it is possible
// to "cycle" over all them by clicking the D-Pad DOWN button, going back up to "the top"
// from "the bottom".
repeat(FOCUS_ATTEMPTS) {
uiDevice.findObject(selector)?.apply { if (isFocusedOrHasFocusedChild) return true }
?: error("The object we try to focus on is gone.")
uiDevice.pressDPadDown()
uiDevice.waitForIdle()
}
return false
}
override fun clickObject(resId: String) {
val selector = By.res(`package`, resId)
focusOnObject(selector) || error("Could not focus on `$resId` object")
uiDevice.pressDPadCenter()
}
@Deprecated(
"Use PipAppHelper.closePipWindow(wmHelper) instead",
ReplaceWith("closePipWindow(wmHelper)")
)
override fun closePipWindow() {
uiDevice.closeTvPipWindow()
}
/**
* Taps the pip window and dismisses it by clicking on the X button.
*/
override fun closePipWindow(wmHelper: WindowManagerStateHelper) {
uiDevice.closeTvPipWindow()
// Wait for animation to complete.
wmHelper.StateSyncBuilder()
.withPipGone()
.withHomeActivityVisible()
.waitForAndVerify()
}
fun waitUntilClosed(): Boolean {
val appSelector = By.pkg(`package`).depth(0)
return uiDevice.wait(Until.gone(appSelector), APP_CLOSE_WAIT_TIME_MS)
}
companion object {
private const val FOCUS_ATTEMPTS = 20
private const val APP_CLOSE_WAIT_TIME_MS = 3_000L
}
}

View File

@@ -21,7 +21,6 @@ import android.content.pm.PackageManager
import android.view.Surface
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.wm.shell.flicker.helpers.PipAppHelper
import org.junit.Before
import org.junit.runners.Parameterized
@@ -38,7 +37,7 @@ abstract class PipTestBase(
hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)
}
}
protected val testApp = PipAppHelper(instrumentation)
protected val testApp = PipAppHelperTv(instrumentation)
@Before
open fun televisionSetUp() {

View File

@@ -19,8 +19,8 @@ package com.android.wm.shell.flicker.pip.tv
import android.graphics.Rect
import androidx.test.filters.RequiresDevice
import androidx.test.uiautomator.UiObject2
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
import com.android.wm.shell.flicker.testapp.Components
import com.android.wm.shell.flicker.wait
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
@@ -165,44 +165,44 @@ class TvPipMenuTests : TvPipTestBase() {
enterPip_openMenu_assertShown()
// PiP menu should contain "No-Op", "Off" and "Clear" buttons...
uiDevice.findTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_NO_OP)
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_NO_OP)
?: fail("\"No-Op\" button should be shown in Pip menu")
uiDevice.findTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_OFF)
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_OFF)
?: fail("\"Off\" button should be shown in Pip menu")
uiDevice.findTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_CLEAR)
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
?: fail("\"Clear\" button should be shown in Pip menu")
// ... and should also contain the "Full screen" and "Close" buttons.
assertFullscreenAndCloseButtonsAreShown()
uiDevice.clickTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_OFF)
uiDevice.clickTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_OFF)
// Invoking the "Off" action should replace it with the "On" action/button and should
// remove the "No-Op" action/button. "Clear" action/button should remain in the menu ...
uiDevice.waitForTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_ON)
uiDevice.waitForTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_ON)
?: fail("\"On\" button should be shown in Pip for a corresponding custom action")
assertNull("\"No-Op\" button should not be shown in Pip menu",
uiDevice.findTvPipMenuElementWithDescription(
Components.PipActivity.MENU_ACTION_NO_OP))
uiDevice.findTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_CLEAR)
ActivityOptions.Pip.MENU_ACTION_NO_OP))
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
?: fail("\"Clear\" button should be shown in Pip menu")
// ... as well as the "Full screen" and "Close" buttons.
assertFullscreenAndCloseButtonsAreShown()
uiDevice.clickTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_CLEAR)
uiDevice.clickTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
// Invoking the "Clear" action should remove all the custom actions and their corresponding
// buttons, ...
uiDevice.waitUntilTvPipMenuElementWithDescriptionIsGone(
Components.PipActivity.MENU_ACTION_ON)?.also {
ActivityOptions.Pip.MENU_ACTION_ON)?.also {
isGone -> if (!isGone) fail("\"On\" button should not be shown in Pip menu")
}
assertNull("\"Off\" button should not be shown in Pip menu",
uiDevice.findTvPipMenuElementWithDescription(
Components.PipActivity.MENU_ACTION_OFF))
ActivityOptions.Pip.MENU_ACTION_OFF))
assertNull("\"Clear\" button should not be shown in Pip menu",
uiDevice.findTvPipMenuElementWithDescription(
Components.PipActivity.MENU_ACTION_CLEAR))
ActivityOptions.Pip.MENU_ACTION_CLEAR))
assertNull("\"No-Op\" button should not be shown in Pip menu",
uiDevice.findTvPipMenuElementWithDescription(
Components.PipActivity.MENU_ACTION_NO_OP))
ActivityOptions.Pip.MENU_ACTION_NO_OP))
// ... but the menu should still contain the "Full screen" and "Close" buttons.
assertFullscreenAndCloseButtonsAreShown()
@@ -217,11 +217,11 @@ class TvPipMenuTests : TvPipTestBase() {
enterPip_openMenu_assertShown()
// PiP menu should contain "No-Op", "Off" and "Clear" buttons for the custom actions...
uiDevice.findTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_NO_OP)
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_NO_OP)
?: fail("\"No-Op\" button should be shown in Pip menu")
uiDevice.findTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_OFF)
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_OFF)
?: fail("\"Off\" button should be shown in Pip menu")
uiDevice.findTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_CLEAR)
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
?: fail("\"Clear\" button should be shown in Pip menu")
// ... should also contain the "Full screen" and "Close" buttons, ...
assertFullscreenAndCloseButtonsAreShown()
@@ -231,7 +231,7 @@ class TvPipMenuTests : TvPipTestBase() {
assertNull("\"Pause\" button should not be shown in menu when there are custom actions",
uiDevice.findTvPipMenuElementWithDescription(pauseButtonDescription))
uiDevice.clickTvPipMenuElementWithDescription(Components.PipActivity.MENU_ACTION_CLEAR)
uiDevice.clickTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
// Invoking the "Clear" action should remove all the custom actions, which should bring up
// media buttons...
uiDevice.waitForTvPipMenuElementWithDescription(pauseButtonDescription)

View File

@@ -28,7 +28,6 @@ import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowKeepVisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerKeepVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsKeepVisible
import org.junit.FixMethodOrder
@@ -48,16 +47,16 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group1
class CopyContentInSplit(testSpec: FlickerTestParameter) : SplitScreenBase(testSpec) {
private val textEditApp = SplitScreenHelper.getIme(instrumentation)
private val textEditApp = SplitScreenUtils.getIme(instrumentation)
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, textEditApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, textEditApp)
}
transitions {
SplitScreenHelper.copyContentInSplit(
SplitScreenUtils.copyContentInSplit(
instrumentation, device, primaryApp, textEditApp)
}
}

View File

@@ -30,7 +30,6 @@ import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowBecomesInvisible
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesInvisible
import com.android.wm.shell.flicker.layerIsVisibleAtEnd
import com.android.wm.shell.flicker.splitAppLayerBoundsBecomesInvisible
@@ -57,14 +56,14 @@ class DismissSplitScreenByDivider (testSpec: FlickerTestParameter) : SplitScreen
get() = {
super.transition(this)
setup {
SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
}
transitions {
if (tapl.isTablet) {
SplitScreenHelper.dragDividerToDismissSplit(device, wmHelper,
SplitScreenUtils.dragDividerToDismissSplit(device, wmHelper,
dragToRight = false, dragToBottom = true)
} else {
SplitScreenHelper.dragDividerToDismissSplit(device, wmHelper,
SplitScreenUtils.dragDividerToDismissSplit(device, wmHelper,
dragToRight = true, dragToBottom = true)
}
wmHelper.StateSyncBuilder()

View File

@@ -28,7 +28,6 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.wm.shell.flicker.appWindowBecomesInvisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesInvisible
import com.android.wm.shell.flicker.splitAppLayerBoundsBecomesInvisible
import com.android.wm.shell.flicker.splitScreenDividerBecomesInvisible
@@ -56,7 +55,7 @@ class DismissSplitScreenByGoHome(
get() = {
super.transition(this)
setup {
SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
}
transitions {
tapl.goHome()

View File

@@ -29,7 +29,6 @@ import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowKeepVisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerKeepVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsChanges
import org.junit.FixMethodOrder
@@ -54,10 +53,10 @@ class DragDividerToResize (testSpec: FlickerTestParameter) : SplitScreenBase(tes
get() = {
super.transition(this)
setup {
SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
}
transitions {
SplitScreenHelper.dragDividerToResizeAndWait(device, wmHelper)
SplitScreenUtils.dragDividerToResizeAndWait(device, wmHelper)
}
}

View File

@@ -30,7 +30,6 @@ import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.layerIsVisibleAtEnd
import com.android.wm.shell.flicker.splitAppLayerBoundsBecomesVisibleByDrag
@@ -76,7 +75,7 @@ class EnterSplitScreenByDragFromAllApps(
.openAllApps()
.getAppIcon(secondaryApp.appName)
.dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
}

View File

@@ -31,7 +31,6 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.layerIsVisibleAtEnd
import com.android.wm.shell.flicker.splitAppLayerBoundsBecomesVisibleByDrag
@@ -60,7 +59,7 @@ class EnterSplitScreenByDragFromNotification(
testSpec: FlickerTestParameter
) : SplitScreenBase(testSpec) {
private val sendNotificationApp = SplitScreenHelper.getSendNotification(instrumentation)
private val sendNotificationApp = SplitScreenUtils.getSendNotification(instrumentation)
@Before
fun before() {
@@ -76,7 +75,7 @@ class EnterSplitScreenByDragFromNotification(
sendNotificationApp.launchViaIntent(wmHelper)
val sendNotification = device.wait(
Until.findObject(By.text("Send Notification")),
SplitScreenHelper.TIMEOUT_MS
SplitScreenUtils.TIMEOUT_MS
)
sendNotification?.click() ?: error("Send notification button not found")
@@ -84,8 +83,8 @@ class EnterSplitScreenByDragFromNotification(
primaryApp.launchViaIntent(wmHelper)
}
transitions {
SplitScreenHelper.dragFromNotificationToSplit(instrumentation, device, wmHelper)
SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, sendNotificationApp)
SplitScreenUtils.dragFromNotificationToSplit(instrumentation, device, wmHelper)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, sendNotificationApp)
}
teardown {
sendNotificationApp.exit(wmHelper)

View File

@@ -30,7 +30,6 @@ import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.layerIsVisibleAtEnd
import com.android.wm.shell.flicker.splitAppLayerBoundsBecomesVisibleByDrag
@@ -70,7 +69,7 @@ class EnterSplitScreenByDragFromTaskbar(
super.transition(this)
setup {
tapl.goHome()
SplitScreenHelper.createShortcutOnHotseatIfNotExist(
SplitScreenUtils.createShortcutOnHotseatIfNotExist(
tapl, secondaryApp.appName
)
primaryApp.launchViaIntent(wmHelper)
@@ -79,7 +78,7 @@ class EnterSplitScreenByDragFromTaskbar(
tapl.launchedAppState.taskbar
.getAppIcon(secondaryApp.appName)
.dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
}

View File

@@ -26,7 +26,6 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.layerIsVisibleAtEnd
import com.android.wm.shell.flicker.splitAppLayerBoundsBecomesVisible
@@ -64,8 +63,8 @@ class EnterSplitScreenFromOverview(testSpec: FlickerTestParameter) : SplitScreen
.waitForAndVerify()
}
transitions {
SplitScreenHelper.splitFromOverview(tapl)
SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
SplitScreenUtils.splitFromOverview(tapl)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
}

View File

@@ -21,12 +21,11 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.setRotation
import com.android.wm.shell.flicker.BaseTest
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
abstract class SplitScreenBase(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
protected val context: Context = instrumentation.context
protected val primaryApp = SplitScreenHelper.getPrimary(instrumentation)
protected val secondaryApp = SplitScreenHelper.getSecondary(instrumentation)
protected val primaryApp = SplitScreenUtils.getPrimary(instrumentation)
protected val secondaryApp = SplitScreenUtils.getSecondary(instrumentation)
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit

View File

@@ -0,0 +1,341 @@
/*
* 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.wm.shell.flicker.splitscreen
import android.app.Instrumentation
import android.graphics.Point
import android.os.SystemClock
import android.view.InputDevice
import android.view.MotionEvent
import android.view.ViewConfiguration
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import com.android.launcher3.tapl.LauncherInstrumentation
import com.android.server.wm.flicker.helpers.ImeAppHelper
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.helpers.NotificationAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.common.IComponentMatcher
import com.android.server.wm.traces.common.IComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
internal object SplitScreenUtils {
internal const val TIMEOUT_MS = 3_000L
private const val DRAG_DURATION_MS = 1_000L
private const val NOTIFICATION_SCROLLER = "notification_stack_scroller"
private const val DIVIDER_BAR = "docked_divider_handle"
private const val GESTURE_STEP_MS = 16L
private const val LONG_PRESS_TIME_MS = 100L
private val SPLIT_DECOR_MANAGER = ComponentNameMatcher("", "SplitDecorManager#")
private val notificationScrollerSelector: BySelector
get() = By.res(SYSTEM_UI_PACKAGE_NAME, NOTIFICATION_SCROLLER)
private val notificationContentSelector: BySelector
get() = By.text("Notification content")
private val dividerBarSelector: BySelector
get() = By.res(SYSTEM_UI_PACKAGE_NAME, DIVIDER_BAR)
fun getPrimary(instrumentation: Instrumentation): StandardAppHelper =
SimpleAppHelper(
instrumentation,
ActivityOptions.SplitScreen.Primary.LABEL,
ActivityOptions.SplitScreen.Primary.COMPONENT.toFlickerComponent()
)
fun getSecondary(instrumentation: Instrumentation): StandardAppHelper =
SimpleAppHelper(
instrumentation,
ActivityOptions.SplitScreen.Secondary.LABEL,
ActivityOptions.SplitScreen.Secondary.COMPONENT.toFlickerComponent()
)
fun getNonResizeable(instrumentation: Instrumentation): NonResizeableAppHelper =
NonResizeableAppHelper(instrumentation)
fun getSendNotification(instrumentation: Instrumentation): NotificationAppHelper =
NotificationAppHelper(instrumentation)
fun getIme(instrumentation: Instrumentation): ImeAppHelper =
ImeAppHelper(instrumentation)
fun waitForSplitComplete(
wmHelper: WindowManagerStateHelper,
primaryApp: IComponentMatcher,
secondaryApp: IComponentMatcher,
) {
wmHelper.StateSyncBuilder()
.withWindowSurfaceAppeared(primaryApp)
.withWindowSurfaceAppeared(secondaryApp)
.withSplitDividerVisible()
.waitForAndVerify()
}
fun enterSplit(
wmHelper: WindowManagerStateHelper,
tapl: LauncherInstrumentation,
primaryApp: StandardAppHelper,
secondaryApp: StandardAppHelper
) {
tapl.workspace.switchToOverview().dismissAllTasks()
primaryApp.launchViaIntent(wmHelper)
secondaryApp.launchViaIntent(wmHelper)
tapl.goHome()
wmHelper.StateSyncBuilder()
.withHomeActivityVisible()
.waitForAndVerify()
splitFromOverview(tapl)
waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
fun splitFromOverview(tapl: LauncherInstrumentation) {
// Note: The initial split position in landscape is different between tablet and phone.
// In landscape, tablet will let the first app split to right side, and phone will
// split to left side.
if (tapl.isTablet) {
tapl.workspace.switchToOverview().overviewActions
.clickSplit()
.currentTask
.open()
} else {
tapl.workspace.switchToOverview().currentTask
.tapMenu()
.tapSplitMenuItem()
.currentTask
.open()
}
SystemClock.sleep(TIMEOUT_MS)
}
fun dragFromNotificationToSplit(
instrumentation: Instrumentation,
device: UiDevice,
wmHelper: WindowManagerStateHelper
) {
val displayBounds = wmHelper.currentState.layerState
.displays.firstOrNull { !it.isVirtual }
?.layerStackSpace
?: error("Display not found")
// Pull down the notifications
device.swipe(
displayBounds.centerX(), 5,
displayBounds.centerX(), displayBounds.bottom, 20 /* steps */
)
SystemClock.sleep(TIMEOUT_MS)
// Find the target notification
val notificationScroller = device.wait(
Until.findObject(notificationScrollerSelector), TIMEOUT_MS
)
var notificationContent = notificationScroller.findObject(notificationContentSelector)
while (notificationContent == null) {
device.swipe(
displayBounds.centerX(), displayBounds.centerY(),
displayBounds.centerX(), displayBounds.centerY() - 150, 20 /* steps */
)
notificationContent = notificationScroller.findObject(notificationContentSelector)
}
// Drag to split
val dragStart = notificationContent.visibleCenter
val dragMiddle = Point(dragStart.x + 50, dragStart.y)
val dragEnd = Point(displayBounds.width / 4, displayBounds.width / 4)
val downTime = SystemClock.uptimeMillis()
touch(
instrumentation, MotionEvent.ACTION_DOWN, downTime, downTime,
TIMEOUT_MS, dragStart
)
// It needs a horizontal movement to trigger the drag
touchMove(
instrumentation, downTime, SystemClock.uptimeMillis(),
DRAG_DURATION_MS, dragStart, dragMiddle
)
touchMove(
instrumentation, downTime, SystemClock.uptimeMillis(),
DRAG_DURATION_MS, dragMiddle, dragEnd
)
// Wait for a while to start splitting
SystemClock.sleep(TIMEOUT_MS)
touch(
instrumentation, MotionEvent.ACTION_UP, downTime, SystemClock.uptimeMillis(),
GESTURE_STEP_MS, dragEnd
)
SystemClock.sleep(TIMEOUT_MS)
}
fun touch(
instrumentation: Instrumentation,
action: Int,
downTime: Long,
eventTime: Long,
duration: Long,
point: Point
) {
val motionEvent = MotionEvent.obtain(
downTime, eventTime, action, point.x.toFloat(), point.y.toFloat(), 0
)
motionEvent.source = InputDevice.SOURCE_TOUCHSCREEN
instrumentation.uiAutomation.injectInputEvent(motionEvent, true)
motionEvent.recycle()
SystemClock.sleep(duration)
}
fun touchMove(
instrumentation: Instrumentation,
downTime: Long,
eventTime: Long,
duration: Long,
from: Point,
to: Point
) {
val steps: Long = duration / GESTURE_STEP_MS
var currentTime = eventTime
var currentX = from.x.toFloat()
var currentY = from.y.toFloat()
val stepX = (to.x.toFloat() - from.x.toFloat()) / steps.toFloat()
val stepY = (to.y.toFloat() - from.y.toFloat()) / steps.toFloat()
for (i in 1..steps) {
val motionMove = MotionEvent.obtain(
downTime, currentTime, MotionEvent.ACTION_MOVE, currentX, currentY, 0
)
motionMove.source = InputDevice.SOURCE_TOUCHSCREEN
instrumentation.uiAutomation.injectInputEvent(motionMove, true)
motionMove.recycle()
currentTime += GESTURE_STEP_MS
if (i == steps - 1) {
currentX = to.x.toFloat()
currentY = to.y.toFloat()
} else {
currentX += stepX
currentY += stepY
}
SystemClock.sleep(GESTURE_STEP_MS)
}
}
fun longPress(
instrumentation: Instrumentation,
point: Point
) {
val downTime = SystemClock.uptimeMillis()
touch(instrumentation, MotionEvent.ACTION_DOWN, downTime, downTime, TIMEOUT_MS, point)
SystemClock.sleep(LONG_PRESS_TIME_MS)
touch(instrumentation, MotionEvent.ACTION_UP, downTime, downTime, TIMEOUT_MS, point)
}
fun createShortcutOnHotseatIfNotExist(
tapl: LauncherInstrumentation,
appName: String
) {
tapl.workspace.deleteAppIcon(tapl.workspace.getHotseatAppIcon(0))
val allApps = tapl.workspace.switchToAllApps()
allApps.freeze()
try {
allApps.getAppIcon(appName).dragToHotseat(0)
} finally {
allApps.unfreeze()
}
}
fun dragDividerToResizeAndWait(
device: UiDevice,
wmHelper: WindowManagerStateHelper
) {
val displayBounds = wmHelper.currentState.layerState
.displays.firstOrNull { !it.isVirtual }
?.layerStackSpace
?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
dividerBar.drag(Point(displayBounds.width * 1 / 3, displayBounds.height * 2 / 3))
wmHelper.StateSyncBuilder()
.withWindowSurfaceDisappeared(SPLIT_DECOR_MANAGER)
.waitForAndVerify()
}
fun dragDividerToDismissSplit(
device: UiDevice,
wmHelper: WindowManagerStateHelper,
dragToRight: Boolean,
dragToBottom: Boolean
) {
val displayBounds = wmHelper.currentState.layerState
.displays.firstOrNull { !it.isVirtual }
?.layerStackSpace
?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
dividerBar.drag(Point(
if (dragToRight) {
displayBounds.width * 4 / 5
} else {
displayBounds.width * 1 / 5
},
if (dragToBottom) {
displayBounds.height * 4 / 5
} else {
displayBounds.height * 1 / 5
}))
}
fun doubleTapDividerToSwitch(device: UiDevice) {
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
val interval = (ViewConfiguration.getDoubleTapTimeout() +
ViewConfiguration.getDoubleTapMinTime()) / 2
dividerBar.click()
SystemClock.sleep(interval.toLong())
dividerBar.click()
}
fun copyContentInSplit(
instrumentation: Instrumentation,
device: UiDevice,
sourceApp: IComponentNameMatcher,
destinationApp: IComponentNameMatcher,
) {
// Copy text from sourceApp
val textView = device.wait(Until.findObject(
By.res(sourceApp.packageName, "SplitScreenTest")), TIMEOUT_MS)
longPress(instrumentation, textView.visibleCenter)
val copyBtn = device.wait(Until.findObject(By.text("Copy")), TIMEOUT_MS)
copyBtn.click()
// Paste text to destinationApp
val editText = device.wait(Until.findObject(
By.res(destinationApp.packageName, "plain_text_input")), TIMEOUT_MS)
longPress(instrumentation, editText.visibleCenter)
val pasteBtn = device.wait(Until.findObject(By.text("Paste")), TIMEOUT_MS)
pasteBtn.click()
// Verify text
if (!textView.text.contentEquals(editText.text)) {
error("Fail to copy content in split")
}
}
}

View File

@@ -29,7 +29,6 @@ import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerIsVisibleAtEnd
import com.android.wm.shell.flicker.layerKeepVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
@@ -55,10 +54,10 @@ class SwitchAppByDoubleTapDivider (testSpec: FlickerTestParameter) : SplitScreen
get() = {
super.transition(this)
setup {
SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
}
transitions {
SplitScreenHelper.doubleTapDividerToSwitch(device)
SplitScreenUtils.doubleTapDividerToSwitch(device)
wmHelper.StateSyncBuilder()
.withAppTransitionIdle()
.waitForAndVerify()

View File

@@ -27,7 +27,6 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.splitScreenDividerBecomesVisible
@@ -48,13 +47,13 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group1
class SwitchBackToSplitFromAnotherApp(testSpec: FlickerTestParameter) : SplitScreenBase(testSpec) {
val thirdApp = SplitScreenHelper.getNonResizeable(instrumentation)
val thirdApp = SplitScreenUtils.getNonResizeable(instrumentation)
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
thirdApp.launchViaIntent(wmHelper)
wmHelper.StateSyncBuilder()
@@ -63,7 +62,7 @@ class SwitchBackToSplitFromAnotherApp(testSpec: FlickerTestParameter) : SplitScr
}
transitions {
tapl.launchedAppState.quickSwitchToPreviousApp()
SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
}

View File

@@ -27,7 +27,6 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.splitScreenDividerBecomesVisible
@@ -53,7 +52,7 @@ class SwitchBackToSplitFromHome(testSpec: FlickerTestParameter) : SplitScreenBas
get() = {
super.transition(this)
setup {
SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
tapl.goHome()
wmHelper.StateSyncBuilder()
@@ -62,7 +61,7 @@ class SwitchBackToSplitFromHome(testSpec: FlickerTestParameter) : SplitScreenBas
}
transitions {
tapl.workspace.quickSwitchToPreviousApp()
SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
}

View File

@@ -27,7 +27,6 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.wm.shell.flicker.appWindowBecomesVisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.splitScreenDividerBecomesVisible
@@ -53,7 +52,7 @@ class SwitchBackToSplitFromRecent(testSpec: FlickerTestParameter) : SplitScreenB
get() = {
super.transition(this)
setup {
SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
tapl.goHome()
wmHelper.StateSyncBuilder()
@@ -64,7 +63,7 @@ class SwitchBackToSplitFromRecent(testSpec: FlickerTestParameter) : SplitScreenB
tapl.workspace.switchToOverview()
.currentTask
.open()
SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
}

View File

@@ -1,35 +0,0 @@
// Copyright (C) 2020 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 {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// all of the 'license_kinds' from "frameworks_base_license"
// to get the below license kinds:
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["frameworks_base_license"],
}
android_test {
name: "WMShellFlickerTestApp",
srcs: ["**/*.java"],
sdk_version: "current",
test_suites: ["device-tests"],
}
java_library {
name: "wmshell-flicker-test-components",
srcs: ["src/**/Components.java"],
sdk_version: "test_current",
}

View File

@@ -1,147 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2020 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.wm.shell.flicker.testapp">
<uses-sdk android:minSdkVersion="29"
android:targetSdkVersion="29"/>
<application android:allowBackup="false"
android:supportsRtl="true">
<activity android:name=".FixedActivity"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:launchMode="singleTop"
android:theme="@style/CutoutShortEdges"
android:label="FixedApp"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".PipActivity"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:taskAffinity="com.android.wm.shell.flicker.testapp.PipActivity"
android:theme="@style/CutoutShortEdges"
android:launchMode="singleTop"
android:label="PipApp"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ImeActivity"
android:taskAffinity="com.android.wm.shell.flicker.testapp.ImeActivity"
android:theme="@style/CutoutShortEdges"
android:label="ImeApp"
android:launchMode="singleTop"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".SplitScreenActivity"
android:resizeableActivity="true"
android:taskAffinity="com.android.wm.shell.flicker.testapp.SplitScreenActivity"
android:theme="@style/CutoutShortEdges"
android:label="SplitScreenPrimaryApp"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".SplitScreenSecondaryActivity"
android:resizeableActivity="true"
android:taskAffinity="com.android.wm.shell.flicker.testapp.SplitScreenSecondaryActivity"
android:theme="@style/CutoutShortEdges"
android:label="SplitScreenSecondaryApp"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".SendNotificationActivity"
android:taskAffinity="com.android.wm.shell.flicker.testapp.SendNotificationActivity"
android:theme="@style/CutoutShortEdges"
android:label="SendNotificationApp"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".NonResizeableActivity"
android:resizeableActivity="false"
android:taskAffinity="com.android.wm.shell.flicker.testapp.NonResizeableActivity"
android:theme="@style/CutoutShortEdges"
android:label="NonResizeableApp"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".SimpleActivity"
android:taskAffinity="com.android.wm.shell.flicker.testapp.SimpleActivity"
android:theme="@style/CutoutShortEdges"
android:label="SimpleApp"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".LaunchBubbleActivity"
android:label="LaunchBubbleApp"
android:exported="true"
android:theme="@style/CutoutShortEdges"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".BubbleActivity"
android:label="BubbleApp"
android:exported="false"
android:theme="@style/CutoutShortEdges"
android:resizeableActivity="true" />
</application>
</manifest>

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusableInTouchMode="true"
android:background="@android:color/holo_green_light">
<EditText android:id="@+id/plain_text_input"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:inputType="text"/>
</LinearLayout>

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2020 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/holo_orange_light">
<TextView
android:id="@+id/NonResizeableTest"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical|center_horizontal"
android:text="NonResizeableActivity"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</LinearLayout>

View File

@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/black">
<Button
android:id="@+id/button_send_notification"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Send Notification" />
</RelativeLayout>

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_light">
</LinearLayout>

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2020 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/holo_blue_light">
<TextView
android:id="@+id/SplitScreenTest"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical|center_horizontal"
android:text="SecondaryActivity"
android:textAppearance="?android:attr/textAppearanceLarge"/>
</LinearLayout>

View File

@@ -1,108 +0,0 @@
/*
* Copyright (C) 2020 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.wm.shell.flicker.testapp;
import android.content.ComponentName;
public class Components {
public static final String PACKAGE_NAME = "com.android.wm.shell.flicker.testapp";
public static class SimpleActivity {
public static final String LABEL = "SimpleApp";
public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
PACKAGE_NAME + ".SimpleActivity");
}
public static class FixedActivity {
public static final String EXTRA_FIXED_ORIENTATION = "fixed_orientation";
public static final String LABEL = "FixedApp";
public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
PACKAGE_NAME + ".FixedActivity");
}
public static class NonResizeableActivity {
public static final String LABEL = "NonResizeableApp";
public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
PACKAGE_NAME + ".NonResizeableActivity");
}
public static class PipActivity {
// Test App > Pip Activity
public static final String LABEL = "PipApp";
public static final String MENU_ACTION_NO_OP = "No-Op";
public static final String MENU_ACTION_ON = "On";
public static final String MENU_ACTION_OFF = "Off";
public static final String MENU_ACTION_CLEAR = "Clear";
// Intent action that this activity dynamically registers to enter picture-in-picture
public static final String ACTION_ENTER_PIP = PACKAGE_NAME + ".PipActivity.ENTER_PIP";
// Intent action that this activity dynamically registers to set requested orientation.
// Will apply the oriention to the value set in the EXTRA_FIXED_ORIENTATION extra.
public static final String ACTION_SET_REQUESTED_ORIENTATION =
PACKAGE_NAME + ".PipActivity.SET_REQUESTED_ORIENTATION";
// Calls enterPictureInPicture() on creation
public static final String EXTRA_ENTER_PIP = "enter_pip";
// Sets the fixed orientation (can be one of {@link ActivityInfo.ScreenOrientation}
public static final String EXTRA_PIP_ORIENTATION = "fixed_orientation";
// Adds a click listener to finish this activity when it is clicked
public static final String EXTRA_TAP_TO_FINISH = "tap_to_finish";
public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
PACKAGE_NAME + ".PipActivity");
}
public static class ImeActivity {
public static final String LABEL = "ImeApp";
public static final String ACTION_CLOSE_IME =
PACKAGE_NAME + ".action.CLOSE_IME";
public static final String ACTION_OPEN_IME =
PACKAGE_NAME + ".action.OPEN_IME";
public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
PACKAGE_NAME + ".ImeActivity");
}
public static class SplitScreenActivity {
public static final String LABEL = "SplitScreenPrimaryApp";
public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
PACKAGE_NAME + ".SplitScreenActivity");
}
public static class SplitScreenSecondaryActivity {
public static final String LABEL = "SplitScreenSecondaryApp";
public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
PACKAGE_NAME + ".SplitScreenSecondaryActivity");
}
public static class SendNotificationActivity {
public static final String LABEL = "SendNotificationApp";
public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
PACKAGE_NAME + ".SendNotificationActivity");
}
public static class LaunchBubbleActivity {
public static final String LABEL = "LaunchBubbleApp";
public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
PACKAGE_NAME + ".LaunchBubbleActivity");
}
public static class BubbleActivity {
public static final String LABEL = "BubbleApp";
public static final ComponentName COMPONENT = new ComponentName(PACKAGE_NAME,
PACKAGE_NAME + ".BubbleActivity");
}
}

View File

@@ -1,66 +0,0 @@
/*
* 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.wm.shell.flicker.testapp;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
public class ImeActivity extends Activity {
private static final String ACTION_OPEN_IME =
"com.android.wm.shell.flicker.testapp.action.OPEN_IME";
private static final String ACTION_CLOSE_IME =
"com.android.wm.shell.flicker.testapp.action.CLOSE_IME";
private InputMethodManager mImm;
private View mEditText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowManager.LayoutParams p = getWindow().getAttributes();
p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
getWindow().setAttributes(p);
setContentView(R.layout.activity_ime);
mEditText = findViewById(R.id.plain_text_input);
mImm = getSystemService(InputMethodManager.class);
handleIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
final String action = intent.getAction();
if (ACTION_OPEN_IME.equals(action)) {
mEditText.requestFocus();
mImm.showSoftInput(mEditText, InputMethodManager.SHOW_FORCED);
} else if (ACTION_CLOSE_IME.equals(action)) {
mImm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
mEditText.clearFocus();
}
}
}

View File

@@ -1,29 +0,0 @@
/*
* Copyright (C) 2020 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.wm.shell.flicker.testapp;
import android.app.Activity;
import android.os.Bundle;
public class NonResizeableActivity extends Activity {
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_non_resizeable);
}
}

View File

@@ -1,33 +0,0 @@
/*
* 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.wm.shell.flicker.testapp;
import android.app.Activity;
import android.os.Bundle;
import android.view.WindowManager;
public class SimpleActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowManager.LayoutParams p = getWindow().getAttributes();
p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
getWindow().setAttributes(p);
setContentView(R.layout.activity_simple);
}
}

View File

@@ -21,13 +21,14 @@ import android.platform.test.annotations.Presubmit
import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.tapl.LauncherInstrumentation
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import org.junit.Assume
import org.junit.Test
/**
* Base test class containing common assertions for [ComponentMatcher.NAV_BAR],
* [ComponentMatcher.TASK_BAR], [ComponentMatcher.STATUS_BAR], and general assertions
* Base test class containing common assertions for [ComponentNameMatcher.NAV_BAR],
* [ComponentNameMatcher.TASK_BAR], [ComponentNameMatcher.STATUS_BAR], and general assertions
* (layers visible in consecutive states, entire screen covered, etc.)
*/
abstract class BaseTest @JvmOverloads constructor(
@@ -72,7 +73,7 @@ abstract class BaseTest @JvmOverloads constructor(
open fun entireScreenCovered() = testSpec.entireScreenCovered()
/**
* Checks that the [ComponentMatcher.NAV_BAR] layer is visible during the whole transition
* Checks that the [ComponentNameMatcher.NAV_BAR] layer is visible during the whole transition
*
* Note: Phones only
*/
@@ -84,7 +85,8 @@ abstract class BaseTest @JvmOverloads constructor(
}
/**
* Checks the position of the [ComponentMatcher.NAV_BAR] at the start and end of the transition
* Checks the position of the [ComponentNameMatcher.NAV_BAR] at the start and end of the
* transition
*
* Note: Phones only
*/
@@ -96,7 +98,7 @@ abstract class BaseTest @JvmOverloads constructor(
}
/**
* Checks that the [ComponentMatcher.NAV_BAR] window is visible during the whole transition
* Checks that the [ComponentNameMatcher.NAV_BAR] window is visible during the whole transition
*
* Note: Phones only
*/
@@ -108,8 +110,8 @@ abstract class BaseTest @JvmOverloads constructor(
}
/**
* Checks that the [ComponentMatcher.TASK_BAR] window is visible at the start and end of the
* transition
* Checks that the [ComponentNameMatcher.TASK_BAR] window is visible at the start and end of
* the transition
*
* Note: Large screen only
*/
@@ -121,7 +123,8 @@ abstract class BaseTest @JvmOverloads constructor(
}
/**
* Checks that the [ComponentMatcher.TASK_BAR] window is visible during the whole transition
* Checks that the [ComponentNameMatcher.TASK_BAR] window is visible during the whole
* transition
*
* Note: Large screen only
*/
@@ -133,7 +136,7 @@ abstract class BaseTest @JvmOverloads constructor(
}
/**
* Checks that the [ComponentMatcher.STATUS_BAR] layer is visible at the start and end
* Checks that the [ComponentNameMatcher.STATUS_BAR] layer is visible at the start and end
* of the transition
*/
@Presubmit
@@ -142,7 +145,7 @@ abstract class BaseTest @JvmOverloads constructor(
testSpec.statusBarLayerIsVisibleAtStartAndEnd()
/**
* Checks the position of the [ComponentMatcher.STATUS_BAR] at the start and end of the
* Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the start and end of the
* transition
*/
@Presubmit
@@ -150,7 +153,8 @@ abstract class BaseTest @JvmOverloads constructor(
open fun statusBarLayerPositionAtStartAndEnd() = testSpec.statusBarLayerPositionAtStartAndEnd()
/**
* Checks that the [ComponentMatcher.STATUS_BAR] window is visible during the whole transition
* Checks that the [ComponentNameMatcher.STATUS_BAR] window is visible during the whole
* transition
*/
@Presubmit
@Test

View File

@@ -33,12 +33,12 @@ import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelpe
import org.junit.Assume.assumeNotNull
class ActivityEmbeddingAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.ACTIVITY_EMBEDDING_LAUNCHER_NAME,
component: ComponentNameMatcher = MAIN_ACTIVITY_COMPONENT,
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
instr: Instrumentation,
launcherName: String = ActivityOptions.ActivityEmbedding.MainActivity.LABEL,
component: ComponentNameMatcher = MAIN_ACTIVITY_COMPONENT,
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
/**
@@ -47,8 +47,8 @@ class ActivityEmbeddingAppHelper @JvmOverloads constructor(
*/
fun launchPlaceholderSplit(wmHelper: WindowManagerStateHelper) {
val launchButton = uiDevice.wait(
Until.findObject(By.res(getPackage(), "launch_placeholder_split_button")),
FIND_TIMEOUT)
Until.findObject(By.res(getPackage(), "launch_placeholder_split_button")),
FIND_TIMEOUT)
require(launchButton != null) {
"Can't find launch placeholder split button on screen."
}
@@ -62,14 +62,15 @@ class ActivityEmbeddingAppHelper @JvmOverloads constructor(
companion object {
private const val TAG = "ActivityEmbeddingAppHelper"
val MAIN_ACTIVITY_COMPONENT = ActivityOptions
.ACTIVITY_EMBEDDING_MAIN_ACTIVITY_COMPONENT_NAME.toFlickerComponent()
val MAIN_ACTIVITY_COMPONENT =
ActivityOptions.ActivityEmbedding.MainActivity.COMPONENT.toFlickerComponent()
val PLACEHOLDER_PRIMARY_COMPONENT = ActivityOptions
.ACTIVITY_EMBEDDING_PLACEHOLDER_PRIMARY_ACTIVITY_COMPONENT_NAME.toFlickerComponent()
val PLACEHOLDER_PRIMARY_COMPONENT =
ActivityOptions.ActivityEmbedding.PlaceholderPrimaryActivity.COMPONENT
.toFlickerComponent()
val PLACEHOLDER_SECONDARY_COMPONENT = ActivityOptions
.ACTIVITY_EMBEDDING_PLACEHOLDER_SECONDARY_ACTIVITY_COMPONENT_NAME
val PLACEHOLDER_SECONDARY_COMPONENT =
ActivityOptions.ActivityEmbedding.PlaceholderSecondaryActivity.COMPONENT
.toFlickerComponent()
@JvmStatic

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.helpers
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
import com.android.server.wm.traces.common.ComponentNameMatcher
@@ -23,4 +23,4 @@ class AppPairsHelper(
instrumentation: Instrumentation,
activityLabel: String,
component: ComponentNameMatcher
) : BaseAppHelper(instrumentation, activityLabel, component)
) : StandardAppHelper(instrumentation, activityLabel, component)

View File

@@ -24,11 +24,11 @@ import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
class FixedOrientationAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.PORTRAIT_ONLY_ACTIVITY_LAUNCHER_NAME,
component: ComponentNameMatcher =
ActivityOptions.PORTRAIT_ONLY_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)
instr: Instrumentation,
launcherName: String = ActivityOptions.PortraitOnlyActivity.LABEL,
component: ComponentNameMatcher =
ActivityOptions.PortraitOnlyActivity.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)

View File

@@ -29,9 +29,8 @@ import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelpe
class GameAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.GAME_ACTIVITY_LAUNCHER_NAME,
component: ComponentNameMatcher =
ActivityOptions.GAME_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherName: String = ActivityOptions.Game.LABEL,
component: ComponentNameMatcher = ActivityOptions.Game.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy =
LauncherStrategyFactory.getInstance(instr).launcherStrategy,
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {

View File

@@ -32,9 +32,9 @@ class ImeAppAutoFocusHelper @JvmOverloads constructor(
instr: Instrumentation,
private val rotation: Int,
private val imePackageName: String = IME_PACKAGE,
launcherName: String = ActivityOptions.IME_ACTIVITY_AUTO_FOCUS_LAUNCHER_NAME,
launcherName: String = ActivityOptions.Ime.AutoFocusActivity.LABEL,
component: ComponentNameMatcher =
ActivityOptions.IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME.toFlickerComponent()
ActivityOptions.Ime.AutoFocusActivity.COMPONENT.toFlickerComponent()
) : ImeAppHelper(instr, launcherName, component) {
override fun openIME(wmHelper: WindowManagerStateHelper) {
// do nothing (the app is focused automatically)
@@ -62,21 +62,22 @@ class ImeAppAutoFocusHelper @JvmOverloads constructor(
fun startDialogThemedActivity(wmHelper: WindowManagerStateHelper) {
val button = uiDevice.wait(Until.findObject(By.res(getPackage(),
"start_dialog_themed_activity_btn")), FIND_TIMEOUT)
"start_dialog_themed_activity_btn")), FIND_TIMEOUT)
requireNotNull(button) {
"Button not found, this usually happens when the device " +
"was left in an unknown state (e.g. Screen turned off)"
"was left in an unknown state (e.g. Screen turned off)"
}
button.click()
wmHelper.StateSyncBuilder()
.withFullScreenApp(
ActivityOptions.DIALOG_THEMED_ACTIVITY_COMPONENT_NAME.toFlickerComponent())
ActivityOptions.DialogThemedActivity.COMPONENT.toFlickerComponent())
.waitForAndVerify()
}
fun dismissDialog(wmHelper: WindowManagerStateHelper) {
val dialog = uiDevice.wait(
Until.findObject(By.text("Dialog for test")), FIND_TIMEOUT)
Until.findObject(By.text("Dialog for test")), FIND_TIMEOUT)
// Pressing back key to dismiss the dialog
if (dialog != null) {
@@ -86,9 +87,10 @@ class ImeAppAutoFocusHelper @JvmOverloads constructor(
.waitForAndVerify()
}
}
fun getInsetsVisibleFromDialog(type: Int): Boolean {
val insetsVisibilityTextView = uiDevice.wait(
Until.findObject(By.res("android:id/text1")), FIND_TIMEOUT)
Until.findObject(By.res("android:id/text1")), FIND_TIMEOUT)
if (insetsVisibilityTextView != null) {
val visibility = insetsVisibilityTextView.text.toString()
val matcher = when (type) {

View File

@@ -28,12 +28,11 @@ import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelpe
open class ImeAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.IME_ACTIVITY_LAUNCHER_NAME,
launcherName: String = ActivityOptions.Ime.Default.LABEL,
component: ComponentNameMatcher =
ActivityOptions.IME_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
ActivityOptions.Ime.Default.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy =
LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
/**
* Opens the IME and wait for it to be displayed
@@ -73,8 +72,8 @@ open class ImeAppHelper @JvmOverloads constructor(
open fun finishActivity(wmHelper: WindowManagerStateHelper) {
val finishButton = uiDevice.wait(
Until.findObject(By.res(getPackage(), "finish_activity_btn")),
FIND_TIMEOUT)
Until.findObject(By.res(getPackage(), "finish_activity_btn")),
FIND_TIMEOUT)
requireNotNull(finishButton) {
"Finish activity button not found, probably IME activity is not on the screen?"
}

View File

@@ -26,16 +26,16 @@ import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelpe
class ImeEditorPopupDialogAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.EDITOR_POPUP_DIALOG_ACTIVITY_LAUNCHER_NAME,
launcherName: String = ActivityOptions.Ime.AutoFocusActivity.LABEL,
component: ComponentNameMatcher =
ActivityOptions.EDITOR_POPUP_DIALOG_ACTIVITY_COMPONENT_NAME.toFlickerComponent()
ActivityOptions.Ime.AutoFocusActivity.COMPONENT.toFlickerComponent()
) : ImeAppHelper(instr, launcherName, component) {
override fun openIME(wmHelper: WindowManagerStateHelper) {
val editText = uiDevice.wait(Until.findObject(By.text("focused editText")), FIND_TIMEOUT)
require(editText != null) {
requireNotNull(editText) {
"Text field not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)"
"was left in an unknown state (e.g. in split screen)"
}
editText.click()
waitIMEShown(wmHelper)
@@ -43,7 +43,7 @@ class ImeEditorPopupDialogAppHelper @JvmOverloads constructor(
fun dismissDialog(wmHelper: WindowManagerStateHelper) {
val dismissButton = uiDevice.wait(
Until.findObject(By.text("Dismiss")), FIND_TIMEOUT)
Until.findObject(By.text("Dismiss")), FIND_TIMEOUT)
// Pressing back key to dismiss the dialog
if (dismissButton != null) {

View File

@@ -25,10 +25,9 @@ import com.android.server.wm.traces.parser.toFlickerComponent
class ImeStateInitializeHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.IME_ACTIVITY_INITIALIZE_LAUNCHER_NAME,
launcherName: String = ActivityOptions.Ime.StateInitializeActivity.LABEL,
component: ComponentNameMatcher =
ActivityOptions.IME_ACTIVITY_INITIALIZE_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
ActivityOptions.Ime.StateInitializeActivity.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy =
LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)

View File

@@ -14,14 +14,14 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.helpers
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.wm.shell.flicker.testapp.Components
class SimpleAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
class LaunchBubbleHelper(instrumentation: Instrumentation) : StandardAppHelper(
instrumentation,
Components.SimpleActivity.LABEL,
Components.SimpleActivity.COMPONENT.toFlickerComponent()
)
ActivityOptions.Bubbles.LaunchBubble.LABEL,
ActivityOptions.Bubbles.LaunchBubble.COMPONENT.toFlickerComponent()
)

View File

@@ -28,13 +28,13 @@ import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
class MailAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.MAIL_ACTIVITY_LAUNCHER_NAME,
component: ComponentNameMatcher =
ActivityOptions.MAIL_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
instr: Instrumentation,
launcherName: String = ActivityOptions.Mail.LABEL,
component: ComponentNameMatcher =
ActivityOptions.Mail.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
fun openMail(rowIdx: Int) {
@@ -46,7 +46,7 @@ class MailAppHelper @JvmOverloads constructor(
if (row != null) break
scrollDown()
}
require(row != null) {""}
require(row != null) { "" }
row.click()
uiDevice.wait(Until.gone(By.res(getPackage(), MAIL_LIST_RES_ID)), FIND_TIMEOUT)
}
@@ -57,9 +57,9 @@ class MailAppHelper @JvmOverloads constructor(
}
fun waitForMailList(): UiObject2 {
var sel = By.res(getPackage(), MAIL_LIST_RES_ID).scrollable(true)
val sel = By.res(getPackage(), MAIL_LIST_RES_ID).scrollable(true)
val ret = uiDevice.wait(Until.findObject(sel), FIND_TIMEOUT)
require(ret != null) {""}
requireNotNull(ret) { "Unable to find $MAIL_LIST_RES_ID object" }
return ret
}

View File

@@ -14,20 +14,31 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.helpers
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
import android.content.Context
import android.provider.Settings
import android.util.Log
import com.android.compatibility.common.util.SystemUtil
import com.android.server.wm.traces.common.ComponentNameMatcher
import java.io.IOException
class MultiWindowHelper(
class MultiWindowUtils(
instrumentation: Instrumentation,
activityLabel: String,
componentsInfo: ComponentNameMatcher
) : BaseAppHelper(instrumentation, activityLabel, componentsInfo) {
) : StandardAppHelper(instrumentation, activityLabel, componentsInfo) {
companion object {
fun executeShellCommand(instrumentation: Instrumentation, cmd: String) {
try {
SystemUtil.runShellCommand(instrumentation, cmd)
} catch (e: IOException) {
Log.e(MultiWindowUtils::class.simpleName, "executeShellCommand error! $e")
}
}
fun getDevEnableNonResizableMultiWindow(context: Context): Int =
Settings.Global.getInt(context.contentResolver,
Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW)

View File

@@ -29,9 +29,9 @@ import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelpe
class NewTasksAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.LAUNCH_NEW_TASK_ACTIVITY_LAUNCHER_NAME,
launcherName: String = ActivityOptions.LaunchNewTask.LABEL,
component: ComponentNameMatcher =
ActivityOptions.LAUNCH_NEW_TASK_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
ActivityOptions.LaunchNewTask.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
@@ -43,7 +43,7 @@ class NewTasksAppHelper @JvmOverloads constructor(
requireNotNull(button) {
"Button not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)"
"was left in an unknown state (e.g. in split screen)"
}
button.click()
wmHelper.StateSyncBuilder()

View File

@@ -25,10 +25,9 @@ import com.android.server.wm.traces.parser.toFlickerComponent
class NonResizeableAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.NON_RESIZEABLE_ACTIVITY_LAUNCHER_NAME,
launcherName: String = ActivityOptions.NonResizeableActivity.LABEL,
component: ComponentNameMatcher =
ActivityOptions.NON_RESIZEABLE_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
ActivityOptions.NonResizeableActivity.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy =
LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)

View File

@@ -28,25 +28,28 @@ import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelpe
class NotificationAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.NOTIFICATION_ACTIVITY_LAUNCHER_NAME,
launcherName: String = ActivityOptions.Notification.LABEL,
component: ComponentNameMatcher =
ActivityOptions.NOTIFICATION_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
ActivityOptions.Notification.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
.getInstance(instr)
.launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
fun postNotification(wmHelper: WindowManagerStateHelper) {
val button = uiDevice.wait(
Until.findObject(By.res(getPackage(), "post_notification")),
FIND_TIMEOUT)
Until.findObject(By.res(getPackage(), "post_notification")),
FIND_TIMEOUT)
require(button != null) {
requireNotNull(button) {
"Post notification button not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)"
"was left in an unknown state (e.g. in split screen)"
}
button.click()
uiDevice.wait(Until.findObject(By.text("Flicker Test Notification")), FIND_TIMEOUT)
?: error("Flicker Notification not found")
?: error("Flicker Notification not found")
wmHelper.StateSyncBuilder()
.withAppTransitionIdle()
.waitForAndVerify()
}
}

View File

@@ -14,28 +14,23 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.helpers
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
import android.media.session.MediaController
import android.media.session.MediaSessionManager
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.helpers.FIND_TIMEOUT
import com.android.server.wm.flicker.helpers.SYSTEMUI_PACKAGE
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.Rect
import com.android.server.wm.traces.common.WindowManagerConditionsFactory
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import com.android.wm.shell.flicker.pip.tv.closeTvPipWindow
import com.android.wm.shell.flicker.pip.tv.isFocusedOrHasFocusedChild
import com.android.wm.shell.flicker.testapp.Components
class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
open class PipAppHelper(instrumentation: Instrumentation) : StandardAppHelper(
instrumentation,
Components.PipActivity.LABEL,
Components.PipActivity.COMPONENT.toFlickerComponent()
ActivityOptions.Pip.LABEL,
ActivityOptions.Pip.COMPONENT.toFlickerComponent()
) {
private val mediaSessionManager: MediaSessionManager
get() = context.getSystemService(MediaSessionManager::class.java)
@@ -46,16 +41,11 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
it.packageName == `package`
}
fun clickObject(resId: String) {
open fun clickObject(resId: String) {
val selector = By.res(`package`, resId)
val obj = uiDevice.findObject(selector) ?: error("Could not find `$resId` object")
if (!isTelevision) {
obj.click()
} else {
focusOnObject(selector) || error("Could not focus on `$resId` object")
uiDevice.pressDPadCenter()
}
obj.click()
}
/**
@@ -85,20 +75,6 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
fun exitPipToFullScreenViaIntent(wmHelper: WindowManagerStateHelper) =
launchViaIntentAndWaitShown(wmHelper)
private fun focusOnObject(selector: BySelector): Boolean {
// We expect all the focusable UI elements to be arranged in a way so that it is possible
// to "cycle" over all them by clicking the D-Pad DOWN button, going back up to "the top"
// from "the bottom".
repeat(FOCUS_ATTEMPTS) {
uiDevice.findObject(selector)?.apply { if (isFocusedOrHasFocusedChild) return true }
?: error("The object we try to focus on is gone.")
uiDevice.pressDPadDown()
uiDevice.waitForIdle()
}
return false
}
fun clickEnterPipButton(wmHelper: WindowManagerStateHelper) {
clickObject(ENTER_PIP_BUTTON_ID)
@@ -140,12 +116,8 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
"Use PipAppHelper.closePipWindow(wmHelper) instead",
ReplaceWith("closePipWindow(wmHelper)")
)
fun closePipWindow() {
if (isTelevision) {
uiDevice.closeTvPipWindow()
} else {
closePipWindow(WindowManagerStateHelper(mInstrumentation))
}
open fun closePipWindow() {
closePipWindow(WindowManagerStateHelper(mInstrumentation))
}
private fun getWindowRect(wmHelper: WindowManagerStateHelper): Rect {
@@ -159,20 +131,16 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
/**
* Taps the pip window and dismisses it by clicking on the X button.
*/
fun closePipWindow(wmHelper: WindowManagerStateHelper) {
if (isTelevision) {
uiDevice.closeTvPipWindow()
} else {
val windowRect = getWindowRect(wmHelper)
uiDevice.click(windowRect.centerX(), windowRect.centerY())
// search and interact with the dismiss button
val dismissSelector = By.res(SYSTEMUI_PACKAGE, "dismiss")
uiDevice.wait(Until.hasObject(dismissSelector), FIND_TIMEOUT)
val dismissPipObject = uiDevice.findObject(dismissSelector)
?: error("PIP window dismiss button not found")
val dismissButtonBounds = dismissPipObject.visibleBounds
uiDevice.click(dismissButtonBounds.centerX(), dismissButtonBounds.centerY())
}
open fun closePipWindow(wmHelper: WindowManagerStateHelper) {
val windowRect = getWindowRect(wmHelper)
uiDevice.click(windowRect.centerX(), windowRect.centerY())
// search and interact with the dismiss button
val dismissSelector = By.res(SYSTEMUI_PACKAGE, "dismiss")
uiDevice.wait(Until.hasObject(dismissSelector), FIND_TIMEOUT)
val dismissPipObject = uiDevice.findObject(dismissSelector)
?: error("PIP window dismiss button not found")
val dismissButtonBounds = dismissPipObject.visibleBounds
uiDevice.click(dismissButtonBounds.centerX(), dismissButtonBounds.centerY())
// Wait for animation to complete.
wmHelper.StateSyncBuilder()
@@ -213,7 +181,6 @@ class PipAppHelper(instrumentation: Instrumentation) : BaseAppHelper(
}
companion object {
private const val FOCUS_ATTEMPTS = 20
private const val ENTER_PIP_BUTTON_ID = "enter_pip"
private const val WITH_CUSTOM_ACTIONS_BUTTON_ID = "with_custom_actions"
private const val MEDIA_SESSION_START_RADIO_BUTTON_ID = "media_session_start"

View File

@@ -25,10 +25,9 @@ import com.android.server.wm.traces.parser.toFlickerComponent
class SeamlessRotationAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.SEAMLESS_ACTIVITY_LAUNCHER_NAME,
launcherName: String = ActivityOptions.SeamlessRotation.LABEL,
component: ComponentNameMatcher =
ActivityOptions.SEAMLESS_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
ActivityOptions.SeamlessRotation.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy =
LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)

View File

@@ -25,10 +25,9 @@ import com.android.server.wm.traces.parser.toFlickerComponent
class ShowWhenLockedAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.SHOW_WHEN_LOCKED_ACTIVITY_LAUNCHER_NAME,
launcherName: String = ActivityOptions.ShowWhenLockedActivity.LABEL,
component: ComponentNameMatcher =
ActivityOptions.SHOW_WHEN_LOCKED_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
ActivityOptions.ShowWhenLockedActivity.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy =
LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)

View File

@@ -25,10 +25,9 @@ import com.android.server.wm.traces.parser.toFlickerComponent
class SimpleAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.SIMPLE_ACTIVITY_LAUNCHER_NAME,
launcherName: String = ActivityOptions.SimpleActivity.LABEL,
component: ComponentNameMatcher =
ActivityOptions.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
ActivityOptions.SimpleActivity.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy =
LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)

View File

@@ -29,16 +29,15 @@ import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelpe
class TwoActivitiesAppHelper @JvmOverloads constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.BUTTON_ACTIVITY_LAUNCHER_NAME,
launcherName: String = ActivityOptions.LaunchNewActivity.LABEL,
component: ComponentNameMatcher =
ActivityOptions.BUTTON_ACTIVITY_COMPONENT_NAME.toFlickerComponent(),
launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
.getInstance(instr)
.launcherStrategy
ActivityOptions.LaunchNewActivity.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy =
LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
private val secondActivityComponent =
ActivityOptions.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME.toFlickerComponent()
ActivityOptions.SimpleActivity.COMPONENT.toFlickerComponent()
fun openSecondActivity(device: UiDevice, wmHelper: WindowManagerStateHelper) {
val launchActivityButton = By.res(getPackage(), LAUNCH_SECOND_ACTIVITY)
@@ -46,7 +45,7 @@ class TwoActivitiesAppHelper @JvmOverloads constructor(
requireNotNull(button) {
"Button not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)"
"was left in an unknown state (e.g. in split screen)"
}
button.click()

View File

@@ -83,19 +83,17 @@ class ActivitiesTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSp
override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/**
* Checks that the [ActivityOptions.BUTTON_ACTIVITY_COMPONENT_NAME] activity is visible at
* the start of the transition, that
* [ActivityOptions.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME] becomes visible during the
* transition, and that [ActivityOptions.BUTTON_ACTIVITY_COMPONENT_NAME] is again visible
* at the end
* Checks that the [ActivityOptions.LaunchNewActivity] activity is visible at
* the start of the transition, that [ActivityOptions.SimpleActivity] becomes visible during
* the transition, and that [ActivityOptions.LaunchNewActivity] is again visible at the end
*/
@Presubmit
@Test
fun finishSubActivity() {
val buttonActivityComponent = ActivityOptions
.BUTTON_ACTIVITY_COMPONENT_NAME.toFlickerComponent()
val imeAutoFocusActivityComponent = ActivityOptions
.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME.toFlickerComponent()
val buttonActivityComponent =
ActivityOptions.LaunchNewActivity.COMPONENT.toFlickerComponent()
val imeAutoFocusActivityComponent =
ActivityOptions.SimpleActivity.COMPONENT.toFlickerComponent()
testSpec.assertWm {
this.isAppWindowOnTop(buttonActivityComponent)
.then()
@@ -106,7 +104,7 @@ class ActivitiesTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSp
}
/**
* Checks that the [ComponentMatcher.LAUNCHER] window is not on top. The launcher cannot be
* Checks that the [ComponentNameMatcher.LAUNCHER] window is not on top. The launcher cannot be
* asserted with `isAppWindowVisible` because it contains 2 windows with the exact same name,
* and both are never simultaneously visible
*/
@@ -119,7 +117,7 @@ class ActivitiesTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSp
}
/**
* Checks that the [ComponentMatcher.LAUNCHER] layer is never visible during the transition
* Checks that the [ComponentNameMatcher.LAUNCHER] layer is never visible during the transition
*/
@Presubmit
@Test

View File

@@ -28,8 +28,7 @@ import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.NewTasksAppHelper
import com.android.server.wm.flicker.helpers.WindowUtils
import com.android.server.wm.flicker.testapp.ActivityOptions.LAUNCH_NEW_TASK_ACTIVITY_COMPONENT_NAME
import com.android.server.wm.flicker.testapp.ActivityOptions.SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.SPLASH_SCREEN
import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
@@ -105,7 +104,7 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
}
/**
* Check that the [ComponentMatcher.LAUNCHER] window is never visible when performing task
* Check that the [ComponentNameMatcher.LAUNCHER] window is never visible when performing task
* transitions.
* A solid color background should be shown above it.
*/
@@ -118,7 +117,7 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
}
/**
* Checks that the [ComponentMatcher.LAUNCHER] layer is never visible when performing task
* Checks that the [ComponentNameMatcher.LAUNCHER] layer is never visible when performing task
* transitions.
* A solid color background should be shown above it.
*/
@@ -246,8 +245,8 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
companion object {
private val LAUNCH_NEW_TASK_ACTIVITY =
LAUNCH_NEW_TASK_ACTIVITY_COMPONENT_NAME.toFlickerComponent()
private val SIMPLE_ACTIVITY = SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME.toFlickerComponent()
ActivityOptions.LaunchNewActivity.COMPONENT.toFlickerComponent()
private val SIMPLE_ACTIVITY = ActivityOptions.SimpleActivity.COMPONENT.toFlickerComponent()
private fun getWallpaperPackage(instrumentation: Instrumentation): IComponentMatcher? {
val wallpaperManager = WallpaperManager.getInstance(instrumentation.targetContext)

View File

@@ -90,7 +90,7 @@ open class SeamlessAppRotationTest(
testApp.launchViaIntent(
wmHelper,
stringExtras = mapOf(
ActivityOptions.EXTRA_STARVE_UI_THREAD
ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD
to testSpec.starveUiThread.toString()
)
)
@@ -164,20 +164,23 @@ open class SeamlessAppRotationTest(
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. App is full screen")
override fun statusBarLayerPositionAtStartAndEnd() { }
override fun statusBarLayerPositionAtStartAndEnd() {
}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. App is full screen")
override fun statusBarLayerIsVisibleAtStartAndEnd() { }
override fun statusBarLayerIsVisibleAtStartAndEnd() {
}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. App is full screen")
override fun statusBarWindowIsAlwaysVisible() { }
override fun statusBarWindowIsAlwaysVisible() {
}
/**
* Checks that the [ComponentMatcher.STATUS_BAR] window is invisible during the whole
* Checks that the [ComponentNameMatcher.STATUS_BAR] window is invisible during the whole
* transition
*/
@Presubmit
@@ -189,7 +192,7 @@ open class SeamlessAppRotationTest(
}
/**
* Checks that the [ComponentMatcher.STATUS_BAR] layer is invisible during the whole
* Checks that the [ComponentNameMatcher.STATUS_BAR] layer is invisible during the whole
* transition
*/
@Presubmit
@@ -218,14 +221,17 @@ open class SeamlessAppRotationTest(
companion object {
private val FlickerTestParameter.starveUiThread
get() = config.getOrDefault(ActivityOptions.EXTRA_STARVE_UI_THREAD, false) as Boolean
get() = config.getOrDefault(
ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD, false) as Boolean
private fun createConfig(
sourceConfig: FlickerTestParameter,
starveUiThread: Boolean
): FlickerTestParameter {
val newConfig = sourceConfig.config.toMutableMap()
.also { it[ActivityOptions.EXTRA_STARVE_UI_THREAD] = starveUiThread }
.also {
it[ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD] = starveUiThread
}
val nameExt = if (starveUiThread) "_BUSY_UI_THREAD" else ""
return FlickerTestParameter(newConfig, nameOverride = "$sourceConfig$nameExt")
}
@@ -233,8 +239,8 @@ open class SeamlessAppRotationTest(
/**
* Creates the test configurations for seamless rotation based on the default rotation
* tests from [FlickerTestParameterFactory.getConfigRotationTests], but adding an
* additional flag ([ActivityOptions.EXTRA_STARVE_UI_THREAD]) to indicate if the app
* should starve the UI thread of not
* additional flag ([ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD]) to indicate
* if the app should starve the UI thread of not
*/
@JvmStatic
private fun getConfigurations(): List<FlickerTestParameter> {

View File

@@ -15,41 +15,41 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.wm.flicker.testapp">
package="com.android.server.wm.flicker.testapp">
<uses-sdk android:minSdkVersion="29"
android:targetSdkVersion="29"/>
android:targetSdkVersion="29"/>
<application android:allowBackup="false"
android:supportsRtl="true">
android:supportsRtl="true">
<uses-library android:name="androidx.window.extensions" android:required="false"/>
<activity android:name=".SimpleActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.SimpleActivity"
android:theme="@style/CutoutShortEdges"
android:label="SimpleApp"
android:exported="true">
android:taskAffinity="com.android.server.wm.flicker.testapp.SimpleActivity"
android:theme="@style/CutoutShortEdges"
android:label="SimpleActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ImeActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivity"
android:theme="@style/CutoutShortEdges"
android:label="ImeApp"
android:exported="true">
android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivity"
android:theme="@style/CutoutShortEdges"
android:label="ImeActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ImeActivityAutoFocus"
android:theme="@style/CutoutShortEdges"
android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivityAutoFocus"
android:windowSoftInputMode="stateVisible"
android:configChanges="orientation|screenSize"
android:label="ImeAppAutoFocus"
android:exported="true">
android:theme="@style/CutoutShortEdges"
android:taskAffinity="com.android.server.wm.flicker.testapp.ImeActivityAutoFocus"
android:windowSoftInputMode="stateVisible"
android:configChanges="orientation|screenSize"
android:label="ImeAppAutoFocus"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
@@ -66,34 +66,34 @@
</intent-filter>
</activity>
<activity android:name=".SeamlessRotationActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.SeamlessRotationActivity"
android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="SeamlessApp"
android:exported="true">
android:taskAffinity="com.android.server.wm.flicker.testapp.SeamlessRotationActivity"
android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="SeamlessActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".NonResizeableActivity"
android:theme="@style/CutoutShortEdges"
android:resizeableActivity="false"
android:taskAffinity="com.android.server.wm.flicker.testapp.NonResizeableActivity"
android:label="NonResizeableApp"
android:exported="true"
android:showOnLockScreen="true">
android:theme="@style/CutoutShortEdges"
android:resizeableActivity="false"
android:taskAffinity="com.android.server.wm.flicker.testapp.NonResizeableActivity"
android:label="NonResizeableActivity"
android:exported="true"
android:showOnLockScreen="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ButtonActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.ButtonActivity"
android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="ButtonActivity"
android:exported="true">
<activity android:name=".LaunchNewActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.LaunchNewActivity"
android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="LaunchNewActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
@@ -111,55 +111,56 @@
</intent-filter>
</activity>
<activity android:name=".DialogThemedActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.DialogThemedActivity"
android:configChanges="orientation|screenSize"
android:theme="@style/DialogTheme"
android:label="DialogThemedActivity"
android:exported="true">
android:taskAffinity="com.android.server.wm.flicker.testapp.DialogThemedActivity"
android:configChanges="orientation|screenSize"
android:theme="@style/DialogTheme"
android:label="DialogThemedActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".PortraitOnlyActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.PortraitOnlyActivity"
android:theme="@style/CutoutShortEdges"
android:screenOrientation="portrait"
android:configChanges="orientation|screenSize"
android:exported="true">
android:taskAffinity="com.android.server.wm.flicker.testapp.PortraitOnlyActivity"
android:theme="@style/CutoutShortEdges"
android:screenOrientation="portrait"
android:configChanges="orientation|screenSize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ImeEditorPopupDialogActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.ImeEditorPopupDialogActivity"
android:configChanges="orientation|screenSize"
android:theme="@style/CutoutShortEdges"
android:label="ImeEditorPopupDialogActivity"
android:exported="true">
android:taskAffinity="com.android.server.wm.flicker.testapp.ImeEditorPopupDialogActivity"
android:configChanges="orientation|screenSize"
android:theme="@style/CutoutShortEdges"
android:label="ImeEditorPopupDialogActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".ShowWhenLockedActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.ShowWhenLockedActivity"
android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="ShowWhenLockedActivity"
android:showWhenLocked="true"
android:exported="true">
android:taskAffinity="com.android.server.wm.flicker.testapp.ShowWhenLockedActivity"
android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="ShowWhenLockedActivity"
android:showWhenLocked="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".NotificationActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.NotificationActivity"
android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:exported="true">
android:taskAffinity="com.android.server.wm.flicker.testapp.NotificationActivity"
android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize"
android:label="NotificationActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
@@ -173,8 +174,8 @@
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
@@ -193,42 +194,110 @@
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="false"/>
<activity android:name=".MailActivity"
android:exported="true"
android:label="MailApp"
android:taskAffinity="com.android.server.wm.flicker.testapp.MailActivity"
android:theme="@style/Theme.AppCompat.Light">
android:exported="true"
android:label="MailActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.MailActivity"
android:theme="@style/Theme.AppCompat.Light">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".GameActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.GameActivity"
android:immersive="true"
android:theme="@android:style/Theme.NoTitleBar"
android:configChanges="screenSize"
android:label="GameApp"
android:exported="true">
android:taskAffinity="com.android.server.wm.flicker.testapp.GameActivity"
android:immersive="true"
android:theme="@android:style/Theme.NoTitleBar"
android:configChanges="screenSize"
android:label="GameActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".PipActivity"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:taskAffinity="com.android.server.wm.flicker.testapp.PipActivity"
android:theme="@style/CutoutShortEdges"
android:launchMode="singleTop"
android:label="PipActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".SplitScreenActivity"
android:resizeableActivity="true"
android:taskAffinity="com.android.server.wm.flicker.testapp.SplitScreenActivity"
android:theme="@style/CutoutShortEdges"
android:label="SplitScreenPrimaryActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".SplitScreenSecondaryActivity"
android:resizeableActivity="true"
android:taskAffinity="com.android.server.wm.flicker.testapp.SplitScreenSecondaryActivity"
android:theme="@style/CutoutShortEdges"
android:label="SplitScreenSecondaryActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".SendNotificationActivity"
android:taskAffinity="com.android.server.wm.flicker.testapp.SendNotificationActivity"
android:theme="@style/CutoutShortEdges"
android:label="SendNotificationActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".LaunchBubbleActivity"
android:label="LaunchBubbleActivity"
android:exported="true"
android:theme="@style/CutoutShortEdges"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".BubbleActivity"
android:label="BubbleActivity"
android:exported="false"
android:theme="@style/CutoutShortEdges"
android:resizeableActivity="true"/>
<service
android:name=".AssistantInteractionSessionService"
android:exported="true"
android:permission="android.permission.BIND_VOICE_INTERACTION" />
android:permission="android.permission.BIND_VOICE_INTERACTION"/>
<service
android:name=".AssistantRecognitionService"
android:exported="true"
android:label="Test Voice Interaction Service">
<intent-filter>
<action android:name="android.speech.RecognitionService" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.speech.RecognitionService"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data
android:name="android.speech"
android:resource="@xml/recognition_service" />
android:resource="@xml/recognition_service"/>
</service>
<service
android:name=".AssistantInteractionService"
@@ -236,12 +305,12 @@
android:label="Test Voice Interaction Service"
android:permission="android.permission.BIND_VOICE_INTERACTION">
<intent-filter>
<action android:name="android.service.voice.VoiceInteractionService" />
<action android:name="android.service.voice.VoiceInteractionService"/>
</intent-filter>
<meta-data
android:name="android.voice_interaction"
android:resource="@xml/interaction_service" />
android:resource="@xml/interaction_service"/>
</service>
</application>
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
</manifest>

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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.
-->
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"

View File

@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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.
-->
~ 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"

View File

@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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.
-->
~ 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"

View File

@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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.
-->
~ 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.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/black">
<Button
android:id="@+id/button_send_notification"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Send Notification" />
</RelativeLayout>

View File

@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2020 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.
-->
~ 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"

View File

@@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2020 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.
-->
~ 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"

View File

@@ -14,21 +14,19 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@android:color/holo_blue_light">
<resources>
<style name="DefaultTheme" parent="@android:style/Theme.DeviceDefault">
<item name="android:windowBackground">@android:color/darker_gray</item>
</style>
<TextView
android:id="@+id/SplitScreenTest"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical|center_horizontal"
android:text="SecondaryActivity"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<style name="CutoutDefault" parent="@style/DefaultTheme">
<item name="android:windowLayoutInDisplayCutoutMode">default</item>
</style>
<style name="CutoutShortEdges" parent="@style/DefaultTheme">
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<style name="CutoutNever" parent="@style/DefaultTheme">
<item name="android:windowLayoutInDisplayCutoutMode">never</item>
</style>
</resources>
</LinearLayout>

View File

@@ -16,9 +16,6 @@
package com.android.server.wm.flicker.testapp;
import static com.android.server.wm.flicker.testapp.ActivityOptions.ACTIVITY_EMBEDDING_PLACEHOLDER_PRIMARY_ACTIVITY_COMPONENT_NAME;
import static com.android.server.wm.flicker.testapp.ActivityOptions.ACTIVITY_EMBEDDING_PLACEHOLDER_SECONDARY_ACTIVITY_COMPONENT_NAME;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
@@ -39,8 +36,6 @@ public class ActivityEmbeddingMainActivity extends Activity {
private static final String TAG = "ActivityEmbeddingMainActivity";
private static final float DEFAULT_SPLIT_RATIO = 0.5f;
private ActivityEmbeddingComponent mEmbeddingComponent;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -51,20 +46,24 @@ public class ActivityEmbeddingMainActivity extends Activity {
/** R.id.launch_placeholder_split_button onClick */
public void launchPlaceholderSplit(View view) {
startActivity(new Intent().setComponent(
ACTIVITY_EMBEDDING_PLACEHOLDER_PRIMARY_ACTIVITY_COMPONENT_NAME));
startActivity(
new Intent().setComponent(
ActivityOptions.ActivityEmbedding.PlaceholderPrimaryActivity.COMPONENT
)
);
}
private void initializeSplitRules() {
mEmbeddingComponent = ActivityEmbeddingAppHelper.getActivityEmbeddingComponent();
if (mEmbeddingComponent == null) {
ActivityEmbeddingComponent embeddingComponent =
ActivityEmbeddingAppHelper.getActivityEmbeddingComponent();
if (embeddingComponent == null) {
// Embedding not supported
Log.d(TAG, "ActivityEmbedding is not supported on this device");
finish();
return;
}
mEmbeddingComponent.setEmbeddingRules(getSplitRules());
embeddingComponent.setEmbeddingRules(getSplitRules());
}
private Set<EmbeddingRule> getSplitRules() {
@@ -72,10 +71,10 @@ public class ActivityEmbeddingMainActivity extends Activity {
final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule.Builder(
new Intent().setComponent(
ACTIVITY_EMBEDDING_PLACEHOLDER_SECONDARY_ACTIVITY_COMPONENT_NAME),
ActivityOptions.ActivityEmbedding.PlaceholderSecondaryActivity.COMPONENT),
activity -> activity instanceof ActivityEmbeddingPlaceholderPrimaryActivity,
intent -> intent.getComponent().equals(
ACTIVITY_EMBEDDING_PLACEHOLDER_PRIMARY_ACTIVITY_COMPONENT_NAME),
ActivityOptions.ActivityEmbedding.PlaceholderPrimaryActivity.COMPONENT),
windowMetrics -> true)
.setSplitRatio(DEFAULT_SPLIT_RATIO)
.build();

View File

@@ -19,94 +19,181 @@ package com.android.server.wm.flicker.testapp;
import android.content.ComponentName;
public class ActivityOptions {
public static final String EXTRA_STARVE_UI_THREAD = "StarveUiThread";
public static final String FLICKER_APP_PACKAGE = "com.android.server.wm.flicker.testapp";
public static final String SEAMLESS_ACTIVITY_LAUNCHER_NAME = "SeamlessApp";
public static final ComponentName SEAMLESS_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".SeamlessRotationActivity");
public static class SimpleActivity {
public static final String LABEL = "SimpleActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".SimpleActivity");
}
public static final String IME_ACTIVITY_AUTO_FOCUS_LAUNCHER_NAME = "ImeAppAutoFocus";
public static final ComponentName IME_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ImeActivityAutoFocus");
public static class SeamlessRotation {
public static final String LABEL = "SeamlessRotationActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".SeamlessRotationActivity");
public static final String IME_ACTIVITY_LAUNCHER_NAME = "ImeActivity";
public static final ComponentName IME_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
public static final String EXTRA_STARVE_UI_THREAD = "StarveUiThread";
}
public static class Ime {
public static class Default {
public static final String LABEL = "ImeActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ImeActivity");
}
public static final String IME_ACTIVITY_INITIALIZE_LAUNCHER_NAME = "ImeStateInitializeActivity";
public static final ComponentName IME_ACTIVITY_INITIALIZE_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
public static class AutoFocusActivity {
public static final String LABEL = "ImeAppAutoFocus";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ImeActivityAutoFocus");
}
public static class StateInitializeActivity {
public static final String LABEL = "ImeStateInitializeActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ImeStateInitializeActivity");
}
public static final String SIMPLE_ACTIVITY_LAUNCHER_NAME = "SimpleApp";
public static final ComponentName SIMPLE_ACTIVITY_AUTO_FOCUS_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".SimpleActivity");
public static final String NON_RESIZEABLE_ACTIVITY_LAUNCHER_NAME = "NonResizeableApp";
public static final ComponentName NON_RESIZEABLE_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".NonResizeableActivity");
public static final String BUTTON_ACTIVITY_LAUNCHER_NAME = "ButtonApp";
public static final ComponentName BUTTON_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ButtonActivity");
public static final String LAUNCH_NEW_TASK_ACTIVITY_LAUNCHER_NAME = "LaunchNewTaskApp";
public static final ComponentName LAUNCH_NEW_TASK_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".LaunchNewTaskActivity");
public static final String DIALOG_THEMED_ACTIVITY = "DialogThemedActivity";
public static final ComponentName DIALOG_THEMED_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".DialogThemedActivity");
public static final String PORTRAIT_ONLY_ACTIVITY_LAUNCHER_NAME = "PortraitOnlyActivity";
public static final ComponentName PORTRAIT_ONLY_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".PortraitOnlyActivity");
public static final String EDITOR_POPUP_DIALOG_ACTIVITY_LAUNCHER_NAME =
"ImeEditorPopupDialogActivity";
public static final ComponentName EDITOR_POPUP_DIALOG_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
public static class EditorPopupDialogActivity {
public static final String LABEL = "ImeEditorPopupDialogActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ImeEditorPopupDialogActivity");
}
}
public static final String SHOW_WHEN_LOCKED_ACTIVITY_LAUNCHER_NAME = "ShowWhenLockedApp";
public static final ComponentName SHOW_WHEN_LOCKED_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ShowWhenLockedActivity");
public static class NonResizeableActivity {
public static final String LABEL = "NonResizeableActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".NonResizeableActivity");
}
public static final String NOTIFICATION_ACTIVITY_LAUNCHER_NAME = "NotificationApp";
public static final ComponentName NOTIFICATION_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".NotificationActivity");
public static class DialogThemedActivity {
public static final String LABEL = "DialogThemedActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".DialogThemedActivity");
}
public static final String ACTIVITY_EMBEDDING_LAUNCHER_NAME = "ActivityEmbeddingMainActivity";
public static final ComponentName ACTIVITY_EMBEDDING_MAIN_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
public static class PortraitOnlyActivity {
public static final String LABEL = "PortraitOnlyActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".PortraitOnlyActivity");
public static final String EXTRA_FIXED_ORIENTATION = "fixed_orientation";
}
public static class ActivityEmbedding {
public static class MainActivity {
public static final String LABEL = "ActivityEmbeddingMainActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ActivityEmbeddingMainActivity");
public static final ComponentName
ACTIVITY_EMBEDDING_PLACEHOLDER_PRIMARY_ACTIVITY_COMPONENT_NAME = new ComponentName(
FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ActivityEmbeddingPlaceholderPrimaryActivity");
public static final ComponentName
ACTIVITY_EMBEDDING_PLACEHOLDER_SECONDARY_ACTIVITY_COMPONENT_NAME = new ComponentName(
FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ActivityEmbeddingPlaceholderSecondaryActivity");
}
public static final String MAIL_ACTIVITY_LAUNCHER_NAME = "MailActivity";
public static final ComponentName MAIL_ACTIVITY_COMPONENT_NAME = new ComponentName(
FLICKER_APP_PACKAGE, FLICKER_APP_PACKAGE + ".MailActivity");
public static class PlaceholderPrimaryActivity {
public static final String LABEL = "ActivityEmbeddingPlaceholderPrimaryActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ActivityEmbeddingPlaceholderPrimaryActivity");
}
public static final String GAME_ACTIVITY_LAUNCHER_NAME = "GameApp";
public static final ComponentName GAME_ACTIVITY_COMPONENT_NAME =
new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".GameActivity");
public static class PlaceholderSecondaryActivity {
public static final String LABEL = "ActivityEmbeddingPlaceholderSecondaryActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ActivityEmbeddingPlaceholderSecondaryActivity");
}
}
public static class Notification {
public static final String LABEL = "NotificationActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".NotificationActivity");
}
public static class Mail {
public static final String LABEL = "MailActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".MailActivity");
}
public static class ShowWhenLockedActivity {
public static final String LABEL = "ShowWhenLockedActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".ShowWhenLockedActivity");
}
public static class LaunchNewTask {
public static final String LABEL = "LaunchNewTaskActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".LaunchNewTaskActivity");
}
public static class Game {
public static final String LABEL = "GameActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".GameActivity");
}
public static class LaunchNewActivity {
public static final String LABEL = "LaunchNewActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".LaunchNewActivity");
}
public static class Pip {
// Test App > Pip Activity
public static final String LABEL = "PipActivity";
public static final String MENU_ACTION_NO_OP = "No-Op";
public static final String MENU_ACTION_ON = "On";
public static final String MENU_ACTION_OFF = "Off";
public static final String MENU_ACTION_CLEAR = "Clear";
// Intent action that this activity dynamically registers to enter picture-in-picture
public static final String ACTION_ENTER_PIP =
FLICKER_APP_PACKAGE + ".PipActivity.ENTER_PIP";
// Intent action that this activity dynamically registers to set requested orientation.
// Will apply the oriention to the value set in the EXTRA_FIXED_ORIENTATION extra.
public static final String ACTION_SET_REQUESTED_ORIENTATION =
FLICKER_APP_PACKAGE + ".PipActivity.SET_REQUESTED_ORIENTATION";
// Calls enterPictureInPicture() on creation
public static final String EXTRA_ENTER_PIP = "enter_pip";
// Sets the fixed orientation (can be one of {@link ActivityInfo.ScreenOrientation}
public static final String EXTRA_PIP_ORIENTATION = "fixed_orientation";
// Adds a click listener to finish this activity when it is clicked
public static final String EXTRA_TAP_TO_FINISH = "tap_to_finish";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".PipActivity");
}
public static class SplitScreen {
public static class Primary {
public static final String LABEL = "SplitScreenPrimaryActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".SplitScreenActivity");
}
public static class Secondary {
public static final String LABEL = "SplitScreenSecondaryActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".SplitScreenSecondaryActivity");
}
}
public static class SendNotificationActivity {
public static final String LABEL = "SendNotificationActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".SendNotificationActivity");
}
public static class Bubbles {
public static class LaunchBubble {
public static final String LABEL = "LaunchBubbleActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".LaunchBubbleActivity");
}
public static class BubbleActivity {
public static final String LABEL = "BubbleActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
FLICKER_APP_PACKAGE + ".BubbleActivity");
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.testapp;
package com.android.server.wm.flicker.testapp;
import android.app.Activity;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 The Android Open Source Project
* 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.testapp;
package com.android.server.wm.flicker.testapp;
import android.app.Notification;
@@ -86,7 +86,7 @@ public class BubbleHelper {
}
private int getNextNotifyId() {
private int getNextNotifyId() {
int id = mNextNotifyId;
mNextNotifyId++;
return id;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* 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.
@@ -14,9 +14,9 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.testapp;
package com.android.server.wm.flicker.testapp;
import static com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION;
import static com.android.server.wm.flicker.testapp.ActivityOptions.PortraitOnlyActivity.EXTRA_FIXED_ORIENTATION;
import android.os.Bundle;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 The Android Open Source Project
* 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.testapp;
package com.android.server.wm.flicker.testapp;
import android.app.Activity;

View File

@@ -22,7 +22,7 @@ import android.os.Bundle;
import android.view.WindowManager;
import android.widget.Button;
public class ButtonActivity extends Activity {
public class LaunchNewActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -30,11 +30,11 @@ public class ButtonActivity extends Activity {
p.layoutInDisplayCutoutMode = WindowManager.LayoutParams
.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
getWindow().setAttributes(p);
setContentView(R.layout.activity_button);
setContentView(R.layout.activity_launch_new);
Button button = findViewById(R.id.launch_second_activity);
button.setOnClickListener(v -> {
Intent intent = new Intent(ButtonActivity.this, SimpleActivity.class);
Intent intent = new Intent(LaunchNewActivity.this, SimpleActivity.class);
startActivity(intent);
});
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.testapp;
package com.android.server.wm.flicker.testapp;
import static android.media.MediaMetadata.METADATA_KEY_TITLE;
import static android.media.session.PlaybackState.ACTION_PAUSE;
@@ -24,10 +24,10 @@ import static android.media.session.PlaybackState.STATE_PAUSED;
import static android.media.session.PlaybackState.STATE_PLAYING;
import static android.media.session.PlaybackState.STATE_STOPPED;
import static com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_ENTER_PIP;
import static com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_SET_REQUESTED_ORIENTATION;
import static com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP;
import static com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_PIP_ORIENTATION;
import static com.android.server.wm.flicker.testapp.ActivityOptions.Pip.ACTION_ENTER_PIP;
import static com.android.server.wm.flicker.testapp.ActivityOptions.Pip.ACTION_SET_REQUESTED_ORIENTATION;
import static com.android.server.wm.flicker.testapp.ActivityOptions.Pip.EXTRA_ENTER_PIP;
import static com.android.server.wm.flicker.testapp.ActivityOptions.Pip.EXTRA_PIP_ORIENTATION;
import android.app.Activity;
import android.app.PendingIntent;
@@ -127,7 +127,6 @@ public class PipActivity extends Activity {
break;
default:
Log.w(TAG, "Unhandled action=" + intent.getAction());
return;
}
}
}

View File

@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.testapp;
import static android.os.SystemClock.sleep;
import static com.android.server.wm.flicker.testapp.ActivityOptions.EXTRA_STARVE_UI_THREAD;
import static com.android.server.wm.flicker.testapp.ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD;
import android.app.Activity;
import android.os.Bundle;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.testapp;
package com.android.server.wm.flicker.testapp;
import android.app.Activity;
import android.app.Notification;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.testapp;
package com.android.server.wm.flicker.testapp;
import android.app.Activity;
import android.os.Bundle;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.wm.shell.flicker.testapp;
package com.android.server.wm.flicker.testapp;
import android.app.Activity;
import android.os.Bundle;