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.systemui_tapl.ui 17 18 import android.graphics.Point 19 import android.graphics.PointF 20 import android.platform.systemui_tapl.utils.DeviceUtils.sysuiResSelector 21 import android.platform.systemui_tapl.volume.panel.ui.VolumePanel 22 import android.platform.uiautomatorhelpers.BetterSwipe 23 import android.platform.uiautomatorhelpers.DeviceHelpers.assertVisible 24 import android.platform.uiautomatorhelpers.DeviceHelpers.click 25 import android.platform.uiautomatorhelpers.DeviceHelpers.uiDevice 26 import android.platform.uiautomatorhelpers.DeviceHelpers.waitForObj 27 import android.platform.uiautomatorhelpers.PRECISE_GESTURE_INTERPOLATOR 28 import com.google.common.truth.Truth 29 30 /** System UI test automation object representing the dialog for adjusting the device volume. */ 31 class VolumeDialog internal constructor() { 32 init { 33 assertVolumeDialogVisible() 34 } 35 36 /** 37 * Changes the volume by dragging the volume slider. 38 * 39 * Note: Volume value cannot be more than 25 and less than 0. 40 * 41 * @param volume new volume value 42 */ setVolumeByDraggingnull43 fun setVolumeByDragging(volume: Int) { 44 assertVolumeDialogVisible() 45 dragAndChangeVolume(volume) 46 assertVolumeDialogVisible() 47 } 48 49 /** Open the ringer drawer by clicking the ringer mode icon on the volume dialog. */ openRingerDrawernull50 fun openRingerDrawer(): VolumeRingerDrawer { 51 val ringerIconSel = sysuiResSelector("volume_new_ringer_active_icon_container") 52 waitForObj(ringerIconSel).click() 53 return VolumeRingerDrawer() 54 } 55 56 /** Open the volume setting panel by clicking the setting icon on the volume dialog. */ 57 @Deprecated( 58 "This new volume panel is rolled out. Use openNewVolumePanel instead", 59 replaceWith = ReplaceWith("openNewVolumePanel"), 60 ) openVolumePanelnull61 fun openVolumePanel(): VolumePanelDialog { 62 sysuiResSelector("settings").click() 63 return VolumePanelDialog() 64 } 65 66 /** Open the volume setting panel by clicking the setting icon on the volume dialog. */ openNewVolumePanelnull67 fun openNewVolumePanel(): VolumePanel { 68 waitForObj(sysuiResSelector("settings")).click() 69 return VolumePanel() 70 } 71 72 /** 73 * Click the live caption button on the volume dialog. 74 * 75 * https://hsv.googleplex.com/4767031439130624 76 * 77 * @return this 78 */ toggleLiveCaptionsnull79 fun toggleLiveCaptions(): VolumeDialog { 80 waitForObj(sysuiResSelector("odi_captions_icon")).click() 81 return this 82 } 83 84 companion object { 85 private val SLIDER = sysuiResSelector("volume_row_slider") 86 val PAGE_TITLE_SELECTOR = sysuiResSelector("volume_dialog") 87 private const val MAX_VOLUME = 26 88 private const val MIN_VOLUME = -1 89 90 /** 91 * Method used for dragging and changing the volume. Note: Volume value cannot be more than 92 * 25 and less than 0. 93 * 94 * @param volume value for volume to changed 95 */ dragAndChangeVolumenull96 private fun dragAndChangeVolume(volume: Int) { 97 val coordinates = getDragCoordinates(volume) 98 assertVolumeDialogVisible() 99 BetterSwipe.from(waitForObj(SLIDER).visibleCenter) 100 .to(PointF(coordinates), interpolator = PRECISE_GESTURE_INTERPOLATOR) 101 .release() 102 } 103 104 /** Asserts that the volume dialog is visible. */ assertVolumeDialogVisiblenull105 private fun assertVolumeDialogVisible() { 106 PAGE_TITLE_SELECTOR.assertVisible() 107 } 108 109 /** 110 * This will get the co-ordinate of the for volume slider based on the volume value 111 * provided. 112 * 113 * Note: Volume value cannot be more than 25 and less than 0. 114 * 115 * Formula's used: Suppose volume slider length is 100 and volume provided is 15, therefore 116 * slider should move to: 117 * 118 * FORMULA: (Volume Provided / Max Volume) * Slider Length Hence in current scenario its: 119 * (15/25)*100 120 * 121 * Since the Android device coordinate works from top to down 122 * [https://screenshot.googleplex .com/Zm3s1rqJ2Es], therefore formula used for coordinate 123 * calculation is: 124 * 125 * X-Coordinate: TOP + ((MAX VOLUME - GIVEN VOLUME)/MAX VOLUME ) * (SLIDER BOTTOM Y 126 * COORDINATE - SLIDER TOP Y COORDINATE) 127 * 128 * Y-Coordinate: SLIDER LEFT X COORDINATE + (SLIDER RIGHT X COORDINATE - SLIDER LEFT X 129 * COORDINATE) / 2 130 * 131 * @param volume value for volume to changed 132 * @return an of Point which is the coordinate of the slider to be moved too. 133 */ getDragCoordinatesnull134 private fun getDragCoordinates(volume: Int): Point { 135 Truth.assertThat(volume).isLessThan(MAX_VOLUME) 136 Truth.assertThat(volume).isGreaterThan(MIN_VOLUME) 137 val dimension = uiDevice.waitForObj(SLIDER).visibleBounds 138 val top = dimension.top 139 val left = dimension.left 140 val right = dimension.right 141 val bottom = dimension.bottom 142 val y = (top + (25 - volume).toFloat() / 25 * (bottom - top)).toInt() 143 val x = left + (right - left) / 2 144 return Point(x, y) 145 } 146 } 147 } 148