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 
17 package com.android.systemui.decor
18 
19 import android.content.Context
20 import android.content.res.Resources
21 import android.view.DisplayCutout
22 import android.view.LayoutInflater
23 import android.view.Surface
24 import android.view.View
25 import android.view.ViewGroup
26 import com.android.systemui.R
27 import com.android.systemui.dagger.SysUISingleton
28 import com.android.systemui.dagger.qualifiers.Main
29 import javax.inject.Inject
30 
31 /**
32  * Provides privacy dot views for each orientation. The PrivacyDot orientation and visibility
33  * of the privacy dot views are controlled by the PrivacyDotViewController.
34  */
35 @SysUISingleton
36 open class PrivacyDotDecorProviderFactory @Inject constructor(
37     @Main private val res: Resources
38 ) : DecorProviderFactory() {
39 
40     private val isPrivacyDotEnabled: Boolean
41         get() = res.getBoolean(R.bool.config_enablePrivacyDot)
42 
43     override val hasProviders: Boolean
44         get() = isPrivacyDotEnabled
45 
46     override val providers: List<DecorProvider>
47         get() {
48             return if (hasProviders) {
49                 listOf(
50                     PrivacyDotCornerDecorProviderImpl(
51                         viewId = R.id.privacy_dot_top_left_container,
52                         alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
53                         alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
54                         layoutId = R.layout.privacy_dot_top_left),
55                     PrivacyDotCornerDecorProviderImpl(
56                         viewId = R.id.privacy_dot_top_right_container,
57                         alignedBound1 = DisplayCutout.BOUNDS_POSITION_TOP,
58                         alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
59                         layoutId = R.layout.privacy_dot_top_right),
60                     PrivacyDotCornerDecorProviderImpl(
61                         viewId = R.id.privacy_dot_bottom_left_container,
62                         alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
63                         alignedBound2 = DisplayCutout.BOUNDS_POSITION_LEFT,
64                         layoutId = R.layout.privacy_dot_bottom_left),
65                     PrivacyDotCornerDecorProviderImpl(
66                         viewId = R.id.privacy_dot_bottom_right_container,
67                         alignedBound1 = DisplayCutout.BOUNDS_POSITION_BOTTOM,
68                         alignedBound2 = DisplayCutout.BOUNDS_POSITION_RIGHT,
69                         layoutId = R.layout.privacy_dot_bottom_right)
70                 )
71             } else {
72                 emptyList()
73             }
74         }
75 }
76 
77 class PrivacyDotCornerDecorProviderImpl(
78     override val viewId: Int,
79     @DisplayCutout.BoundsPosition override val alignedBound1: Int,
80     @DisplayCutout.BoundsPosition override val alignedBound2: Int,
81     private val layoutId: Int
82 ) : CornerDecorProvider() {
83 
84     override fun onReloadResAndMeasure(
85         view: View,
86         reloadToken: Int,
87         rotation: Int,
88         tintColor: Int,
89         displayUniqueId: String?
90     ) {
91         // Do nothing here because it is handled inside PrivacyDotViewController
92     }
93 
94     override fun inflateView(
95         context: Context,
96         parent: ViewGroup,
97         @Surface.Rotation rotation: Int,
98         tintColor: Int
99     ): View {
100         LayoutInflater.from(context).inflate(layoutId, parent, true)
101         return parent.getChildAt(parent.childCount - 1 /* latest new added child */)
102     }
103 }
104