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.wm.shell.windowdecor.additionalviewcontainer 18 19 import android.annotation.LayoutRes 20 import android.content.Context 21 import android.graphics.PixelFormat 22 import android.view.Gravity 23 import android.view.LayoutInflater 24 import android.view.SurfaceControl 25 import android.view.View 26 import android.view.WindowInsets 27 import android.view.WindowManager 28 import android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS 29 import com.android.wm.shell.windowdecor.WindowManagerWrapper 30 31 /** 32 * An [AdditionalViewContainer] that uses the system [WindowManager] instance. Intended 33 * for view containers that should be above the status bar layer. 34 */ 35 class AdditionalSystemViewContainer( 36 private val windowManagerWrapper: WindowManagerWrapper, 37 taskId: Int, 38 x: Int, 39 y: Int, 40 width: Int, 41 height: Int, 42 flags: Int, 43 @WindowInsets.Type.InsetsType forciblyShownTypes: Int = 0, 44 ignoreCutouts: Boolean = false, 45 override val view: View 46 ) : AdditionalViewContainer() { 47 val lp: WindowManager.LayoutParams = WindowManager.LayoutParams( 48 width, height, x, y, 49 WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL, 50 flags, 51 PixelFormat.TRANSPARENT <lambda>null52 ).apply { 53 title = "Additional view container of Task=$taskId" 54 gravity = Gravity.LEFT or Gravity.TOP 55 setTrustedOverlay() 56 this.forciblyShownTypes = forciblyShownTypes 57 if (ignoreCutouts) { 58 fitInsetsTypes = 0 59 layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS 60 } 61 } 62 63 constructor( 64 context: Context, 65 windowManagerWrapper: WindowManagerWrapper, 66 taskId: Int, 67 x: Int, 68 y: Int, 69 width: Int, 70 height: Int, 71 flags: Int, 72 @LayoutRes layoutId: Int, 73 ignoreCutouts: Boolean = false 74 ) : this( 75 windowManagerWrapper = windowManagerWrapper, 76 taskId = taskId, 77 x = x, 78 y = y, 79 width = width, 80 height = height, 81 flags = flags, 82 view = LayoutInflater.from(context).inflate(layoutId, null /* parent */), 83 ignoreCutouts = ignoreCutouts 84 ) 85 86 constructor( 87 context: Context, 88 windowManagerWrapper: WindowManagerWrapper, 89 taskId: Int, 90 x: Int, 91 y: Int, 92 width: Int, 93 height: Int, 94 flags: Int, 95 ignoreCutouts: Boolean = false 96 ) : this( 97 windowManagerWrapper = windowManagerWrapper, 98 taskId = taskId, 99 x = x, 100 y = y, 101 width = width, 102 height = height, 103 flags = flags, 104 view = View(context), 105 ignoreCutouts = ignoreCutouts 106 ) 107 108 init { 109 windowManagerWrapper.addView(view, lp) 110 } 111 releaseViewnull112 override fun releaseView() { 113 windowManagerWrapper.removeViewImmediate(view) 114 } 115 setPositionnull116 override fun setPosition(t: SurfaceControl.Transaction, x: Float, y: Float) { 117 val lp = (view.layoutParams as WindowManager.LayoutParams).apply { 118 this.x = x.toInt() 119 this.y = y.toInt() 120 } 121 windowManagerWrapper.updateViewLayout(view, lp) 122 } 123 124 class Factory { createnull125 fun create( 126 windowManagerWrapper: WindowManagerWrapper, 127 taskId: Int, 128 x: Int, 129 y: Int, 130 width: Int, 131 height: Int, 132 flags: Int, 133 view: View, 134 ): AdditionalSystemViewContainer = 135 AdditionalSystemViewContainer( 136 windowManagerWrapper = windowManagerWrapper, 137 taskId = taskId, 138 x = x, 139 y = y, 140 width = width, 141 height = height, 142 flags = flags, 143 view = view 144 ) 145 } 146 } 147