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