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