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:
committed by
Android (Google) Code Review
commit
71cb599df4
@@ -48,6 +48,6 @@ android_test {
|
||||
"wm-flicker-common-assertions",
|
||||
"wm-flicker-common-app-helpers",
|
||||
"platform-test-annotations",
|
||||
"wmshell-flicker-test-components",
|
||||
"flickertestapplib",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
)
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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?"
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
@@ -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>
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user