1 /* 2 * Copyright (C) 2020 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.wm; 18 19 import android.content.Context; 20 import android.os.Handler; 21 import android.os.RemoteException; 22 import android.util.ArraySet; 23 import android.util.Slog; 24 import android.util.SparseArray; 25 import android.view.IDisplayWindowInsetsController; 26 import android.view.IWindowManager; 27 import android.view.InsetsController; 28 import android.view.InsetsState; 29 import android.view.InsetsVisibilities; 30 import android.view.WindowInsets.Type; 31 32 import androidx.annotation.VisibleForTesting; 33 34 import com.android.systemui.dagger.qualifiers.Main; 35 import com.android.wm.shell.common.DisplayController; 36 import com.android.wm.shell.common.DisplayImeController; 37 import com.android.wm.shell.common.DisplayInsetsController; 38 import com.android.wm.shell.common.TransactionPool; 39 40 import java.util.Objects; 41 42 /** 43 * Controller that maps between displays and {@link IDisplayWindowInsetsController} in order to 44 * give system bar control to SystemUI. 45 * {@link R.bool#config_remoteInsetsControllerControlsSystemBars} determines whether this controller 46 * takes control or not. 47 */ 48 public class DisplaySystemBarsController extends DisplayImeController { 49 50 private static final String TAG = "DisplaySystemBarsController"; 51 52 private final Context mContext; 53 private final DisplayController mDisplayController; 54 private final Handler mHandler; 55 private SparseArray<PerDisplay> mPerDisplaySparseArray; 56 DisplaySystemBarsController( Context context, IWindowManager wmService, DisplayController displayController, DisplayInsetsController displayInsetsController, @Main Handler mainHandler, TransactionPool transactionPool)57 public DisplaySystemBarsController( 58 Context context, 59 IWindowManager wmService, 60 DisplayController displayController, 61 DisplayInsetsController displayInsetsController, 62 @Main Handler mainHandler, 63 TransactionPool transactionPool) { 64 super(wmService, displayController, displayInsetsController, (r) -> mainHandler.post(r), 65 transactionPool); 66 mContext = context; 67 mDisplayController = displayController; 68 mHandler = mainHandler; 69 } 70 71 @Override onDisplayAdded(int displayId)72 public void onDisplayAdded(int displayId) { 73 PerDisplay pd = new PerDisplay(displayId); 74 pd.register(); 75 // Lazy loading policy control filters instead of during boot. 76 if (mPerDisplaySparseArray == null) { 77 mPerDisplaySparseArray = new SparseArray<>(); 78 BarControlPolicy.reloadFromSetting(mContext); 79 BarControlPolicy.registerContentObserver(mContext, mHandler, () -> { 80 int size = mPerDisplaySparseArray.size(); 81 for (int i = 0; i < size; i++) { 82 mPerDisplaySparseArray.valueAt(i).updateDisplayWindowRequestedVisibilities(); 83 } 84 }); 85 } 86 mPerDisplaySparseArray.put(displayId, pd); 87 } 88 89 @Override onDisplayRemoved(int displayId)90 public void onDisplayRemoved(int displayId) { 91 try { 92 mWmService.setDisplayWindowInsetsController(displayId, null); 93 } catch (RemoteException e) { 94 Slog.w(TAG, "Unable to remove insets controller on display " + displayId); 95 } 96 mPerDisplaySparseArray.remove(displayId); 97 } 98 99 @VisibleForTesting 100 class PerDisplay extends DisplayImeController.PerDisplay { 101 102 int mDisplayId; 103 InsetsController mInsetsController; 104 InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities(); 105 String mPackageName; 106 PerDisplay(int displayId)107 PerDisplay(int displayId) { 108 super(displayId, mDisplayController.getDisplayLayout(displayId).rotation()); 109 mDisplayId = displayId; 110 mInsetsController = new InsetsController( 111 new DisplaySystemBarsInsetsControllerHost(mHandler, visibilities -> { 112 mRequestedVisibilities.set(visibilities); 113 updateDisplayWindowRequestedVisibilities(); 114 })); 115 } 116 117 @Override insetsChanged(InsetsState insetsState)118 public void insetsChanged(InsetsState insetsState) { 119 super.insetsChanged(insetsState); 120 mInsetsController.onStateChanged(insetsState); 121 updateDisplayWindowRequestedVisibilities(); 122 } 123 124 @Override hideInsets(@ype.InsetsType int types, boolean fromIme)125 public void hideInsets(@Type.InsetsType int types, boolean fromIme) { 126 if ((types & Type.ime()) == 0) { 127 mInsetsController.hide(types); 128 } else { 129 super.hideInsets(types, fromIme); 130 } 131 132 } 133 134 @Override showInsets(@ype.InsetsType int types, boolean fromIme)135 public void showInsets(@Type.InsetsType int types, boolean fromIme) { 136 if ((types & Type.ime()) == 0) { 137 mInsetsController.show(types); 138 } else { 139 super.showInsets(types, fromIme); 140 } 141 142 } 143 144 @Override topFocusedWindowChanged(String packageName)145 public void topFocusedWindowChanged(String packageName) { 146 if (Objects.equals(mPackageName, packageName)) { 147 return; 148 } 149 mPackageName = packageName; 150 updateDisplayWindowRequestedVisibilities(); 151 } 152 updateDisplayWindowRequestedVisibilities()153 private void updateDisplayWindowRequestedVisibilities() { 154 if (mPackageName == null) { 155 return; 156 } 157 int[] barVisibilities = BarControlPolicy.getBarVisibilities(mPackageName); 158 updateRequestedVisibilities(barVisibilities[0], /* visible= */ true); 159 updateRequestedVisibilities(barVisibilities[1], /* visible= */ false); 160 showInsets(barVisibilities[0], /* fromIme= */ false); 161 hideInsets(barVisibilities[1], /* fromIme= */ false); 162 try { 163 mWmService.updateDisplayWindowRequestedVisibilities(mDisplayId, 164 mRequestedVisibilities); 165 } catch (RemoteException e) { 166 Slog.w(TAG, "Unable to update window manager service."); 167 } 168 } 169 updateRequestedVisibilities(@ype.InsetsType int types, boolean visible)170 private void updateRequestedVisibilities(@Type.InsetsType int types, boolean visible) { 171 ArraySet<Integer> internalTypes = InsetsState.toInternalType(types); 172 for (int i = internalTypes.size() - 1; i >= 0; i--) { 173 mRequestedVisibilities.setVisibility(internalTypes.valueAt(i), visible); 174 } 175 } 176 } 177 } 178