• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 com.android.quickstep.recents.domain.usecase
18 
19 import android.graphics.Bitmap
20 import android.view.Surface
21 import com.android.quickstep.recents.data.RecentsRotationStateRepository
22 import com.android.systemui.shared.recents.model.ThumbnailData
23 import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
24 import com.android.systemui.shared.recents.utilities.Utilities
25 
26 /**
27  * Use case responsible for validating the aspect ratio and rotation of a thumbnail against the
28  * expected values based on the view's dimensions and the current rotation state.
29  *
30  * This class checks if the thumbnail's aspect ratio significantly differs from the aspect ratio of
31  * the view it is intended to be displayed in, and if the thumbnail's rotation is consistent with
32  * the device's current rotation state.
33  *
34  * @property rotationStateRepository Repository providing the current rotation state of the device.
35  */
36 class IsThumbnailValidUseCase(private val rotationStateRepository: RecentsRotationStateRepository) {
invokenull37     operator fun invoke(thumbnailData: ThumbnailData?, viewWidth: Int, viewHeight: Int): Boolean {
38         val thumbnail = thumbnailData?.thumbnail ?: return false
39         return !isInaccurateThumbnail(thumbnail, viewWidth, viewHeight, thumbnailData.rotation)
40     }
41 
isInaccurateThumbnailnull42     private fun isInaccurateThumbnail(
43         thumbnail: Bitmap,
44         viewWidth: Int,
45         viewHeight: Int,
46         rotation: Int,
47     ): Boolean =
48         isAspectRatioDifferentFromViewAspectRatio(
49             thumbnail = thumbnail,
50             width = viewWidth.toFloat(),
51             height = viewHeight.toFloat(),
52         ) || isRotationDifferentFromTask(rotation)
53 
54     private fun isAspectRatioDifferentFromViewAspectRatio(
55         thumbnail: Bitmap,
56         width: Float,
57         height: Float,
58     ): Boolean {
59         return Utilities.isRelativePercentDifferenceGreaterThan(
60             /* first = */ width / height,
61             /* second = */ thumbnail.width / thumbnail.height.toFloat(),
62             /* bound = */ PreviewPositionHelper.MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT,
63         )
64     }
65 
isRotationDifferentFromTasknull66     private fun isRotationDifferentFromTask(thumbnailRotation: Int): Boolean {
67         val rotationState = rotationStateRepository.getRecentsRotationState()
68         return if (rotationState.orientationHandlerRotation == Surface.ROTATION_0) {
69             (rotationState.activityRotation - thumbnailRotation) % 2 != 0
70         } else {
71             rotationState.orientationHandlerRotation != thumbnailRotation
72         }
73     }
74 }
75