1 /*
2  * Copyright (C) 2024 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.systemui
18 
19 import android.content.Context
20 import android.graphics.Rect
21 import android.util.RotationUtils
22 import android.view.Display
23 import android.view.DisplayCutout
24 import com.android.systemui.dagger.SysUISingleton
25 import com.android.systemui.display.naturalBounds
26 import javax.inject.Inject
27 
28 @SysUISingleton
29 class SysUICutoutProvider
30 @Inject
31 constructor(
32     private val context: Context,
33     private val cameraProtectionLoader: CameraProtectionLoader,
34 ) {
35 
<lambda>null36     private val cameraProtectionList by lazy {
37         cameraProtectionLoader.loadCameraProtectionInfoList()
38     }
39 
40     /**
41      * Returns the [SysUICutoutInformation] for the current display and the current rotation.
42      *
43      * This means that the bounds of the display cutout and the camera protection will be
44      * adjusted/rotated for the current rotation.
45      */
cutoutInfoForCurrentDisplayAndRotationnull46     fun cutoutInfoForCurrentDisplayAndRotation(): SysUICutoutInformation? {
47         val display = context.display
48         val displayCutout: DisplayCutout = display.cutout ?: return null
49         return SysUICutoutInformation(displayCutout, getCameraProtectionForDisplay(display))
50     }
51 
getCameraProtectionForDisplaynull52     private fun getCameraProtectionForDisplay(display: Display): CameraProtectionInfo? {
53         val displayUniqueId: String? = display.uniqueId
54         if (displayUniqueId.isNullOrEmpty()) {
55             return null
56         }
57         val cameraProtection: CameraProtectionInfo =
58             cameraProtectionList.firstOrNull { it.displayUniqueId == displayUniqueId }
59                 ?: return null
60         val adjustedBoundsForRotation =
61             calculateCameraProtectionBoundsForRotation(display, cameraProtection.bounds)
62         return cameraProtection.copy(bounds = adjustedBoundsForRotation)
63     }
64 
calculateCameraProtectionBoundsForRotationnull65     private fun calculateCameraProtectionBoundsForRotation(
66         display: Display,
67         originalProtectionBounds: Rect,
68     ): Rect {
69         val displayNaturalBounds = display.naturalBounds
70         val rotatedBoundsOut = Rect(originalProtectionBounds)
71         RotationUtils.rotateBounds(
72             /* inOutBounds = */ rotatedBoundsOut,
73             /* parentWidth = */ displayNaturalBounds.width(),
74             /* parentHeight = */ displayNaturalBounds.height(),
75             /* rotation = */ display.rotation
76         )
77         return rotatedBoundsOut
78     }
79 }
80