• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.platform.systemui_tapl.ui
18 
19 import android.graphics.PointF
20 import android.platform.helpers.CommonUtils
21 import android.platform.systemui_tapl.ui.Bubble.Companion.bubbleViews
22 import android.platform.systemui_tapl.utils.DeviceUtils.launcherResSelector
23 import android.platform.systemui_tapl.utils.DeviceUtils.sysuiResSelector
24 import android.platform.uiautomatorhelpers.BetterSwipe
25 import android.platform.uiautomatorhelpers.DeviceHelpers.assertVisible
26 import android.platform.uiautomatorhelpers.DeviceHelpers.context
27 import android.platform.uiautomatorhelpers.DeviceHelpers.hasObject
28 import android.platform.uiautomatorhelpers.DeviceHelpers.uiDevice
29 import android.platform.uiautomatorhelpers.DeviceHelpers.waitForNullableObj
30 import android.platform.uiautomatorhelpers.DeviceHelpers.waitForObj
31 import android.platform.uiautomatorhelpers.FLING_GESTURE_INTERPOLATOR
32 import android.view.WindowInsets
33 import android.view.WindowManager
34 import android.view.WindowMetrics
35 import androidx.test.uiautomator.UiObject2
36 import com.android.launcher3.tapl.LauncherInstrumentation
37 import com.google.common.truth.Truth.assertWithMessage
38 import java.time.Duration
39 import java.time.temporal.ChronoUnit.MILLIS
40 
41 /** System UI test automation object representing the expanded bubble stack. */
42 class ExpandedBubbleStack internal constructor() {
43     init {
44         BUBBLE_EXPANDED_VIEW.assertVisible(timeout = FIND_OBJECT_TIMEOUT) {
45             "Bubbles expanded view should be visible"
46         }
47     }
48 
49     /** Returns all bubbles. */
50     val bubbles: List<Bubble>
51         get() = bubbleViews.map { bubbleView: UiObject2 -> Bubble(bubbleView) }
52 
53     /** Clicks the overflow button and returns the overflow panel that appears. */
54     fun openOverflow(): BubbleOverflow {
55         bubbleOverflow.click()
56         return BubbleOverflow()
57     }
58 
59     /** Closes the stack by swiping up. */
60     fun closeBySwiping() {
61         val windowBounds = windowMetrics.bounds
62         val x = windowBounds.width() / 2f
63         // Move up by 1 pixel to ensure tap begins on screen.
64         val startY = windowBounds.bottom - 1f
65         // From bottom middle of screen
66         val from = PointF(x, startY)
67         // To middle of screen
68         val to = PointF(x, startY / 2)
69         // Use a custom duration for bubble swipe to reduce flakiness on slow device.
70         BetterSwipe.swipe(
71             from,
72             to,
73             duration = Duration.of(700, MILLIS),
74             interpolator = FLING_GESTURE_INTERPOLATOR,
75         )
76         Root.get().verifyNoExpandedBubbleIsVisible()
77     }
78 
79     /** Closes the stack by the "back" gesture. */
80     fun closeByBackGesture() {
81         LauncherInstrumentation().pressBack()
82         Root.get().verifyNoExpandedBubbleIsVisible()
83     }
84 
85     /** Closes the stack by clicking outside. */
86     fun closeByClickingOutside() {
87         val gestureInsets =
88             windowMetrics.windowInsets.getInsetsIgnoringVisibility(
89                 WindowInsets.Type.mandatorySystemGestures() or WindowInsets.Type.displayCutout()
90             )
91         val clickX = gestureInsets.left
92         val clickY = gestureInsets.top
93         uiDevice.click(clickX, clickY)
94         Root.get().verifyNoExpandedBubbleIsVisible()
95     }
96 
97     /** Dismiss Manage education to proceed with expanded bubbles */
98     fun dismissManageEducation() {
99         if (hasObject(BUBBLE_MANAGE_EDUCATION)) {
100             waitForObj(BUBBLE_GOT_IT_BUTTON).click()
101             uiDevice.waitForIdle()
102         }
103     }
104 
105     companion object {
106         val FIND_OBJECT_TIMEOUT = Duration.ofSeconds(20)
107         val BUBBLE_EXPANDED_VIEW = sysuiResSelector("bubble_expanded_view")
108         private val BUBBLE_OVERFLOW_BUTTON = sysuiResSelector("bubble_overflow_button")
109         private val BUBBLE_BAR_OVERFLOW = launcherResSelector("bubble_overflow_button")
110         private val BUBBLE_MANAGE_EDUCATION = sysuiResSelector("manage_education_view")
111         private val BUBBLE_GOT_IT_BUTTON = sysuiResSelector("got_it")
112 
113         private val windowMetrics: WindowMetrics
114             get() = context.getSystemService(WindowManager::class.java)!!.currentWindowMetrics
115 
116         @JvmStatic
117         internal val bubbleOverflow: UiObject2
118             get() {
119                 val bubbleOverflow =
120                     if (CommonUtils.isLargeScreen()) {
121                         // Check bubble bar first if we're large screen
122                         waitForNullableObj(BUBBLE_BAR_OVERFLOW, timeout = FIND_OBJECT_TIMEOUT)
123                             ?:
124                             // Check floating in case bubble bar wasn't active
125                             waitForNullableObj(
126                                 BUBBLE_OVERFLOW_BUTTON,
127                                 timeout = FIND_OBJECT_TIMEOUT,
128                             )
129                     } else {
130                         waitForNullableObj(BUBBLE_OVERFLOW_BUTTON, timeout = FIND_OBJECT_TIMEOUT)
131                     }
132                 assertWithMessage("Bubble overflow not visible").that(bubbleOverflow).isNotNull()
133                 return bubbleOverflow!!
134             }
135     }
136 }
137