• 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.car.window;
18 
19 import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
20 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
21 
22 import android.content.Context;
23 import android.graphics.PixelFormat;
24 import android.os.Binder;
25 import android.view.Gravity;
26 import android.view.LayoutInflater;
27 import android.view.View;
28 import android.view.ViewGroup;
29 import android.view.WindowInsets;
30 import android.view.WindowManager;
31 
32 import com.android.systemui.R;
33 import com.android.systemui.dagger.SysUISingleton;
34 import com.android.systemui.statusbar.policy.ConfigurationController;
35 
36 import javax.inject.Inject;
37 
38 /**
39  * Controls the expansion state of the primary window which will contain all of the fullscreen sysui
40  * behavior. This window still has a collapsed state in order to watch for swipe events to expand
41  * this window for the notification panel.
42  */
43 @SysUISingleton
44 public class SystemUIOverlayWindowController implements
45         ConfigurationController.ConfigurationListener {
46 
47     private final Context mContext;
48     private final WindowManager mWindowManager;
49 
50     private ViewGroup mBaseLayout;
51     private WindowManager.LayoutParams mLp;
52     private WindowManager.LayoutParams mLpChanged;
53     private boolean mIsAttached = false;
54     private boolean mVisible = false;
55     private boolean mFocusable = false;
56     private boolean mUsingStableInsets = false;
57 
58     @Inject
SystemUIOverlayWindowController( Context context, WindowManager windowManager, ConfigurationController configurationController )59     public SystemUIOverlayWindowController(
60             Context context,
61             WindowManager windowManager,
62             ConfigurationController configurationController
63     ) {
64         mContext = context;
65         mWindowManager = windowManager;
66 
67         mLpChanged = new WindowManager.LayoutParams();
68         mBaseLayout = (ViewGroup) LayoutInflater.from(context)
69                 .inflate(R.layout.sysui_overlay_window, /* root= */ null, false);
70 
71         configurationController.addCallback(this);
72     }
73 
74     /** Returns the base view of the primary window. */
getBaseLayout()75     public ViewGroup getBaseLayout() {
76         return mBaseLayout;
77     }
78 
79     /** Returns {@code true} if the window is already attached. */
isAttached()80     public boolean isAttached() {
81         return mIsAttached;
82     }
83 
84     /** Attaches the window to the window manager. */
attach()85     public void attach() {
86         if (mIsAttached) {
87             return;
88         }
89         mIsAttached = true;
90         // Now that the status bar window encompasses the sliding panel and its
91         // translucent backdrop, the entire thing is made TRANSLUCENT and is
92         // hardware-accelerated.
93         mLp = new WindowManager.LayoutParams(
94                 ViewGroup.LayoutParams.MATCH_PARENT,
95                 ViewGroup.LayoutParams.MATCH_PARENT,
96                 WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE,
97                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
98                         | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
99                         | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
100                         | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
101                         | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
102                 PixelFormat.TRANSLUCENT);
103         mLp.token = new Binder();
104         mLp.gravity = Gravity.TOP;
105         mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
106         mLp.setTitle("SystemUIOverlayWindow");
107         mLp.packageName = mContext.getPackageName();
108         mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
109         mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
110 
111         mWindowManager.addView(mBaseLayout, mLp);
112         mLpChanged.copyFrom(mLp);
113         setWindowVisible(false);
114     }
115 
116     /** Sets the types of insets to fit. Note: This should be rarely used. */
setFitInsetsTypes(@indowInsets.Type.InsetsType int types)117     public void setFitInsetsTypes(@WindowInsets.Type.InsetsType int types) {
118         mLpChanged.setFitInsetsTypes(types);
119         mLpChanged.setFitInsetsIgnoringVisibility(mUsingStableInsets);
120         updateWindow();
121     }
122 
123     /** Sets the sides of system bar insets to fit. Note: This should be rarely used. */
setFitInsetsSides(@indowInsets.Side.InsetsSide int sides)124     public void setFitInsetsSides(@WindowInsets.Side.InsetsSide int sides) {
125         mLpChanged.setFitInsetsSides(sides);
126         mLpChanged.setFitInsetsIgnoringVisibility(mUsingStableInsets);
127         updateWindow();
128     }
129 
130     /** Sets the window to the visible state. */
setWindowVisible(boolean visible)131     public void setWindowVisible(boolean visible) {
132         mVisible = visible;
133         if (visible) {
134             mBaseLayout.setVisibility(View.VISIBLE);
135         } else {
136             mBaseLayout.setVisibility(View.INVISIBLE);
137         }
138         updateWindow();
139     }
140 
141     /** Sets the window to be focusable. */
setWindowFocusable(boolean focusable)142     public void setWindowFocusable(boolean focusable) {
143         mFocusable = focusable;
144         if (focusable) {
145             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
146         } else {
147             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
148         }
149         updateWindow();
150     }
151 
152     /** Sets the window to enable IME. */
setWindowNeedsInput(boolean needsInput)153     public void setWindowNeedsInput(boolean needsInput) {
154         if (needsInput) {
155             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
156         } else {
157             mLpChanged.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
158         }
159         updateWindow();
160     }
161 
162     /** Returns {@code true} if the window is visible */
isWindowVisible()163     public boolean isWindowVisible() {
164         return mVisible;
165     }
166 
isWindowFocusable()167     public boolean isWindowFocusable() {
168         return mFocusable;
169     }
170 
setUsingStableInsets(boolean useStableInsets)171     protected void setUsingStableInsets(boolean useStableInsets) {
172         mUsingStableInsets = useStableInsets;
173     }
174 
updateWindow()175     private void updateWindow() {
176         if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
177             if (isAttached()) {
178                 mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
179                 mWindowManager.updateViewLayout(mBaseLayout, mLp);
180             }
181         }
182     }
183 }
184