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 static com.android.systemui.shared.Flags.shadeAllowBackGesture; 24 25 import android.annotation.LongDef; 26 import android.content.Context; 27 import android.content.res.Resources; 28 import android.view.ViewConfiguration; 29 import android.view.WindowManagerPolicyConstants; 30 31 import com.android.internal.policy.ScreenDecorationsUtils; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 import java.util.StringJoiner; 36 37 /** 38 * Various shared constants between Launcher and SysUI as part of quickstep 39 */ 40 public class QuickStepContract { 41 42 public static final String KEY_EXTRA_SYSUI_PROXY = "extra_sysui_proxy"; 43 public static final String KEY_EXTRA_UNFOLD_ANIMATION_FORWARDER = "extra_unfold_animation"; 44 // See ISysuiUnlockAnimationController.aidl 45 public static final String KEY_EXTRA_UNLOCK_ANIMATION_CONTROLLER = "unlock_animation"; 46 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 long SYSUI_STATE_SCREEN_PINNING = 1L << 0; 55 // The navigation bar is hidden due to immersive mode 56 public static final long SYSUI_STATE_NAV_BAR_HIDDEN = 1L << 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 long SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED = 1L << 2; 60 // The keyguard bouncer is showing 61 public static final long SYSUI_STATE_BOUNCER_SHOWING = 1L << 3; 62 // The navigation bar a11y button should be shown 63 public static final long SYSUI_STATE_A11Y_BUTTON_CLICKABLE = 1L << 4; 64 // The navigation bar a11y button shortcut is available 65 public static final long SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE = 1L << 5; 66 // The keyguard is showing and not occluded 67 public static final long SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING = 1L << 6; 68 // The recents feature is disabled (either by SUW/SysUI/device policy) 69 public static final long SYSUI_STATE_OVERVIEW_DISABLED = 1L << 7; 70 // The home feature is disabled (either by SUW/SysUI/device policy) 71 public static final long SYSUI_STATE_HOME_DISABLED = 1L << 8; 72 // The keyguard is showing, but occluded 73 public static final long SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED = 1L << 9; 74 // The search feature is disabled (either by SUW/SysUI/device policy) 75 public static final long SYSUI_STATE_SEARCH_DISABLED = 1L << 10; 76 // The notification panel is expanded and interactive (either locked or unlocked), and quick 77 // settings is expanded. 78 public static final long SYSUI_STATE_QUICK_SETTINGS_EXPANDED = 1L << 11; 79 // Winscope tracing is enabled 80 public static final long SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION = 1L << 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 long SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED = 1L << 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 long SYSUI_STATE_BUBBLES_EXPANDED = 1L << 14; 89 // A SysUI dialog is showing. 90 public static final long SYSUI_STATE_DIALOG_SHOWING = 1L << 15; 91 // The one-handed mode is active 92 public static final long SYSUI_STATE_ONE_HANDED_ACTIVE = 1L << 16; 93 // Allow system gesture no matter the system bar(s) is visible or not 94 public static final long SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY = 1L << 17; 95 // The IME is showing 96 public static final long SYSUI_STATE_IME_SHOWING = 1L << 18; 97 // The window magnification is overlapped with system gesture insets at the bottom. 98 public static final long SYSUI_STATE_MAGNIFICATION_OVERLAP = 1L << 19; 99 // ImeSwitcher is showing 100 public static final long SYSUI_STATE_IME_SWITCHER_SHOWING = 1L << 20; 101 // Device dozing/AOD state 102 public static final long SYSUI_STATE_DEVICE_DOZING = 1L << 21; 103 // The home feature is disabled (either by SUW/SysUI/device policy) 104 public static final long SYSUI_STATE_BACK_DISABLED = 1L << 22; 105 // The bubble stack is expanded AND the mange menu for bubbles is expanded on top of it. 106 public static final long SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED = 1L << 23; 107 // The voice interaction session window is showing 108 public static final long SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING = 1L << 25; 109 // Freeform windows are showing in desktop mode 110 public static final long SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE = 1L << 26; 111 // Device dreaming state 112 public static final long SYSUI_STATE_DEVICE_DREAMING = 1L << 27; 113 // Whether the device is currently awake (as opposed to asleep, see WakefulnessLifecycle). 114 // Note that the device is awake on while waking up on, but not while going to sleep. 115 public static final long SYSUI_STATE_AWAKE = 1L << 28; 116 // Whether the device is currently transitioning between awake/asleep indicated by 117 // SYSUI_STATE_AWAKE. 118 public static final long SYSUI_STATE_WAKEFULNESS_TRANSITION = 1L << 29; 119 // The notification panel expansion fraction is > 0 120 public static final long SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE = 1L << 30; 121 // When keyguard will be dismissed but didn't start animation yet 122 public static final long SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY = 1L << 31; 123 // Physical keyboard shortcuts helper is showing 124 public static final long SYSUI_STATE_SHORTCUT_HELPER_SHOWING = 1L << 32; 125 // Touchpad gestures are disabled 126 public static final long SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED = 1L << 33; 127 128 // Mask for SystemUiStateFlags to isolate SYSUI_STATE_AWAKE and 129 // SYSUI_STATE_WAKEFULNESS_TRANSITION, to match WAKEFULNESS_* constants 130 public static final long SYSUI_STATE_WAKEFULNESS_MASK = 131 SYSUI_STATE_AWAKE | SYSUI_STATE_WAKEFULNESS_TRANSITION; 132 // Mirroring the WakefulnessLifecycle#Wakefulness states 133 public static final long WAKEFULNESS_ASLEEP = 0; 134 public static final long WAKEFULNESS_AWAKE = SYSUI_STATE_AWAKE; 135 public static final long WAKEFULNESS_GOING_TO_SLEEP = SYSUI_STATE_WAKEFULNESS_TRANSITION; 136 public static final long WAKEFULNESS_WAKING = 137 SYSUI_STATE_WAKEFULNESS_TRANSITION | SYSUI_STATE_AWAKE; 138 139 // Whether the back gesture is allowed (or ignored) by the Shade 140 public static final boolean ALLOW_BACK_GESTURE_IN_SHADE = shadeAllowBackGesture(); 141 142 @Retention(RetentionPolicy.SOURCE) 143 @LongDef({SYSUI_STATE_SCREEN_PINNING, 144 SYSUI_STATE_NAV_BAR_HIDDEN, 145 SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED, 146 SYSUI_STATE_QUICK_SETTINGS_EXPANDED, 147 SYSUI_STATE_BOUNCER_SHOWING, 148 SYSUI_STATE_A11Y_BUTTON_CLICKABLE, 149 SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE, 150 SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING, 151 SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED, 152 SYSUI_STATE_OVERVIEW_DISABLED, 153 SYSUI_STATE_HOME_DISABLED, 154 SYSUI_STATE_SEARCH_DISABLED, 155 SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION, 156 SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED, 157 SYSUI_STATE_BUBBLES_EXPANDED, 158 SYSUI_STATE_DIALOG_SHOWING, 159 SYSUI_STATE_ONE_HANDED_ACTIVE, 160 SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY, 161 SYSUI_STATE_IME_SHOWING, 162 SYSUI_STATE_MAGNIFICATION_OVERLAP, 163 SYSUI_STATE_IME_SWITCHER_SHOWING, 164 SYSUI_STATE_DEVICE_DOZING, 165 SYSUI_STATE_BACK_DISABLED, 166 SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED, 167 SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING, 168 SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE, 169 SYSUI_STATE_DEVICE_DREAMING, 170 SYSUI_STATE_AWAKE, 171 SYSUI_STATE_WAKEFULNESS_TRANSITION, 172 SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE, 173 SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY, 174 SYSUI_STATE_SHORTCUT_HELPER_SHOWING, 175 SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED, 176 }) 177 public @interface SystemUiStateFlags {} 178 getSystemUiStateString(long flags)179 public static String getSystemUiStateString(long flags) { 180 StringJoiner str = new StringJoiner("|"); 181 if ((flags & SYSUI_STATE_SCREEN_PINNING) != 0) { 182 str.add("screen_pinned"); 183 } 184 if ((flags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) { 185 str.add("overview_disabled"); 186 } 187 if ((flags & SYSUI_STATE_HOME_DISABLED) != 0) { 188 str.add("home_disabled"); 189 } 190 if ((flags & SYSUI_STATE_SEARCH_DISABLED) != 0) { 191 str.add("search_disabled"); 192 } 193 if ((flags & SYSUI_STATE_NAV_BAR_HIDDEN) != 0) { 194 str.add("navbar_hidden"); 195 } 196 if ((flags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0) { 197 str.add("notif_expanded"); 198 } 199 if ((flags & SYSUI_STATE_QUICK_SETTINGS_EXPANDED) != 0) { 200 str.add("qs_visible"); 201 } 202 if ((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) != 0) { 203 str.add("keygrd_visible"); 204 } 205 if ((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0) { 206 str.add("keygrd_occluded"); 207 } 208 if ((flags & SYSUI_STATE_BOUNCER_SHOWING) != 0) { 209 str.add("bouncer_visible"); 210 } 211 if ((flags & SYSUI_STATE_DIALOG_SHOWING) != 0) { 212 str.add("dialog_showing"); 213 } 214 if ((flags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0) { 215 str.add("a11y_click"); 216 } 217 if ((flags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0) { 218 str.add("a11y_long_click"); 219 } 220 if ((flags & SYSUI_STATE_DISABLE_GESTURE_SPLIT_INVOCATION) != 0) { 221 str.add("disable_gesture_split_invocation"); 222 } 223 if ((flags & SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED) != 0) { 224 str.add("asst_gesture_constrain"); 225 } 226 if ((flags & SYSUI_STATE_BUBBLES_EXPANDED) != 0) { 227 str.add("bubbles_expanded"); 228 } 229 if ((flags & SYSUI_STATE_ONE_HANDED_ACTIVE) != 0) { 230 str.add("one_handed_active"); 231 } 232 if ((flags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) { 233 str.add("allow_gesture"); 234 } 235 if ((flags & SYSUI_STATE_IME_SHOWING) != 0) { 236 str.add("ime_visible"); 237 } 238 if ((flags & SYSUI_STATE_MAGNIFICATION_OVERLAP) != 0) { 239 str.add("magnification_overlap"); 240 } 241 if ((flags & SYSUI_STATE_IME_SWITCHER_SHOWING) != 0) { 242 str.add("ime_switcher_showing"); 243 } 244 if ((flags & SYSUI_STATE_DEVICE_DOZING) != 0) { 245 str.add("device_dozing"); 246 } 247 if ((flags & SYSUI_STATE_BACK_DISABLED) != 0) { 248 str.add("back_disabled"); 249 } 250 if ((flags & SYSUI_STATE_BUBBLES_MANAGE_MENU_EXPANDED) != 0) { 251 str.add("bubbles_mange_menu_expanded"); 252 } 253 if ((flags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0) { 254 str.add("vis_win_showing"); 255 } 256 if ((flags & SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0) { 257 str.add("freeform_active_in_desktop_mode"); 258 } 259 if ((flags & SYSUI_STATE_DEVICE_DREAMING) != 0) { 260 str.add("device_dreaming"); 261 } 262 if ((flags & SYSUI_STATE_WAKEFULNESS_TRANSITION) != 0) { 263 str.add("wakefulness_transition"); 264 } 265 if ((flags & SYSUI_STATE_AWAKE) != 0) { 266 str.add("awake"); 267 } 268 if ((flags & SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE) != 0) { 269 str.add("notif_visible"); 270 } 271 if ((flags & SYSUI_STATE_STATUS_BAR_KEYGUARD_GOING_AWAY) != 0) { 272 str.add("keygrd_going_away"); 273 } 274 if ((flags & SYSUI_STATE_SHORTCUT_HELPER_SHOWING) != 0) { 275 str.add("shortcut_helper_showing"); 276 } 277 if ((flags & SYSUI_STATE_TOUCHPAD_GESTURES_DISABLED) != 0) { 278 str.add("touchpad_gestures_disabled"); 279 } 280 281 return str.toString(); 282 } 283 284 /** 285 * Ratio of quickstep touch slop (when system takes over the touch) to view touch slop 286 */ 287 public static final float QUICKSTEP_TOUCH_SLOP_RATIO = 3; 288 289 /** 290 * Touch slop for quickstep gesture 291 */ getQuickStepTouchSlopPx(Context context)292 public static final float getQuickStepTouchSlopPx(Context context) { 293 return QUICKSTEP_TOUCH_SLOP_RATIO * ViewConfiguration.get(context).getScaledTouchSlop(); 294 } 295 296 /** 297 * Returns whether the specified sysui state is such that the assistant gesture should be 298 * disabled. 299 */ isAssistantGestureDisabled(long sysuiStateFlags)300 public static boolean isAssistantGestureDisabled(long sysuiStateFlags) { 301 if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) { 302 sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN; 303 } 304 // Disable when in quick settings, screen pinning, immersive, the bouncer is showing, 305 // or search is disabled 306 long disableFlags = SYSUI_STATE_SCREEN_PINNING 307 | SYSUI_STATE_NAV_BAR_HIDDEN 308 | SYSUI_STATE_BOUNCER_SHOWING 309 | SYSUI_STATE_SEARCH_DISABLED 310 | SYSUI_STATE_QUICK_SETTINGS_EXPANDED; 311 if ((sysuiStateFlags & disableFlags) != 0) { 312 return true; 313 } 314 315 // Disable when notifications are showing (only if unlocked) 316 if ((sysuiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0 317 && (sysuiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING) == 0) { 318 return true; 319 } 320 321 return false; 322 } 323 324 /** 325 * Returns whether the specified sysui state is such that the back gesture should be 326 * disabled. 327 */ isBackGestureDisabled(long sysuiStateFlags, boolean forTrackpad)328 public static boolean isBackGestureDisabled(long sysuiStateFlags, boolean forTrackpad) { 329 // Always allow when the bouncer/global actions/voice session is showing (even on top of 330 // the keyguard) 331 if ((sysuiStateFlags & SYSUI_STATE_BOUNCER_SHOWING) != 0 332 || (sysuiStateFlags & SYSUI_STATE_DIALOG_SHOWING) != 0 333 || (sysuiStateFlags & SYSUI_STATE_VOICE_INTERACTION_WINDOW_SHOWING) != 0) { 334 return false; 335 } 336 if ((sysuiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0) { 337 sysuiStateFlags &= ~SYSUI_STATE_NAV_BAR_HIDDEN; 338 } 339 340 return (sysuiStateFlags & getBackGestureDisabledMask(forTrackpad)) != 0; 341 } 342 getBackGestureDisabledMask(boolean forTrackpad)343 private static long getBackGestureDisabledMask(boolean forTrackpad) { 344 // Disable when in immersive, or the notifications are interactive 345 long disableFlags = SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING; 346 if (!forTrackpad) { 347 disableFlags |= SYSUI_STATE_NAV_BAR_HIDDEN; 348 } 349 350 // EdgeBackGestureHandler ignores Back gesture when SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED. 351 // To allow Shade to respond to Back, we're bypassing this check (behind a flag). 352 if (!ALLOW_BACK_GESTURE_IN_SHADE) { 353 disableFlags |= SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED; 354 } 355 return disableFlags; 356 } 357 358 /** 359 * @return whether this nav bar mode is edge to edge 360 */ isGesturalMode(int mode)361 public static boolean isGesturalMode(int mode) { 362 return mode == NAV_BAR_MODE_GESTURAL; 363 } 364 365 /** 366 * @return whether this nav bar mode is swipe up 367 */ isSwipeUpMode(int mode)368 public static boolean isSwipeUpMode(int mode) { 369 return mode == NAV_BAR_MODE_2BUTTON; 370 } 371 372 /** 373 * @return whether this nav bar mode is 3 button 374 */ isLegacyMode(int mode)375 public static boolean isLegacyMode(int mode) { 376 return mode == NAV_BAR_MODE_3BUTTON; 377 } 378 379 /** 380 * Corner radius that should be used on windows in order to cover the display. 381 * These values are expressed in pixels because they should not respect display or font 382 * scaling. The corner radius may change when folding/unfolding the device. 383 */ getWindowCornerRadius(Context context)384 public static float getWindowCornerRadius(Context context) { 385 return ScreenDecorationsUtils.getWindowCornerRadius(context); 386 } 387 388 /** 389 * If live rounded corners are supported on windows. 390 */ supportsRoundedCornersOnWindows(Resources resources)391 public static boolean supportsRoundedCornersOnWindows(Resources resources) { 392 return ScreenDecorationsUtils.supportsRoundedCornersOnWindows(resources); 393 } 394 } 395