• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 android.content.Context;
20 import android.os.Handler;
21 import android.os.RemoteException;
22 import android.util.Log;
23 import android.view.IWindowManager;
24 import android.view.MotionEvent;
25 
26 import com.android.systemui.dagger.qualifiers.Main;
27 import com.android.systemui.statusbar.AutoHideUiElement;
28 
29 import javax.inject.Inject;
30 
31 /** A controller to control all auto-hide things. Also see {@link AutoHideUiElement}. */
32 public class AutoHideController {
33     private static final String TAG = "AutoHideController";
34     private static final long AUTO_HIDE_TIMEOUT_MS = 2250;
35 
36     private final IWindowManager mWindowManagerService;
37     private final Handler mHandler;
38 
39     private AutoHideUiElement mStatusBar;
40     private AutoHideUiElement mNavigationBar;
41     private int mDisplayId;
42 
43     private boolean mAutoHideSuspended;
44 
45     private final Runnable mAutoHide = () -> {
46         if (isAnyTransientBarShown()) {
47             hideTransientBars();
48         }
49     };
50 
51     @Inject
AutoHideController(Context context, @Main Handler handler, IWindowManager iWindowManager)52     public AutoHideController(Context context, @Main Handler handler,
53             IWindowManager iWindowManager) {
54         mHandler = handler;
55         mWindowManagerService = iWindowManager;
56 
57         mDisplayId = context.getDisplayId();
58     }
59 
60     /**
61      * Sets a {@link AutoHideUiElement} status bar that should be controlled by the
62      * {@link AutoHideController}.
63      */
setStatusBar(AutoHideUiElement element)64     public void setStatusBar(AutoHideUiElement element) {
65         mStatusBar = element;
66     }
67 
68     /**
69      * Sets a {@link AutoHideUiElement} navigation bar that should be controlled by the
70      * {@link AutoHideController}.
71      */
setNavigationBar(AutoHideUiElement element)72     public void setNavigationBar(AutoHideUiElement element) {
73         mNavigationBar = element;
74     }
75 
hideTransientBars()76     private void hideTransientBars() {
77         try {
78             mWindowManagerService.hideTransientBars(mDisplayId);
79         } catch (RemoteException ex) {
80             Log.w(TAG, "Cannot get WindowManager");
81         }
82 
83         if (mStatusBar != null) {
84             mStatusBar.hide();
85         }
86 
87         if (mNavigationBar != null) {
88             mNavigationBar.hide();
89         }
90     }
91 
resumeSuspendedAutoHide()92     void resumeSuspendedAutoHide() {
93         if (mAutoHideSuspended) {
94             scheduleAutoHide();
95             Runnable checkBarModesRunnable = getCheckBarModesRunnable();
96             if (checkBarModesRunnable != null) {
97                 mHandler.postDelayed(checkBarModesRunnable, 500); // longer than home -> launcher
98             }
99         }
100     }
101 
suspendAutoHide()102     void suspendAutoHide() {
103         mHandler.removeCallbacks(mAutoHide);
104         Runnable checkBarModesRunnable = getCheckBarModesRunnable();
105         if (checkBarModesRunnable != null) {
106             mHandler.removeCallbacks(checkBarModesRunnable);
107         }
108         mAutoHideSuspended = isAnyTransientBarShown();
109     }
110 
111     /** Schedules or cancels auto hide behavior based on current system bar state. */
touchAutoHide()112     public void touchAutoHide() {
113         // update transient bar auto hide
114         if (isAnyTransientBarShown()) {
115             scheduleAutoHide();
116         } else {
117             cancelAutoHide();
118         }
119     }
120 
getCheckBarModesRunnable()121     private Runnable getCheckBarModesRunnable() {
122         if (mStatusBar != null) {
123             return () -> mStatusBar.synchronizeState();
124         } else if (mNavigationBar != null) {
125             return () -> mNavigationBar.synchronizeState();
126         } else {
127             return null;
128         }
129     }
130 
cancelAutoHide()131     private void cancelAutoHide() {
132         mAutoHideSuspended = false;
133         mHandler.removeCallbacks(mAutoHide);
134     }
135 
scheduleAutoHide()136     private void scheduleAutoHide() {
137         cancelAutoHide();
138         mHandler.postDelayed(mAutoHide, AUTO_HIDE_TIMEOUT_MS);
139     }
140 
checkUserAutoHide(MotionEvent event)141     public void checkUserAutoHide(MotionEvent event) {
142         boolean shouldHide = isAnyTransientBarShown()
143                 && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar.
144                 && event.getX() == 0 && event.getY() == 0;
145 
146         if (mStatusBar != null) {
147             shouldHide &= mStatusBar.shouldHideOnTouch();
148         }
149         if (mNavigationBar != null) {
150             shouldHide &= mNavigationBar.shouldHideOnTouch();
151         }
152 
153         if (shouldHide) {
154             userAutoHide();
155         }
156     }
157 
userAutoHide()158     private void userAutoHide() {
159         cancelAutoHide();
160         mHandler.postDelayed(mAutoHide, 350); // longer than app gesture -> flag clear
161     }
162 
isAnyTransientBarShown()163     private boolean isAnyTransientBarShown() {
164         if (mStatusBar != null && mStatusBar.isVisible()) {
165             return true;
166         }
167 
168         if (mNavigationBar != null && mNavigationBar.isVisible()) {
169             return true;
170         }
171 
172         return false;
173     }
174 }
175