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