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.shared.system;
18 
19 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
20 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
21 import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
22 
23 import android.annotation.IntDef;
24 import android.content.Context;
25 import android.content.res.Resources;
26 import android.view.ViewConfiguration;
27 import android.view.WindowManagerPolicyConstants;
28 
29 import com.android.internal.policy.ScreenDecorationsUtils;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 import java.util.StringJoiner;
34 
35 /**
36  * Various shared constants between Launcher and SysUI as part of quickstep
37  */
38 public class QuickStepContract {
39     // Fully qualified name of the Launcher activity.
40     public static final String LAUNCHER_ACTIVITY_CLASS_NAME =
41             "com.google.android.apps.nexuslauncher.NexusLauncherActivity";
42 
43     public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy";
44     public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius";
45     public static final String KEY_EXTRA_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners";
46     // See IPip.aidl
47     public static final String KEY_EXTRA_SHELL_PIP = "extra_shell_pip";
48     // See ISplitScreen.aidl
49     public static final String KEY_EXTRA_SHELL_SPLIT_SCREEN = "extra_shell_split_screen";
50     // See IOneHanded.aidl
51     public static final String KEY_EXTRA_SHELL_ONE_HANDED = "extra_shell_one_handed";
52     // See IShellTransitions.aidl
53     public static final String KEY_EXTRA_SHELL_SHELL_TRANSITIONS =
54             "extra_shell_shell_transitions";
55     // See IStartingWindow.aidl
56     public static final String KEY_EXTRA_SHELL_STARTING_WINDOW =
57             "extra_shell_starting_window";
58     // See ISmartspaceTransitionController.aidl
59     public static final String KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER = "smartspace_transition";
60     // See IRecentTasks.aidl
61     public static final String KEY_EXTRA_RECENT_TASKS = "recent_tasks";
62 
63     public static final String NAV_BAR_MODE_2BUTTON_OVERLAY =
64             WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
65     public static final String NAV_BAR_MODE_3BUTTON_OVERLAY =
66             WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
67     public static final String NAV_BAR_MODE_GESTURAL_OVERLAY =
68             WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
69 
70     // Overview is disabled, either because the device is in lock task mode, or because the device
71     // policy has disabled the feature
72     public static final int SYSUI_STATE_SCREEN_PINNING = 1 << 0;
73     // The navigation bar is hidden due to immersive mode
74     public static final int SYSUI_STATE_NAV_BAR_HIDDEN = 1 << 1;
75     // The notification panel is expanded and interactive (either locked or unlocked), and the
76     // quick settings is not expanded
77     public static final int SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED = 1 << 2;
78     // The keyguard bouncer is showing
79     public static final int SYSUI_STATE_BOUNCER_SHOWING = 1 << 3;
80     // The navigation bar a11y button should be shown
81     public static final int SYSUI_STATE_A11Y_BUTTON_CLICKABLE = 1 << 4;
82     // The navigation bar a11y button shortcut is available
83     public static final int SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE = 1 << 5;
84     // The keyguard is showing and not occluded
85     public static final int SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING = 1 << 6;
86     // The recents feature is disabled (either by SUW/SysUI/device policy)
87     public static final int SYSUI_STATE_OVERVIEW_DISABLED = 1 << 7;
88     // The home feature is disabled (either by SUW/SysUI/device policy)
89     public static final int SYSUI_STATE_HOME_DISABLED = 1 << 8;
90     // The keyguard is showing, but occluded
91     public static final int SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED = 1 << 9;
92     // The search feature is disabled (either by SUW/SysUI/device policy)
93     public static final int SYSUI_STATE_SEARCH_DISABLED = 1 << 10;
94     // The notification panel is expanded and interactive (either locked or unlocked), and quick
95     // settings is expanded.
96     public static final int SYSUI_STATE_QUICK_SETTINGS_EXPANDED = 1 << 11;
97     // Winscope tracing is enabled
98     public static final int SYSUI_STATE_TRACING_ENABLED = 1 << 12;
99     // The Assistant gesture should be constrained. It is up to the launcher implementation to
100     // decide how to constrain it
101     public static final int SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED = 1 << 13;
102     // The bubble stack is expanded. This means that the home gesture should be ignored, since a
103     // swipe up is an attempt to close the bubble stack, but that the back gesture should remain
104     // enabled (since it's used to navigate back within the bubbled app, or to collapse the bubble
105     // stack.
106     public static final int SYSUI_STATE_BUBBLES_EXPANDED = 1 << 14;
107     // The global actions dialog is showing
108     public static final int SYSUI_STATE_GLOBAL_ACTIONS_SHOWING = 1 << 15;
109     // The one-handed mode is active
110     public static final int SYSUI_STATE_ONE_HANDED_ACTIVE = 1 << 16;
111     // Allow system gesture no matter the system bar(s) is visible or not
112     public static final int SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY = 1 << 17;
113     // The IME is showing
114     public static final int SYSUI_STATE_IME_SHOWING = 1 << 18;
115     // The window magnification is overlapped with system gesture insets at the bottom.
116     public static final int SYSUI_STATE_MAGNIFICATION_OVERLAP = 1 << 19;
117     // ImeSwitcher is showing
118     public static final int SYSUI_STATE_IME_SWITCHER_SHOWING = 1 << 20;
119     // Device dozing/AOD state
120     public static final int SYSUI_STATE_DEVICE_DOZING = 1 << 21;
121     // The home feature is disabled (either by SUW/SysUI/device policy)
122     public static final int SYSUI_STATE_BACK_DISABLED = 1 << 22;
123     // The bubble stack is expanded AND the mange menu for bubbles is expanded on top of it.
124     public static final int SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED = 1 << 23;
125 
126     @Retention(RetentionPolicy.SOURCE)
127     @IntDef({SYSUI_STATE_SCREEN_PINNING,
128             SYSUI_STATE_NAV_BAR_HIDDEN,
129             SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
130             SYSUI_STATE_QUICK_SETTINGS_EXPANDED,
131             SYSUI_STATE_BOUNCER_SHOWING,
132             SYSUI_STATE_A11Y_BUTTON_CLICKABLE,
133             SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE,
134             SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
135             SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
136             SYSUI_STATE_OVERVIEW_DISABLED,
137             SYSUI_STATE_HOME_DISABLED,
138             SYSUI_STATE_SEARCH_DISABLED,
139             SYSUI_STATE_TRACING_ENABLED,
140             SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED,
141             SYSUI_STATE_BUBBLES_EXPANDED,
142             SYSUI_STATE_GLOBAL_ACTIONS_SHOWING,
143             SYSUI_STATE_ONE_HANDED_ACTIVE,
144             SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY,
145             SYSUI_STATE_IME_SHOWING,
146             SYSUI_STATE_MAGNIFICATION_OVERLAP,
147             SYSUI_STATE_IME_SWITCHER_SHOWING,
148             SYSUI_STATE_DEVICE_DOZING,
149             SYSUI_STATE_BACK_DISABLED,
150             SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED
151     })
152     public @interface SystemUiStateFlags {}
153 
getSystemUiStateString(int flags)154     public static String getSystemUiStateString(int flags) {
155         StringJoiner str = new StringJoiner("|");
156         str.add((flags & SYSUI_STATE_SCREEN_PINNING) != 0 ? "screen_pinned" : "");
157         str.add((flags & SYSUI_STATE_OVERVIEW_DISABLED) != 0 ? "overview_disabled" : "");
158         str.add((flags & SYSUI_STATE_HOME_DISABLED) != 0 ? "home_disabled" : "");
159         str.add((flags & SYSUI_STATE_SEARCH_DISABLED) != 0 ? "search_disabled" : "");
160         str.add((flags & SYSUI_STATE_NAV_BAR_HIDDEN) != 0 ? "navbar_hidden" : "");
161         str.add((flags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0 ? "notif_visible" : "");
162         str.add((flags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) != 0 ? "qs_visible" : "");
163         str.add((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) != 0 ? "keygrd_visible" : "");
164         str.add((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0
165                 ? "keygrd_occluded" : "");
166         str.add((flags & SYSUI_STATE_BOUNCER_SHOWING) != 0 ? "bouncer_visible" : "");
167         str.add((flags & SYSUI_STATE_GLOBAL_ACTIONS_SHOWING) != 0 ? "global_actions" : "");
168         str.add((flags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0 ? "a11y_click" : "");
169         str.add((flags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0 ? "a11y_long_click" : "");
170         str.add((flags & SYSUI_STATE_TRACING_ENABLED) != 0 ? "tracing" : "");
171         str.add((flags & SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED) != 0
172                 ? "asst_gesture_constrain" : "");
173         str.add((flags & SYSUI_STATE_BUBBLES_EXPANDED) != 0 ? "bubbles_expanded" : "");
174         str.add((flags & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0 ? "one_handed_active" : "");
175         str.add((flags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0
176                 ? "allow_gesture" : "");
177         str.add((flags & SYSUI_STATE_IME_SHOWING) != 0 ? "ime_visible" : "");
178         str.add((flags & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0 ? "magnification_overlap" : "");
179         str.add((flags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0 ? "ime_switcher_showing" : "");
180         str.add((flags & SYSUI_STATE_DEVICE_DOZING) != 0 ? "device_dozing" : "");
181         str.add((flags & SYSUI_STATE_BACK_DISABLED) != 0 ? "back_disabled" : "");
182         str.add((flags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0
183                 ? "bubbles_mange_menu_expanded" : "");
184         return str.toString();
185     }
186 
187     /**
188      * Ratio of quickstep touch slop (when system takes over the touch) to view touch slop
189      */
190     public static final float QUICKSTEP_TOUCH_SLOP_RATIO = 3;
191 
192     /**
193      * Touch slop for quickstep gesture
194      */
getQuickStepTouchSlopPx(Context context)195     public static final float getQuickStepTouchSlopPx(Context context) {
196         return QUICKSTEP_TOUCH_SLOP_RATIO * ViewConfiguration.get(context).getScaledTouchSlop();
197     }
198 
199     /**
200      * Touch slopes and thresholds for quick step operations. Drag slop is the point where the
201      * home button press/long press over are ignored and will start to drag when exceeded and the
202      * touch slop is when the respected operation will occur when exceeded. Touch slop must be
203      * larger than the drag slop.
204      */
getQuickStepDragSlopPx()205     public static int getQuickStepDragSlopPx() {
206         return convertDpToPixel(10);
207     }
208 
getQuickStepTouchSlopPx()209     public static int getQuickStepTouchSlopPx() {
210         return convertDpToPixel(24);
211     }
212 
getQuickScrubTouchSlopPx()213     public static int getQuickScrubTouchSlopPx() {
214         return convertDpToPixel(24);
215     }
216 
convertDpToPixel(float dp)217     private static int convertDpToPixel(float dp) {
218         return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
219     }
220 
221     /**
222      * Returns whether the specified sysui state is such that the assistant gesture should be
223      * disabled.
224      */
isAssistantGestureDisabled(int sysuiStateFlags)225     public static boolean isAssistantGestureDisabled(int sysuiStateFlags) {
226         if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) {
227             sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
228         }
229         // Disable when in quick settings, screen pinning, immersive, the bouncer is showing,
230         // or search is disabled
231         int disableFlags = SYSUI_STATE_SCREEN_PINNING
232                 | SYSUI_STATE_NAV_BAR_HIDDEN
233                 | SYSUI_STATE_BOUNCER_SHOWING
234                 | SYSUI_STATE_SEARCH_DISABLED
235                 | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
236         if ((sysuiStateFlags & disableFlags) != 0) {
237             return true;
238         }
239 
240         // Disable when notifications are showing (only if unlocked)
241         if ((sysuiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0
242                 && (sysuiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) == 0) {
243             return true;
244         }
245 
246         return false;
247     }
248 
249     /**
250      * Returns whether the specified sysui state is such that the back gesture should be
251      * disabled.
252      */
isBackGestureDisabled(int sysuiStateFlags)253     public static boolean isBackGestureDisabled(int sysuiStateFlags) {
254         // Always allow when the bouncer/global actions is showing (even on top of the keyguard)
255         if ((sysuiStateFlags & SYSUI_STATE_BOUNCER_SHOWING) != 0
256                 || (sysuiStateFlags & SYSUI_STATE_GLOBAL_ACTIONS_SHOWING) != 0) {
257             return false;
258         }
259         if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) {
260             sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN;
261         }
262         // Disable when in immersive, or the notifications are interactive
263         int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN
264                 | SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
265                 | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
266         return (sysuiStateFlags & disableFlags) != 0;
267     }
268 
269     /**
270      * @return whether this nav bar mode is edge to edge
271      */
isGesturalMode(int mode)272     public static boolean isGesturalMode(int mode) {
273         return mode == NAV_BAR_MODE_GESTURAL;
274     }
275 
276     /**
277      * @return whether this nav bar mode is swipe up
278      */
isSwipeUpMode(int mode)279     public static boolean isSwipeUpMode(int mode) {
280         return mode == NAV_BAR_MODE_2BUTTON;
281     }
282 
283     /**
284      * @return whether this nav bar mode is 3 button
285      */
isLegacyMode(int mode)286     public static boolean isLegacyMode(int mode) {
287         return mode == NAV_BAR_MODE_3BUTTON;
288     }
289 
290     /**
291      * Corner radius that should be used on windows in order to cover the display.
292      * These values are expressed in pixels because they should not respect display or font
293      * scaling, this means that we don't have to reload them on config changes.
294      */
getWindowCornerRadius(Context context)295     public static float getWindowCornerRadius(Context context) {
296         return ScreenDecorationsUtils.getWindowCornerRadius(context);
297     }
298 
299     /**
300      * If live rounded corners are supported on windows.
301      */
supportsRoundedCornersOnWindows(Resources resources)302     public static boolean supportsRoundedCornersOnWindows(Resources resources) {
303         return ScreenDecorationsUtils.supportsRoundedCornersOnWindows(resources);
304     }
305 }
306