blob: 614dea6549f47420ce88dac76d3a311deb9d07fb [file] [log] [blame]
/*
* 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.server.wm.flicker.helpers
import android.content.Context
import android.graphics.Point
import android.graphics.Rect
import android.view.WindowManager
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.traces.common.layers.Display
import com.android.server.wm.traces.common.region.Region
import com.android.server.wm.traces.common.service.PlatformConsts
object WindowUtils {
/** Helper functions to retrieve system window sizes and positions. */
private val context
get() = InstrumentationRegistry.getInstrumentation().context
private val resources
get() = context.getResources()
/** Get the display bounds */
val displayBounds: Rect
get() {
val display = Point()
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
wm.defaultDisplay.getRealSize(display)
return Rect(0, 0, display.x, display.y)
}
/** Gets the current display rotation */
val displayRotation: PlatformConsts.Rotation
get() {
val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
return PlatformConsts.Rotation.getByValue(wm.defaultDisplay.rotation)
}
/**
* Get the display bounds when the device is at a specific rotation
*
* @param requestedRotation Device rotation
*/
fun getDisplayBounds(requestedRotation: PlatformConsts.Rotation): Region {
val displayIsRotated = displayRotation.isRotated()
val requestedDisplayIsRotated = requestedRotation.isRotated()
// if the current orientation changes with the requested rotation,
// flip height and width of display bounds.
return if (displayIsRotated != requestedDisplayIsRotated) {
Region.from(0, 0, displayBounds.height(), displayBounds.width())
} else {
Region.from(0, 0, displayBounds.width(), displayBounds.height())
}
}
/**
* Gets the expected status bar position for a specific display
*
* @param display the main display
*/
fun getStatusBarPosition(display: Display): Region {
val resourceName =
if (!display.transform.getRotation().isRotated()) {
"status_bar_height_portrait"
} else {
"status_bar_height_landscape"
}
val resourceId = resources.getIdentifier(resourceName, "dimen", "android")
val height = resources.getDimensionPixelSize(resourceId)
return Region.from(0, 0, display.layerStackSpace.width, height)
}
/**
* Gets the expected navigation bar position for a specific display
*
* @param display the main display
*/
fun getNavigationBarPosition(display: Display): Region {
return getNavigationBarPosition(display, isGesturalNavigationEnabled)
}
/**
* Gets the expected navigation bar position for a specific display
*
* @param display the main display
* @param isGesturalNavigation whether gestural navigation is enabled
*/
fun getNavigationBarPosition(display: Display, isGesturalNavigation: Boolean): Region {
val navBarWidth = getDimensionPixelSize("navigation_bar_width")
val navBarHeight = navigationBarFrameHeight
val displayHeight = display.layerStackSpace.height
val displayWidth = display.layerStackSpace.width
val requestedRotation = display.transform.getRotation()
return when {
// nav bar is at the bottom of the screen
!requestedRotation.isRotated() || isGesturalNavigation ->
Region.from(0, displayHeight - navBarHeight, displayWidth, displayHeight)
// nav bar is on the right side
requestedRotation == PlatformConsts.Rotation.ROTATION_90 ->
Region.from(displayWidth - navBarWidth, 0, displayWidth, displayHeight)
// nav bar is on the left side
requestedRotation == PlatformConsts.Rotation.ROTATION_270 ->
Region.from(0, 0, navBarWidth, displayHeight)
else -> error("Unknown rotation $requestedRotation")
}
}
/**
* Estimate the navigation bar position at a specific rotation
*
* @param requestedRotation Device rotation
*/
fun estimateNavigationBarPosition(requestedRotation: PlatformConsts.Rotation): Region {
val displayBounds = displayBounds
val displayWidth: Int
val displayHeight: Int
if (!requestedRotation.isRotated()) {
displayWidth = displayBounds.width()
displayHeight = displayBounds.height()
} else {
// swap display dimensions in landscape or seascape mode
displayWidth = displayBounds.height()
displayHeight = displayBounds.width()
}
val navBarWidth = getDimensionPixelSize("navigation_bar_width")
val navBarHeight = navigationBarFrameHeight
return when {
// nav bar is at the bottom of the screen
!requestedRotation.isRotated() || isGesturalNavigationEnabled ->
Region.from(0, displayHeight - navBarHeight, displayWidth, displayHeight)
// nav bar is on the right side
requestedRotation == PlatformConsts.Rotation.ROTATION_90 ->
Region.from(displayWidth - navBarWidth, 0, displayWidth, displayHeight)
// nav bar is on the left side
requestedRotation == PlatformConsts.Rotation.ROTATION_270 ->
Region.from(0, 0, navBarWidth, displayHeight)
else -> error("Unknown rotation $requestedRotation")
}
}
/** Checks if the device uses gestural navigation */
val isGesturalNavigationEnabled: Boolean
get() {
val resourceId =
resources.getIdentifier("config_navBarInteractionMode", "integer", "android")
return resources.getInteger(resourceId) == 2 /* NAV_BAR_MODE_GESTURAL */
}
fun getDimensionPixelSize(resourceName: String): Int {
val resourceId = resources.getIdentifier(resourceName, "dimen", "android")
return resources.getDimensionPixelSize(resourceId)
}
/** Gets the navigation bar frame height */
val navigationBarFrameHeight: Int
get() {
return getDimensionPixelSize("navigation_bar_frame_height")
}
/** Split screen divider inset height */
val dockedStackDividerInset: Int
get() {
val resourceId =
resources.getIdentifier("docked_stack_divider_insets", "dimen", "android")
return resources.getDimensionPixelSize(resourceId)
}
}