blob: f9b936763308da55932e98ca3772479e92586aa1 [file] [log] [blame]
Charles Chen8c9a83f2018-12-18 17:44:10 +08001/*
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
17package com.android.systemui.statusbar.phone;
18
Charles Chen8c9a83f2018-12-18 17:44:10 +080019import android.content.Context;
Charles Chen8c9a83f2018-12-18 17:44:10 +080020import android.os.Handler;
21import android.os.RemoteException;
22import android.util.Log;
23import android.view.IWindowManager;
24import android.view.MotionEvent;
Charles Chen8c9a83f2018-12-18 17:44:10 +080025
Dave Mankofff4736812019-10-18 17:25:50 -040026import com.android.systemui.dagger.qualifiers.MainHandler;
Charles Chen8c9a83f2018-12-18 17:44:10 +080027import com.android.systemui.statusbar.NotificationRemoteInputManager;
28
29import javax.inject.Inject;
Charles Chen8c9a83f2018-12-18 17:44:10 +080030
31/** A controller to control all auto-hide things. */
Jorim Jaggi956ca412019-01-07 14:49:14 +010032public class AutoHideController {
Charles Chen8c9a83f2018-12-18 17:44:10 +080033 private static final String TAG = "AutoHideController";
34
35 private final IWindowManager mWindowManagerService;
36
37 private final Handler mHandler;
38 private final NotificationRemoteInputManager mRemoteInputManager;
Charles Chen8c9a83f2018-12-18 17:44:10 +080039 private StatusBar mStatusBar;
40 private NavigationBarFragment mNavigationBar;
41
Jorim Jaggi956ca412019-01-07 14:49:14 +010042 private int mDisplayId;
Charles Chen8c9a83f2018-12-18 17:44:10 +080043
44 private boolean mAutoHideSuspended;
45
Jorim Jaggi956ca412019-01-07 14:49:14 +010046 private static final long AUTO_HIDE_TIMEOUT_MS = 2250;
Charles Chen8c9a83f2018-12-18 17:44:10 +080047
48 private final Runnable mAutoHide = () -> {
Jorim Jaggi956ca412019-01-07 14:49:14 +010049 if (isAnyTransientBarShown()) {
50 hideTransientBars();
Charles Chen8c9a83f2018-12-18 17:44:10 +080051 }
52 };
53
54 @Inject
Dave Mankofff4736812019-10-18 17:25:50 -040055 public AutoHideController(Context context, @MainHandler Handler handler,
Lucas Dupind236ee32019-10-08 15:33:59 -070056 NotificationRemoteInputManager notificationRemoteInputManager,
57 IWindowManager iWindowManager) {
Charles Chen8c9a83f2018-12-18 17:44:10 +080058 mHandler = handler;
Lucas Dupind236ee32019-10-08 15:33:59 -070059 mRemoteInputManager = notificationRemoteInputManager;
60 mWindowManagerService = iWindowManager;
Charles Chen8c9a83f2018-12-18 17:44:10 +080061
62 mDisplayId = context.getDisplayId();
63 }
64
Charles Chen8c9a83f2018-12-18 17:44:10 +080065 void setStatusBar(StatusBar statusBar) {
66 mStatusBar = statusBar;
67 }
68
69 void setNavigationBar(NavigationBarFragment navigationBar) {
70 mNavigationBar = navigationBar;
71 }
72
Jorim Jaggi956ca412019-01-07 14:49:14 +010073 private void hideTransientBars() {
Charles Chen8c9a83f2018-12-18 17:44:10 +080074 try {
Jorim Jaggi956ca412019-01-07 14:49:14 +010075 mWindowManagerService.hideTransientBars(mDisplayId);
Charles Chen8c9a83f2018-12-18 17:44:10 +080076 } catch (RemoteException ex) {
77 Log.w(TAG, "Cannot get WindowManager");
78 }
Jorim Jaggi956ca412019-01-07 14:49:14 +010079 if (mStatusBar != null) {
80 mStatusBar.clearTransient();
81 }
82 if (mNavigationBar != null) {
83 mNavigationBar.clearTransient();
84 }
Charles Chen8c9a83f2018-12-18 17:44:10 +080085 }
86
87 void resumeSuspendedAutoHide() {
88 if (mAutoHideSuspended) {
89 scheduleAutoHide();
90 Runnable checkBarModesRunnable = getCheckBarModesRunnable();
91 if (checkBarModesRunnable != null) {
92 mHandler.postDelayed(checkBarModesRunnable, 500); // longer than home -> launcher
93 }
94 }
95 }
96
97 void suspendAutoHide() {
98 mHandler.removeCallbacks(mAutoHide);
99 Runnable checkBarModesRunnable = getCheckBarModesRunnable();
100 if (checkBarModesRunnable != null) {
101 mHandler.removeCallbacks(checkBarModesRunnable);
102 }
Jorim Jaggi956ca412019-01-07 14:49:14 +0100103 mAutoHideSuspended = isAnyTransientBarShown();
Charles Chen8c9a83f2018-12-18 17:44:10 +0800104 }
105
106 void touchAutoHide() {
107 // update transient bar auto hide
Jorim Jaggi956ca412019-01-07 14:49:14 +0100108 if (isAnyTransientBarShown()) {
Charles Chen8c9a83f2018-12-18 17:44:10 +0800109 scheduleAutoHide();
110 } else {
111 cancelAutoHide();
112 }
113 }
114
115 private Runnable getCheckBarModesRunnable() {
Jorim Jaggi956ca412019-01-07 14:49:14 +0100116 if (mStatusBar != null) {
Charles Chen8c9a83f2018-12-18 17:44:10 +0800117 return () -> mStatusBar.checkBarModes();
Jorim Jaggi956ca412019-01-07 14:49:14 +0100118 } else if (mNavigationBar != null) {
Charles Chen8c9a83f2018-12-18 17:44:10 +0800119 return () -> mNavigationBar.checkNavBarModes();
120 } else {
121 return null;
122 }
123 }
124
125 private void cancelAutoHide() {
126 mAutoHideSuspended = false;
127 mHandler.removeCallbacks(mAutoHide);
128 }
129
130 private void scheduleAutoHide() {
131 cancelAutoHide();
Jorim Jaggi956ca412019-01-07 14:49:14 +0100132 mHandler.postDelayed(mAutoHide, AUTO_HIDE_TIMEOUT_MS);
Charles Chen8c9a83f2018-12-18 17:44:10 +0800133 }
134
135 void checkUserAutoHide(MotionEvent event) {
Jorim Jaggi956ca412019-01-07 14:49:14 +0100136 boolean shouldAutoHide = isAnyTransientBarShown()
Charles Chen8c9a83f2018-12-18 17:44:10 +0800137 && event.getAction() == MotionEvent.ACTION_OUTSIDE // touch outside the source bar.
138 && event.getX() == 0 && event.getY() == 0;
Jorim Jaggi956ca412019-01-07 14:49:14 +0100139 if (mStatusBar != null) {
Charles Chen8c9a83f2018-12-18 17:44:10 +0800140 // a touch outside both bars
141 shouldAutoHide &= !mRemoteInputManager.getController().isRemoteInputActive();
142 }
143 if (shouldAutoHide) {
144 userAutoHide();
145 }
146 }
147
148 private void userAutoHide() {
149 cancelAutoHide();
150 mHandler.postDelayed(mAutoHide, 350); // longer than app gesture -> flag clear
151 }
152
Jorim Jaggi956ca412019-01-07 14:49:14 +0100153 private boolean isAnyTransientBarShown() {
154 return (mStatusBar != null && mStatusBar.isTransientShown())
155 || mNavigationBar != null && mNavigationBar.isTransientShown();
Charles Chen8c9a83f2018-12-18 17:44:10 +0800156 }
157}