/*
* Copyright 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 androidx.graphics.lowlatency
import android.os.Build
import android.util.Log
import android.view.Surface
import android.view.View
import androidx.annotation.RequiresApi
import androidx.graphics.surface.SurfaceControlCompat
/**
* Helper class to determine the corresponding transformation hint based on various Android
* API levels
*/
internal class BufferTransformHintResolver {
fun getBufferTransformHint(view: View): Int {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S_V2) {
return TransformHintHelper.resolveBufferTransformHint(view)
} else {
val orientation: String?
return try {
orientation = getDisplayOrientation()
val rotation = view.display?.rotation
if (rotation != null) {
val transform = getBufferTransformHintFromInstallOrientation(
orientation,
rotation
)
Log.v(TAG, "Obtained transform: $transform for orientation: $orientation")
transform
} else {
Log.w(TAG, "Unable to obtain current display rotation")
UNKNOWN_TRANSFORM
}
} catch (exception: Exception) {
Log.w(TAG, "Unable to obtain current display orientation")
UNKNOWN_TRANSFORM
}
}
}
internal fun getBufferTransformHintFromInstallOrientation(
orientation: String,
rotation: Int
): Int =
when (orientation) {
ORIENTATION_90 -> {
when (rotation) {
Surface.ROTATION_0 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_90
Surface.ROTATION_90 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_180
Surface.ROTATION_180 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_270
Surface.ROTATION_270 -> SurfaceControlCompat.BUFFER_TRANSFORM_IDENTITY
else -> UNKNOWN_TRANSFORM
}
}
ORIENTATION_180 -> {
when (rotation) {
Surface.ROTATION_0 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_180
Surface.ROTATION_90 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_270
Surface.ROTATION_180 -> SurfaceControlCompat.BUFFER_TRANSFORM_IDENTITY
Surface.ROTATION_270 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_90
else -> UNKNOWN_TRANSFORM
}
}
ORIENTATION_270 -> {
when (rotation) {
Surface.ROTATION_0 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_270
Surface.ROTATION_90 -> SurfaceControlCompat.BUFFER_TRANSFORM_IDENTITY
Surface.ROTATION_180 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_90
Surface.ROTATION_270 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_180
else -> UNKNOWN_TRANSFORM
}
}
ORIENTATION_0 -> {
when (rotation) {
Surface.ROTATION_0 -> SurfaceControlCompat.BUFFER_TRANSFORM_IDENTITY
Surface.ROTATION_90 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_90
Surface.ROTATION_180 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_180
Surface.ROTATION_270 -> SurfaceControlCompat.BUFFER_TRANSFORM_ROTATE_270
else -> UNKNOWN_TRANSFORM
}
}
else -> {
Log.w(TAG, "Unknown orientation \"$orientation\"")
UNKNOWN_TRANSFORM
}
}
internal companion object {
const val TAG = "TRANSFORM_HINT_RESOLVER"
const val UNKNOWN_TRANSFORM = -1
const val ORIENTATION_0 = "ORIENTATION_0"
const val ORIENTATION_90 = "ORIENTATION_90"
const val ORIENTATION_180 = "ORIENTATION_180"
const val ORIENTATION_270 = "ORIENTATION_270"
init {
System.loadLibrary("graphics-core")
}
external fun getDisplayOrientation(): String
}
}
/**
* Helper class to avoid class verification errors
*/
@RequiresApi(Build.VERSION_CODES.S_V2)
internal class TransformHintHelper private constructor() {
companion object {
@RequiresApi(Build.VERSION_CODES.S_V2)
@androidx.annotation.DoNotInline
fun resolveBufferTransformHint(view: View): Int =
view.rootSurfaceControl?.bufferTransformHint ?: 0
}
}