1 /* 2 * Copyright (C) 2022 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 package android.platform.test.scenario.tapl_common 17 18 import android.graphics.Rect 19 import android.platform.uiautomator_helpers.BetterFling 20 import android.platform.uiautomator_helpers.BetterScroll 21 import android.platform.uiautomator_helpers.DeviceHelpers.waitForObj 22 import androidx.test.uiautomator.By 23 import androidx.test.uiautomator.Direction 24 import androidx.test.uiautomator.UiObject2 25 26 /** 27 * Ui object with diagnostic metadata and flake-free gestures. 28 * 29 * @param [uiObject] UI Automator object 30 * @param [name] Name of the object for diags 31 */ 32 class TaplUiObject constructor(val uiObject: UiObject2, private val name: String) { 33 // Margins used for gestures (avoids touching too close to the object's edge). 34 private var mMarginLeft = 5 35 private var mMarginTop = 5 36 private var mMarginRight = 5 37 private var mMarginBottom = 5 38 39 /** Sets the margins used for gestures in pixels. */ setGestureMarginnull40 fun setGestureMargin(margin: Int) { 41 setGestureMargins(margin, margin, margin, margin) 42 } 43 44 /** Sets the margins used for gestures in pixels. */ setGestureMarginsnull45 fun setGestureMargins(left: Int, top: Int, right: Int, bottom: Int) { 46 mMarginLeft = left 47 mMarginTop = top 48 mMarginRight = right 49 mMarginBottom = bottom 50 } 51 52 /** Returns this object's visible bounds with the margins removed. */ getVisibleBoundsForGesturesnull53 private fun getVisibleBoundsForGestures(): Rect { 54 val ret: Rect = uiObject.visibleBounds 55 ret.left = ret.left + mMarginLeft 56 ret.top = ret.top + mMarginTop 57 ret.right = ret.right - mMarginRight 58 ret.bottom = ret.bottom - mMarginBottom 59 return ret 60 } 61 62 /** Wait for the object to become clickable and enabled, then clicks the object. */ clicknull63 fun click() { 64 Gestures.click(uiObject, name) 65 } 66 67 /** 68 * Waits for a child UI object with a given resource id. Fails if the object is not visible. 69 * 70 * @param [resourceId] Resource id. 71 * @param [childObjectName] Name of the object for diags. 72 * @return The found UI object. 73 */ waitForChildObjectnull74 fun waitForChildObject(childResourceId: String, childObjectName: String): TaplUiObject { 75 val selector = By.res(uiObject.applicationPackage, childResourceId) 76 val childObject = uiObject.waitForObj(selector) 77 return TaplUiObject(childObject, childObjectName) 78 } 79 80 /** 81 * Performs a scroll gesture on this object. 82 * 83 * @param direction The direction in which to scroll. 84 * @param percent The distance to scroll as a percentage of this object's visible size. 85 * @param verifyIsScrollable Whether to verify that the object is scrollable. 86 */ scrollnull87 fun scroll(direction: Direction, percent: Float, verifyIsScrollable: Boolean = false) { 88 if (verifyIsScrollable) { 89 Gestures.waitForObjectEnabled(uiObject, name) 90 Gestures.waitForObjectScrollable(uiObject, name) 91 } 92 93 require(percent >= 0.0f) { "Percent must be greater than 0.0f" } 94 require(percent <= 1.0f) { "Percent must be less than 1.0f" } 95 96 // To scroll, we swipe in the opposite direction 97 val swipeDirection: Direction = Direction.reverse(direction) 98 99 // Scroll by performing repeated swipes 100 val bounds: Rect = getVisibleBoundsForGestures() 101 val segment = Math.min(percent, 1.0f) 102 BetterScroll.scroll(bounds, swipeDirection, segment) 103 } 104 105 /** 106 * Performs a fling gesture on this object. 107 * 108 * @param direction The direction in which to scroll. 109 * @param percent The distance to scroll as a percentage of this object's visible size. 110 * @param verifyIsScrollable Whether to verify that the object is scrollable. 111 */ flingnull112 fun fling(direction: Direction, percent: Float, verifyIsScrollable: Boolean = false) { 113 if (verifyIsScrollable) { 114 Gestures.waitForObjectEnabled(uiObject, name) 115 Gestures.waitForObjectScrollable(uiObject, name) 116 } 117 118 require(percent >= 0.0f) { "Percent must be greater than 0.0f" } 119 require(percent <= 1.0f) { "Percent must be less than 1.0f" } 120 121 // To fling, we swipe in the opposite direction 122 val swipeDirection: Direction = Direction.reverse(direction) 123 124 val bounds: Rect = getVisibleBoundsForGestures() 125 val segment = Math.min(percent, 1.0f) 126 127 BetterFling.fling(bounds, swipeDirection, percentage = segment) 128 } 129 } 130