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 
40     public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy";
41     public static final String KEY_EXTRA_INPUT_MONITOR = "extra_input_monitor";
42     public static final String KEY_EXTRA_WINDOW_CORNER_RADIUS = "extra_window_corner_radius";
43     public static final String KEY_EXTRA_SUPPORTS_WINDOW_CORNERS = "extra_supports_window_corners";
44 
45     public static final String NAV_BAR_MODE_2BUTTON_OVERLAY =
46             WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
47     public static final String NAV_BAR_MODE_3BUTTON_OVERLAY =
48             WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
49     public static final String NAV_BAR_MODE_GESTURAL_OVERLAY =
50             WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
51 
52     // Overview is disabled, either because the device is in lock task mode, or because the device
53     // policy has disabled the feature
54     public static final int SYSUI_STATE_SCREEN_PINNING = 1 << 0;
55     // The navigation bar is hidden due to immersive mode
56     public static final int SYSUI_STATE_NAV_BAR_HIDDEN = 1 << 1;
57     // The notification panel is expanded and interactive (either locked or unlocked), and the
58     // quick settings is not expanded
59     public static final int SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED = 1 << 2;
60     // The keyguard bouncer is showing
61     public static final int SYSUI_STATE_BOUNCER_SHOWING = 1 << 3;
62     // The navigation bar a11y button should be shown
63     public static final int SYSUI_STATE_A11Y_BUTTON_CLICKABLE = 1 << 4;
64     // The navigation bar a11y button shortcut is available
65     public static final int SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE = 1 << 5;
66     // The keyguard is showing and not occluded
67     public static final int SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING = 1 << 6;
68     // The recents feature is disabled (either by SUW/SysUI/device policy)
69     public static final int SYSUI_STATE_OVERVIEW_DISABLED = 1 << 7;
70     // The home feature is disabled (either by SUW/SysUI/device policy)
71     public static final int SYSUI_STATE_HOME_DISABLED = 1 << 8;
72     // The keyguard is showing, but occluded
73     public static final int SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED = 1 << 9;
74     // The search feature is disabled (either by SUW/SysUI/device policy)
75     public static final int SYSUI_STATE_SEARCH_DISABLED = 1 << 10;
76     // The notification panel is expanded and interactive (either locked or unlocked), and quick
77     // settings is expanded.
78     public static final int SYSUI_STATE_QUICK_SETTINGS_EXPANDED = 1 << 11;
79     // Winscope tracing is enabled
80     public static final int SYSUI_STATE_TRACING_ENABLED = 1 << 12;
81     // The Assistant gesture should be constrained. It is up to the launcher implementation to
82     // decide how to constrain it
83     public static final int SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED = 1 << 13;
84     // The bubble stack is expanded. This means that the home gesture should be ignored, since a
85     // swipe up is an attempt to close the bubble stack, but that the back gesture should remain
86     // enabled (since it's used to navigate back within the bubbled app, or to collapse the bubble
87     // stack.
88     public static final int SYSUI_STATE_BUBBLES_EXPANDED = 1 << 14;
89     // The global actions dialog is showing
90     public static final int SYSUI_STATE_GLOBAL_ACTIONS_SHOWING = 1 << 15;
91 
92     @Retention(RetentionPolicy.SOURCE)
93     @IntDef({SYSUI_STATE_SCREEN_PINNING,
94             SYSUI_STATE_NAV_BAR_HIDDEN,
95             SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
96             SYSUI_STATE_QUICK_SETTINGS_EXPANDED,
97             SYSUI_STATE_BOUNCER_SHOWING,
98             SYSUI_STATE_A11Y_BUTTON_CLICKABLE,
99             SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE,
100             SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING,
101             SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED,
102             SYSUI_STATE_OVERVIEW_DISABLED,
103             SYSUI_STATE_HOME_DISABLED,
104             SYSUI_STATE_SEARCH_DISABLED,
105             SYSUI_STATE_TRACING_ENABLED,
106             SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED,
107             SYSUI_STATE_BUBBLES_EXPANDED,
108             SYSUI_STATE_GLOBAL_ACTIONS_SHOWING
109     })
110     public @interface SystemUiStateFlags {}
111 
getSystemUiStateString(int flags)112     public static String getSystemUiStateString(int flags) {
113         StringJoiner str = new StringJoiner("|");
114         str.add((flags & SYSUI_STATE_SCREEN_PINNING) != 0 ? "screen_pinned" : "");
115         str.add((flags & SYSUI_STATE_OVERVIEW_DISABLED) != 0 ? "overview_disabled" : "");
116         str.add((flags & SYSUI_STATE_HOME_DISABLED) != 0 ? "home_disabled" : "");
117         str.add((flags & SYSUI_STATE_SEARCH_DISABLED) != 0 ? "search_disabled" : "");
118         str.add((flags & SYSUI_STATE_NAV_BAR_HIDDEN) != 0 ? "navbar_hidden" : "");
119         str.add((flags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0 ? "notif_visible" : "");
120         str.add((flags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) != 0 ? "qs_visible" : "");
121         str.add((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) != 0 ? "keygrd_visible" : "");
122         str.add((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0
123                 ? "keygrd_occluded" : "");
124         str.add((flags & SYSUI_STATE_BOUNCER_SHOWING) != 0 ? "bouncer_visible" : "");
125         str.add((flags & SYSUI_STATE_GLOBAL_ACTIONS_SHOWING) != 0 ? "global_actions" : "");
126         str.add((flags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0 ? "a11y_click" : "");
127         str.add((flags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0 ? "a11y_long_click" : "");
128         str.add((flags & SYSUI_STATE_TRACING_ENABLED) != 0 ? "tracing" : "");
129         str.add((flags & SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED) != 0
130                 ? "asst_gesture_constrain" : "");
131         str.add((flags & SYSUI_STATE_BUBBLES_EXPANDED) != 0 ? "bubbles_expanded" : "");
132         return str.toString();
133     }
134 
135     /**
136      * Ratio of quickstep touch slop (when system takes over the touch) to view touch slop
137      */
138     public static final float QUICKSTEP_TOUCH_SLOP_RATIO = 3;
139 
140     /**
141      * Touch slop for quickstep gesture
142      */
getQuickStepTouchSlopPx(Context context)143     public static final float getQuickStepTouchSlopPx(Context context) {
144         return QUICKSTEP_TOUCH_SLOP_RATIO * ViewConfiguration.get(context).getScaledTouchSlop();
145     }
146 
147     /**
148      * Touch slopes and thresholds for quick step operations. Drag slop is the point where the
149      * home button press/long press over are ignored and will start to drag when exceeded and the
150      * touch slop is when the respected operation will occur when exceeded. Touch slop must be
151      * larger than the drag slop.
152      */
getQuickStepDragSlopPx()153     public static int getQuickStepDragSlopPx() {
154         return convertDpToPixel(10);
155     }
156 
getQuickStepTouchSlopPx()157     public static int getQuickStepTouchSlopPx() {
158         return convertDpToPixel(24);
159     }
160 
getQuickScrubTouchSlopPx()161     public static int getQuickScrubTouchSlopPx() {
162         return convertDpToPixel(24);
163     }
164 
convertDpToPixel(float dp)165     private static int convertDpToPixel(float dp) {
166         return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
167     }
168 
169     /**
170      * Returns whether the specified sysui state is such that the assistant gesture should be
171      * disabled.
172      */
isAssistantGestureDisabled(int sysuiStateFlags)173     public static boolean isAssistantGestureDisabled(int sysuiStateFlags) {
174         // Disable when in quick settings, screen pinning, immersive, the bouncer is showing,
175         // or search is disabled
176         int disableFlags = SYSUI_STATE_SCREEN_PINNING
177                 | SYSUI_STATE_NAV_BAR_HIDDEN
178                 | SYSUI_STATE_BOUNCER_SHOWING
179                 | SYSUI_STATE_SEARCH_DISABLED
180                 | SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
181         if ((sysuiStateFlags & disableFlags) != 0) {
182             return true;
183         }
184 
185         // Disable when notifications are showing (only if unlocked)
186         if ((sysuiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0
187                 && (sysuiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) == 0) {
188             return true;
189         }
190 
191         return false;
192     }
193 
194     /**
195      * Returns whether the specified sysui state is such that the back gesture should be
196      * disabled.
197      */
isBackGestureDisabled(int sysuiStateFlags)198     public static boolean isBackGestureDisabled(int sysuiStateFlags) {
199         // Always allow when the bouncer/global actions is showing (even on top of the keyguard)
200         if ((sysuiStateFlags & SYSUI_STATE_BOUNCER_SHOWING) != 0
201                 || (sysuiStateFlags & SYSUI_STATE_GLOBAL_ACTIONS_SHOWING) != 0) {
202             return false;
203         }
204         // Disable when in immersive, or the notifications are interactive
205         int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN
206                 | SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
207                 | SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
208         return (sysuiStateFlags & disableFlags) != 0;
209     }
210 
211     /**
212      * @return whether this nav bar mode is edge to edge
213      */
isGesturalMode(int mode)214     public static boolean isGesturalMode(int mode) {
215         return mode == NAV_BAR_MODE_GESTURAL;
216     }
217 
218     /**
219      * @return whether this nav bar mode is swipe up
220      */
isSwipeUpMode(int mode)221     public static boolean isSwipeUpMode(int mode) {
222         return mode == NAV_BAR_MODE_2BUTTON;
223     }
224 
225     /**
226      * @return whether this nav bar mode is 3 button
227      */
isLegacyMode(int mode)228     public static boolean isLegacyMode(int mode) {
229         return mode == NAV_BAR_MODE_3BUTTON;
230     }
231 
232     /**
233      * Corner radius that should be used on windows in order to cover the display.
234      * These values are expressed in pixels because they should not respect display or font
235      * scaling, this means that we don't have to reload them on config changes.
236      */
getWindowCornerRadius(Resources resources)237     public static float getWindowCornerRadius(Resources resources) {
238         return ScreenDecorationsUtils.getWindowCornerRadius(resources);
239     }
240 
241     /**
242      * If live rounded corners are supported on windows.
243      */
supportsRoundedCornersOnWindows(Resources resources)244     public static boolean supportsRoundedCornersOnWindows(Resources resources) {
245         return ScreenDecorationsUtils.supportsRoundedCornersOnWindows(resources);
246     }
247 }
248