1 /*
2  * Copyright (C) 2019 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.statusbar.phone;
18 
19 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
20 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
21 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
22 
23 import android.content.Context;
24 import android.content.res.Resources;
25 import android.graphics.PixelFormat;
26 import android.os.Binder;
27 import android.util.Log;
28 import android.view.Gravity;
29 import android.view.ViewGroup;
30 import android.view.WindowManager;
31 
32 import com.android.systemui.dagger.qualifiers.Main;
33 import com.android.systemui.statusbar.SuperStatusBarViewFactory;
34 
35 import javax.inject.Inject;
36 import javax.inject.Singleton;
37 
38 /**
39  * Encapsulates all logic for the status bar window state management.
40  */
41 @Singleton
42 public class StatusBarWindowController {
43     private static final String TAG = "StatusBarWindowController";
44     private static final boolean DEBUG = false;
45 
46     private final Context mContext;
47     private final WindowManager mWindowManager;
48     private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
49     private final Resources mResources;
50     private int mBarHeight = -1;
51     private final State mCurrentState = new State();
52 
53     private ViewGroup mStatusBarView;
54     private WindowManager.LayoutParams mLp;
55     private final WindowManager.LayoutParams mLpChanged;
56 
57     @Inject
StatusBarWindowController(Context context, WindowManager windowManager, SuperStatusBarViewFactory superStatusBarViewFactory, @Main Resources resources)58     public StatusBarWindowController(Context context, WindowManager windowManager,
59             SuperStatusBarViewFactory superStatusBarViewFactory,
60             @Main Resources resources) {
61         mContext = context;
62         mWindowManager = windowManager;
63         mSuperStatusBarViewFactory = superStatusBarViewFactory;
64         mStatusBarView = mSuperStatusBarViewFactory.getStatusBarWindowView();
65         mLpChanged = new WindowManager.LayoutParams();
66         mResources = resources;
67 
68         if (mBarHeight < 0) {
69             mBarHeight = mResources.getDimensionPixelSize(
70                     com.android.internal.R.dimen.status_bar_height);
71         }
72     }
73 
getStatusBarHeight()74     public int getStatusBarHeight() {
75         return mBarHeight;
76     }
77 
78     /**
79      * Rereads the status_bar_height from configuration and reapplys the current state if the height
80      * is different.
81      */
refreshStatusBarHeight()82     public void refreshStatusBarHeight() {
83         int heightFromConfig = mResources.getDimensionPixelSize(
84                 com.android.internal.R.dimen.status_bar_height);
85 
86         if (mBarHeight != heightFromConfig) {
87             mBarHeight = heightFromConfig;
88             apply(mCurrentState);
89         }
90 
91         if (DEBUG) Log.v(TAG, "defineSlots");
92     }
93 
94     /**
95      * Adds the status bar view to the window manager.
96      */
attach()97     public void attach() {
98         // Now that the status bar window encompasses the sliding panel and its
99         // translucent backdrop, the entire thing is made TRANSLUCENT and is
100         // hardware-accelerated.
101         mLp = new WindowManager.LayoutParams(
102                 ViewGroup.LayoutParams.MATCH_PARENT,
103                 mBarHeight,
104                 WindowManager.LayoutParams.TYPE_STATUS_BAR,
105                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
106                         | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
107                         | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
108                 PixelFormat.TRANSLUCENT);
109         mLp.privateFlags |= PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC;
110         mLp.token = new Binder();
111         mLp.gravity = Gravity.TOP;
112         mLp.setFitInsetsTypes(0 /* types */);
113         mLp.setTitle("StatusBar");
114         mLp.packageName = mContext.getPackageName();
115         mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
116 
117         mWindowManager.addView(mStatusBarView, mLp);
118         mLpChanged.copyFrom(mLp);
119     }
120 
121     /** Set force status bar visible. */
setForceStatusBarVisible(boolean forceStatusBarVisible)122     public void setForceStatusBarVisible(boolean forceStatusBarVisible) {
123         mCurrentState.mForceStatusBarVisible = forceStatusBarVisible;
124         apply(mCurrentState);
125     }
126 
applyHeight()127     private void applyHeight() {
128         mLpChanged.height = mBarHeight;
129     }
130 
apply(State state)131     private void apply(State state) {
132         applyForceStatusBarVisibleFlag(state);
133         applyHeight();
134         if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
135             mWindowManager.updateViewLayout(mStatusBarView, mLp);
136         }
137     }
138 
139     private static class State {
140         boolean mForceStatusBarVisible;
141     }
142 
applyForceStatusBarVisibleFlag(State state)143     private void applyForceStatusBarVisibleFlag(State state) {
144         if (state.mForceStatusBarVisible) {
145             mLpChanged.privateFlags |= PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
146         } else {
147             mLpChanged.privateFlags &= ~PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
148         }
149     }
150 }
151