PhoneWindowManager.java revision 5026936e49540449165fd5881231f8970a29ea91
1/* 2 * Copyright (C) 2006 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.server.policy; 18 19import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; 20import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; 21import static android.app.ActivityManager.StackId.HOME_STACK_ID; 22import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; 23import static android.content.pm.PackageManager.FEATURE_TELEVISION; 24import static android.content.pm.PackageManager.FEATURE_WATCH; 25import static android.content.res.Configuration.EMPTY; 26import static android.content.res.Configuration.UI_MODE_TYPE_CAR; 27import static android.content.res.Configuration.UI_MODE_TYPE_MASK; 28import static android.view.WindowManager.DOCKED_LEFT; 29import static android.view.WindowManager.DOCKED_RIGHT; 30import static android.view.WindowManager.DOCKED_TOP; 31import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION; 32import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; 33import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; 34import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW; 35import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 36import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; 37import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN; 38import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; 39import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR; 40import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; 41import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN; 42import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 43import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; 44import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 45import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 46import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 47import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; 48import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW; 49import static android.view.WindowManager.LayoutParams.MATCH_PARENT; 50import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND; 51import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT; 52import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 53import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 54import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT; 55import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR; 56import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; 57import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; 58import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; 59import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; 60import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; 61import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 62import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; 63import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; 64import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL; 65import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 66import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; 67import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; 68import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; 69import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; 70import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; 71import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 72import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY; 73import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; 74import static android.view.WindowManager.LayoutParams.TYPE_DRAG; 75import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 76import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER; 77import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 78import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 79import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; 80import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY; 81import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 82import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; 83import static android.view.WindowManager.LayoutParams.TYPE_PHONE; 84import static android.view.WindowManager.LayoutParams.TYPE_POINTER; 85import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; 86import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; 87import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; 88import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; 89import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT; 90import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR; 91import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; 92import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 93import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; 94import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; 95import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; 96import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 97import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 98import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; 99import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 100import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; 101import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING; 102import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; 103import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 104import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN; 105import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION; 106import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED; 107import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT; 108import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED; 109import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; 110import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; 111import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN; 112 113import android.annotation.Nullable; 114import android.app.ActivityManager; 115import android.app.ActivityManager.StackId; 116import android.app.ActivityManagerInternal; 117import android.app.ActivityManagerInternal.SleepToken; 118import android.app.AppOpsManager; 119import android.app.IUiModeManager; 120import android.app.ProgressDialog; 121import android.app.SearchManager; 122import android.app.StatusBarManager; 123import android.app.UiModeManager; 124import android.content.ActivityNotFoundException; 125import android.content.BroadcastReceiver; 126import android.content.ComponentName; 127import android.content.ContentResolver; 128import android.content.Context; 129import android.content.Intent; 130import android.content.IntentFilter; 131import android.content.ServiceConnection; 132import android.content.pm.ActivityInfo; 133import android.content.pm.ApplicationInfo; 134import android.content.pm.PackageManager; 135import android.content.pm.ResolveInfo; 136import android.content.res.CompatibilityInfo; 137import android.content.res.Configuration; 138import android.content.res.Resources; 139import android.content.res.TypedArray; 140import android.database.ContentObserver; 141import android.graphics.PixelFormat; 142import android.graphics.Rect; 143import android.hardware.hdmi.HdmiControlManager; 144import android.hardware.hdmi.HdmiPlaybackClient; 145import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback; 146import android.hardware.input.InputManagerInternal; 147import android.hardware.power.V1_0.PowerHint; 148import android.media.AudioAttributes; 149import android.media.AudioManager; 150import android.media.AudioSystem; 151import android.media.IAudioService; 152import android.media.Ringtone; 153import android.media.RingtoneManager; 154import android.media.session.MediaSessionLegacyHelper; 155import android.os.Binder; 156import android.os.Build; 157import android.os.Bundle; 158import android.os.Debug; 159import android.os.FactoryTest; 160import android.os.Handler; 161import android.os.IBinder; 162import android.os.IDeviceIdleController; 163import android.os.Looper; 164import android.os.Message; 165import android.os.Messenger; 166import android.os.PowerManager; 167import android.os.PowerManagerInternal; 168import android.os.Process; 169import android.os.RemoteException; 170import android.os.ServiceManager; 171import android.os.SystemClock; 172import android.os.SystemProperties; 173import android.os.UEventObserver; 174import android.os.UserHandle; 175import android.os.Vibrator; 176import android.provider.MediaStore; 177import android.provider.Settings; 178import android.service.dreams.DreamManagerInternal; 179import android.service.dreams.DreamService; 180import android.service.dreams.IDreamManager; 181import android.speech.RecognizerIntent; 182import android.telecom.TelecomManager; 183import android.util.DisplayMetrics; 184import android.util.EventLog; 185import android.util.Log; 186import android.util.LongSparseArray; 187import android.util.MutableBoolean; 188import android.util.Slog; 189import android.util.SparseArray; 190import android.view.Display; 191import android.view.Gravity; 192import android.view.HapticFeedbackConstants; 193import android.view.IApplicationToken; 194import android.view.IWindowManager; 195import android.view.InputChannel; 196import android.view.InputDevice; 197import android.view.InputEvent; 198import android.view.InputEventReceiver; 199import android.view.KeyCharacterMap; 200import android.view.KeyCharacterMap.FallbackAction; 201import android.view.KeyEvent; 202import android.view.MotionEvent; 203import android.view.Surface; 204import android.view.View; 205import android.view.ViewConfiguration; 206import android.view.WindowManager; 207import android.view.WindowManager.LayoutParams; 208import android.view.WindowManagerGlobal; 209import android.view.WindowManagerInternal; 210import android.view.WindowManagerInternal.AppTransitionListener; 211import android.view.WindowManagerPolicy; 212import android.view.accessibility.AccessibilityEvent; 213import android.view.accessibility.AccessibilityManager; 214import android.view.animation.Animation; 215import android.view.animation.AnimationSet; 216import android.view.animation.AnimationUtils; 217 218import com.android.internal.R; 219import com.android.internal.logging.MetricsLogger; 220import com.android.internal.policy.IKeyguardDismissCallback; 221import com.android.internal.policy.IShortcutService; 222import com.android.internal.policy.PhoneWindow; 223import com.android.internal.statusbar.IStatusBarService; 224import com.android.internal.util.ScreenShapeHelper; 225import com.android.internal.widget.PointerLocationView; 226import com.android.server.GestureLauncherService; 227import com.android.server.LocalServices; 228import com.android.server.policy.keyguard.KeyguardServiceDelegate; 229import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener; 230import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback; 231import com.android.server.statusbar.StatusBarManagerInternal; 232import com.android.server.wm.AppTransition; 233import com.android.server.vr.VrManagerInternal; 234 235import java.io.File; 236import java.io.FileReader; 237import java.io.IOException; 238import java.io.PrintWriter; 239import java.util.List; 240 241/** 242 * WindowManagerPolicy implementation for the Android phone UI. This 243 * introduces a new method suffix, Lp, for an internal lock of the 244 * PhoneWindowManager. This is used to protect some internal state, and 245 * can be acquired with either the Lw and Li lock held, so has the restrictions 246 * of both of those when held. 247 */ 248public class PhoneWindowManager implements WindowManagerPolicy { 249 static final String TAG = "WindowManager"; 250 static final boolean DEBUG = false; 251 static final boolean localLOGV = false; 252 static final boolean DEBUG_INPUT = false; 253 static final boolean DEBUG_KEYGUARD = false; 254 static final boolean DEBUG_LAYOUT = false; 255 static final boolean DEBUG_SPLASH_SCREEN = false; 256 static final boolean DEBUG_WAKEUP = false; 257 static final boolean SHOW_SPLASH_SCREENS = true; 258 259 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. 260 // No longer recommended for desk docks; 261 static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false; 262 263 static final boolean ALTERNATE_CAR_MODE_NAV_SIZE = false; 264 265 static final int SHORT_PRESS_POWER_NOTHING = 0; 266 static final int SHORT_PRESS_POWER_GO_TO_SLEEP = 1; 267 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP = 2; 268 static final int SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME = 3; 269 static final int SHORT_PRESS_POWER_GO_HOME = 4; 270 271 static final int LONG_PRESS_POWER_NOTHING = 0; 272 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; 273 static final int LONG_PRESS_POWER_SHUT_OFF = 2; 274 static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3; 275 276 static final int LONG_PRESS_BACK_NOTHING = 0; 277 static final int LONG_PRESS_BACK_GO_TO_VOICE_ASSIST = 1; 278 279 static final int MULTI_PRESS_POWER_NOTHING = 0; 280 static final int MULTI_PRESS_POWER_THEATER_MODE = 1; 281 static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2; 282 283 // Number of presses needed before we induce panic press behavior on the back button 284 static final int PANIC_PRESS_BACK_COUNT = 4; 285 static final int PANIC_PRESS_BACK_NOTHING = 0; 286 static final int PANIC_PRESS_BACK_HOME = 1; 287 288 // These need to match the documentation/constant in 289 // core/res/res/values/config.xml 290 static final int LONG_PRESS_HOME_NOTHING = 0; 291 static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 1; 292 static final int LONG_PRESS_HOME_ASSIST = 2; 293 static final int LAST_LONG_PRESS_HOME_BEHAVIOR = LONG_PRESS_HOME_ASSIST; 294 295 static final int DOUBLE_TAP_HOME_NOTHING = 0; 296 static final int DOUBLE_TAP_HOME_RECENT_SYSTEM_UI = 1; 297 298 static final int SHORT_PRESS_WINDOW_NOTHING = 0; 299 static final int SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE = 1; 300 301 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0; 302 static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1; 303 304 static final int PENDING_KEY_NULL = -1; 305 306 // Controls navigation bar opacity depending on which workspace stacks are currently 307 // visible. 308 // Nav bar is always opaque when either the freeform stack or docked stack is visible. 309 static final int NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED = 0; 310 // Nav bar is always translucent when the freeform stack is visible, otherwise always opaque. 311 static final int NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE = 1; 312 313 static final int APPLICATION_MEDIA_SUBLAYER = -2; 314 static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1; 315 static final int APPLICATION_PANEL_SUBLAYER = 1; 316 static final int APPLICATION_SUB_PANEL_SUBLAYER = 2; 317 static final int APPLICATION_ABOVE_SUB_PANEL_SUBLAYER = 3; 318 319 static public final String SYSTEM_DIALOG_REASON_KEY = "reason"; 320 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions"; 321 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; 322 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; 323 static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist"; 324 325 /** 326 * These are the system UI flags that, when changing, can cause the layout 327 * of the screen to change. 328 */ 329 static final int SYSTEM_UI_CHANGING_LAYOUT = 330 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 331 | View.SYSTEM_UI_FLAG_FULLSCREEN 332 | View.STATUS_BAR_TRANSLUCENT 333 | View.NAVIGATION_BAR_TRANSLUCENT 334 | View.STATUS_BAR_TRANSPARENT 335 | View.NAVIGATION_BAR_TRANSPARENT; 336 337 private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder() 338 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 339 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) 340 .build(); 341 342 // The panic gesture may become active only after the keyguard is dismissed and the immersive 343 // app shows again. If that doesn't happen for 30s we drop the gesture. 344 private static final long PANIC_GESTURE_EXPIRATION = 30000; 345 346 private static final String SYSUI_PACKAGE = "com.android.systemui"; 347 private static final String SYSUI_SCREENSHOT_SERVICE = 348 "com.android.systemui.screenshot.TakeScreenshotService"; 349 private static final String SYSUI_SCREENSHOT_ERROR_RECEIVER = 350 "com.android.systemui.screenshot.ScreenshotServiceErrorReceiver"; 351 352 private static final int NAV_BAR_BOTTOM = 0; 353 private static final int NAV_BAR_RIGHT = 1; 354 private static final int NAV_BAR_LEFT = 2; 355 356 /** 357 * Keyguard stuff 358 */ 359 private boolean mKeyguardDrawnOnce; 360 361 /* Table of Application Launch keys. Maps from key codes to intent categories. 362 * 363 * These are special keys that are used to launch particular kinds of applications, 364 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C) 365 * usage page. We don't support quite that many yet... 366 */ 367 static SparseArray<String> sApplicationLaunchKeyCategories; 368 static { 369 sApplicationLaunchKeyCategories = new SparseArray<String>(); 370 sApplicationLaunchKeyCategories.append( 371 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER); 372 sApplicationLaunchKeyCategories.append( 373 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL); 374 sApplicationLaunchKeyCategories.append( 375 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS); 376 sApplicationLaunchKeyCategories.append( 377 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR); 378 sApplicationLaunchKeyCategories.append( 379 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC); 380 sApplicationLaunchKeyCategories.append( 381 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR); 382 } 383 384 /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */ 385 static final int WAITING_FOR_DRAWN_TIMEOUT = 1000; 386 387 /** Amount of time (in milliseconds) a toast window can be shown. */ 388 public static final int TOAST_WINDOW_TIMEOUT = 3500; // 3.5 seconds 389 390 /** 391 * Lock protecting internal state. Must not call out into window 392 * manager with lock held. (This lock will be acquired in places 393 * where the window manager is calling in with its own lock held.) 394 */ 395 private final Object mLock = new Object(); 396 397 Context mContext; 398 IWindowManager mWindowManager; 399 WindowManagerFuncs mWindowManagerFuncs; 400 WindowManagerInternal mWindowManagerInternal; 401 PowerManager mPowerManager; 402 ActivityManagerInternal mActivityManagerInternal; 403 InputManagerInternal mInputManagerInternal; 404 DreamManagerInternal mDreamManagerInternal; 405 PowerManagerInternal mPowerManagerInternal; 406 IStatusBarService mStatusBarService; 407 StatusBarManagerInternal mStatusBarManagerInternal; 408 boolean mPreloadedRecentApps; 409 final Object mServiceAquireLock = new Object(); 410 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes 411 SearchManager mSearchManager; 412 AccessibilityManager mAccessibilityManager; 413 BurnInProtectionHelper mBurnInProtectionHelper; 414 AppOpsManager mAppOpsManager; 415 private boolean mHasFeatureWatch; 416 417 // Vibrator pattern for haptic feedback of a long press. 418 long[] mLongPressVibePattern; 419 420 // Vibrator pattern for haptic feedback of virtual key press. 421 long[] mVirtualKeyVibePattern; 422 423 // Vibrator pattern for a short vibration. 424 long[] mKeyboardTapVibePattern; 425 426 // Vibrator pattern for a short vibration when tapping on an hour/minute tick of a Clock. 427 long[] mClockTickVibePattern; 428 429 // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar. 430 long[] mCalendarDateVibePattern; 431 432 // Vibrator pattern for haptic feedback during boot when safe mode is disabled. 433 long[] mSafeModeDisabledVibePattern; 434 435 // Vibrator pattern for haptic feedback during boot when safe mode is enabled. 436 long[] mSafeModeEnabledVibePattern; 437 438 // Vibrator pattern for haptic feedback of a context click. 439 long[] mContextClickVibePattern; 440 441 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */ 442 boolean mEnableShiftMenuBugReports = false; 443 444 boolean mSafeMode; 445 WindowState mStatusBar = null; 446 int mStatusBarHeight; 447 WindowState mNavigationBar = null; 448 boolean mHasNavigationBar = false; 449 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side? 450 int mNavigationBarPosition = NAV_BAR_BOTTOM; 451 int[] mNavigationBarHeightForRotationDefault = new int[4]; 452 int[] mNavigationBarWidthForRotationDefault = new int[4]; 453 int[] mNavigationBarHeightForRotationInCarMode = new int[4]; 454 int[] mNavigationBarWidthForRotationInCarMode = new int[4]; 455 456 private LongSparseArray<IShortcutService> mShortcutKeyServices = new LongSparseArray<>(); 457 458 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. 459 // This is for car dock and this is updated from resource. 460 private boolean mEnableCarDockHomeCapture = true; 461 462 boolean mBootMessageNeedsHiding; 463 KeyguardServiceDelegate mKeyguardDelegate; 464 final Runnable mWindowManagerDrawCallback = new Runnable() { 465 @Override 466 public void run() { 467 if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!"); 468 mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE); 469 } 470 }; 471 final DrawnListener mKeyguardDrawnCallback = new DrawnListener() { 472 @Override 473 public void onDrawn() { 474 if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onDrawn."); 475 mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE); 476 } 477 }; 478 479 GlobalActions mGlobalActions; 480 Handler mHandler; 481 WindowState mLastInputMethodWindow = null; 482 WindowState mLastInputMethodTargetWindow = null; 483 484 // FIXME This state is shared between the input reader and handler thread. 485 // Technically it's broken and buggy but it has been like this for many years 486 // and we have not yet seen any problems. Someday we'll rewrite this logic 487 // so that only one thread is involved in handling input policy. Unfortunately 488 // it's on a critical path for power management so we can't just post the work to the 489 // handler thread. We'll need to resolve this someday by teaching the input dispatcher 490 // to hold wakelocks during dispatch and eliminating the critical path. 491 volatile boolean mPowerKeyHandled; 492 volatile boolean mBackKeyHandled; 493 volatile boolean mBeganFromNonInteractive; 494 volatile int mPowerKeyPressCounter; 495 volatile int mBackKeyPressCounter; 496 volatile boolean mEndCallKeyHandled; 497 volatile boolean mCameraGestureTriggeredDuringGoingToSleep; 498 volatile boolean mGoingToSleep; 499 volatile boolean mRecentsVisible; 500 volatile boolean mTvPictureInPictureVisible; 501 502 // Used to hold the last user key used to wake the device. This helps us prevent up events 503 // from being passed to the foregrounded app without a corresponding down event 504 volatile int mPendingWakeKey = PENDING_KEY_NULL; 505 506 int mRecentAppsHeldModifiers; 507 boolean mLanguageSwitchKeyPressed; 508 509 int mLidState = LID_ABSENT; 510 int mCameraLensCoverState = CAMERA_LENS_COVER_ABSENT; 511 boolean mHaveBuiltInKeyboard; 512 513 boolean mSystemReady; 514 boolean mSystemBooted; 515 private boolean mDeferBindKeyguard; 516 boolean mHdmiPlugged; 517 HdmiControl mHdmiControl; 518 IUiModeManager mUiModeManager; 519 int mUiMode; 520 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED; 521 int mLidOpenRotation; 522 int mCarDockRotation; 523 int mDeskDockRotation; 524 int mUndockedHdmiRotation; 525 int mDemoHdmiRotation; 526 boolean mDemoHdmiRotationLock; 527 int mDemoRotation; 528 boolean mDemoRotationLock; 529 530 boolean mWakeGestureEnabledSetting; 531 MyWakeGestureListener mWakeGestureListener; 532 533 // Default display does not rotate, apps that require non-default orientation will have to 534 // have the orientation emulated. 535 private boolean mForceDefaultOrientation = false; 536 537 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE; 538 int mUserRotation = Surface.ROTATION_0; 539 boolean mAccelerometerDefault; 540 541 boolean mSupportAutoRotation; 542 int mAllowAllRotations = -1; 543 boolean mCarDockEnablesAccelerometer; 544 boolean mDeskDockEnablesAccelerometer; 545 int mLidKeyboardAccessibility; 546 int mLidNavigationAccessibility; 547 boolean mLidControlsScreenLock; 548 boolean mLidControlsSleep; 549 int mShortPressOnPowerBehavior; 550 int mLongPressOnPowerBehavior; 551 int mDoublePressOnPowerBehavior; 552 int mTriplePressOnPowerBehavior; 553 int mLongPressOnBackBehavior; 554 int mPanicPressOnBackBehavior; 555 int mShortPressOnSleepBehavior; 556 int mShortPressWindowBehavior; 557 boolean mAwake; 558 boolean mScreenOnEarly; 559 boolean mScreenOnFully; 560 ScreenOnListener mScreenOnListener; 561 boolean mKeyguardDrawComplete; 562 boolean mWindowManagerDrawComplete; 563 boolean mOrientationSensorEnabled = false; 564 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 565 boolean mHasSoftInput = false; 566 boolean mTranslucentDecorEnabled = true; 567 boolean mUseTvRouting; 568 569 int mPointerLocationMode = 0; // guarded by mLock 570 571 // The last window we were told about in focusChanged. 572 WindowState mFocusedWindow; 573 IApplicationToken mFocusedApp; 574 575 PointerLocationView mPointerLocationView; 576 577 // The current size of the screen; really; extends into the overscan area of 578 // the screen and doesn't account for any system elements like the status bar. 579 int mOverscanScreenLeft, mOverscanScreenTop; 580 int mOverscanScreenWidth, mOverscanScreenHeight; 581 // The current visible size of the screen; really; (ir)regardless of whether the status 582 // bar can be hidden but not extending into the overscan area. 583 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop; 584 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight; 585 // Like mOverscanScreen*, but allowed to move into the overscan region where appropriate. 586 int mRestrictedOverscanScreenLeft, mRestrictedOverscanScreenTop; 587 int mRestrictedOverscanScreenWidth, mRestrictedOverscanScreenHeight; 588 // The current size of the screen; these may be different than (0,0)-(dw,dh) 589 // if the status bar can't be hidden; in that case it effectively carves out 590 // that area of the display from all other windows. 591 int mRestrictedScreenLeft, mRestrictedScreenTop; 592 int mRestrictedScreenWidth, mRestrictedScreenHeight; 593 // During layout, the current screen borders accounting for any currently 594 // visible system UI elements. 595 int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom; 596 // For applications requesting stable content insets, these are them. 597 int mStableLeft, mStableTop, mStableRight, mStableBottom; 598 // For applications requesting stable content insets but have also set the 599 // fullscreen window flag, these are the stable dimensions without the status bar. 600 int mStableFullscreenLeft, mStableFullscreenTop; 601 int mStableFullscreenRight, mStableFullscreenBottom; 602 // During layout, the current screen borders with all outer decoration 603 // (status bar, input method dock) accounted for. 604 int mCurLeft, mCurTop, mCurRight, mCurBottom; 605 // During layout, the frame in which content should be displayed 606 // to the user, accounting for all screen decoration except for any 607 // space they deem as available for other content. This is usually 608 // the same as mCur*, but may be larger if the screen decor has supplied 609 // content insets. 610 int mContentLeft, mContentTop, mContentRight, mContentBottom; 611 // During layout, the frame in which voice content should be displayed 612 // to the user, accounting for all screen decoration except for any 613 // space they deem as available for other content. 614 int mVoiceContentLeft, mVoiceContentTop, mVoiceContentRight, mVoiceContentBottom; 615 // During layout, the current screen borders along which input method 616 // windows are placed. 617 int mDockLeft, mDockTop, mDockRight, mDockBottom; 618 // During layout, the layer at which the doc window is placed. 619 int mDockLayer; 620 // During layout, this is the layer of the status bar. 621 int mStatusBarLayer; 622 int mLastSystemUiFlags; 623 // Bits that we are in the process of clearing, so we want to prevent 624 // them from being set by applications until everything has been updated 625 // to have them clear. 626 int mResettingSystemUiFlags = 0; 627 // Bits that we are currently always keeping cleared. 628 int mForceClearedSystemUiFlags = 0; 629 int mLastFullscreenStackSysUiFlags; 630 int mLastDockedStackSysUiFlags; 631 final Rect mNonDockedStackBounds = new Rect(); 632 final Rect mDockedStackBounds = new Rect(); 633 final Rect mLastNonDockedStackBounds = new Rect(); 634 final Rect mLastDockedStackBounds = new Rect(); 635 636 // What we last reported to system UI about whether the compatibility 637 // menu needs to be displayed. 638 boolean mLastFocusNeedsMenu = false; 639 // If nonzero, a panic gesture was performed at that time in uptime millis and is still pending. 640 private long mPendingPanicGestureUptime; 641 642 InputConsumer mInputConsumer = null; 643 644 static final Rect mTmpParentFrame = new Rect(); 645 static final Rect mTmpDisplayFrame = new Rect(); 646 static final Rect mTmpOverscanFrame = new Rect(); 647 static final Rect mTmpContentFrame = new Rect(); 648 static final Rect mTmpVisibleFrame = new Rect(); 649 static final Rect mTmpDecorFrame = new Rect(); 650 static final Rect mTmpStableFrame = new Rect(); 651 static final Rect mTmpNavigationFrame = new Rect(); 652 static final Rect mTmpOutsetFrame = new Rect(); 653 private static final Rect mTmpRect = new Rect(); 654 655 WindowState mTopFullscreenOpaqueWindowState; 656 WindowState mTopFullscreenOpaqueOrDimmingWindowState; 657 WindowState mTopDockedOpaqueWindowState; 658 WindowState mTopDockedOpaqueOrDimmingWindowState; 659 boolean mTopIsFullscreen; 660 boolean mForceStatusBar; 661 boolean mForceStatusBarFromKeyguard; 662 private boolean mForceStatusBarTransparent; 663 int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED; 664 boolean mForcingShowNavBar; 665 int mForcingShowNavBarLayer; 666 667 private boolean mPendingKeyguardOccluded; 668 private boolean mKeyguardOccludedChanged; 669 670 boolean mShowingDream; 671 private boolean mLastShowingDream; 672 boolean mDreamingLockscreen; 673 boolean mDreamingSleepTokenNeeded; 674 SleepToken mDreamingSleepToken; 675 SleepToken mScreenOffSleepToken; 676 volatile boolean mKeyguardOccluded; 677 boolean mHomePressed; 678 boolean mHomeConsumed; 679 boolean mHomeDoubleTapPending; 680 Intent mHomeIntent; 681 Intent mCarDockIntent; 682 Intent mDeskDockIntent; 683 boolean mSearchKeyShortcutPending; 684 boolean mConsumeSearchKeyUp; 685 boolean mAssistKeyLongPressed; 686 boolean mPendingMetaAction; 687 boolean mPendingCapsLockToggle; 688 int mMetaState; 689 int mInitialMetaState; 690 boolean mForceShowSystemBars; 691 692 // support for activating the lock screen while the screen is on 693 boolean mAllowLockscreenWhenOn; 694 int mLockScreenTimeout; 695 boolean mLockScreenTimerActive; 696 697 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.) 698 int mEndcallBehavior; 699 700 // Behavior of POWER button while in-call and screen on. 701 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.) 702 int mIncallPowerBehavior; 703 704 // Behavior of Back button while in-call and screen on 705 int mIncallBackBehavior; 706 707 Display mDisplay; 708 709 private int mDisplayRotation; 710 711 int mLandscapeRotation = 0; // default landscape rotation 712 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation 713 int mPortraitRotation = 0; // default portrait rotation 714 int mUpsideDownRotation = 0; // "other" portrait rotation 715 716 int mOverscanLeft = 0; 717 int mOverscanTop = 0; 718 int mOverscanRight = 0; 719 int mOverscanBottom = 0; 720 721 // What we do when the user long presses on home 722 private int mLongPressOnHomeBehavior; 723 724 // What we do when the user double-taps on home 725 private int mDoubleTapOnHomeBehavior; 726 727 // Allowed theater mode wake actions 728 private boolean mAllowTheaterModeWakeFromKey; 729 private boolean mAllowTheaterModeWakeFromPowerKey; 730 private boolean mAllowTheaterModeWakeFromMotion; 731 private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming; 732 private boolean mAllowTheaterModeWakeFromCameraLens; 733 private boolean mAllowTheaterModeWakeFromLidSwitch; 734 private boolean mAllowTheaterModeWakeFromWakeGesture; 735 736 // Whether to support long press from power button in non-interactive mode 737 private boolean mSupportLongPressPowerWhenNonInteractive; 738 739 // Whether to go to sleep entering theater mode from power button 740 private boolean mGoToSleepOnButtonPressTheaterMode; 741 742 // Screenshot trigger states 743 // Time to volume and power must be pressed within this interval of each other. 744 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150; 745 // Increase the chord delay when taking a screenshot from the keyguard 746 private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f; 747 private boolean mScreenshotChordEnabled; 748 private boolean mScreenshotChordVolumeDownKeyTriggered; 749 private long mScreenshotChordVolumeDownKeyTime; 750 private boolean mScreenshotChordVolumeDownKeyConsumed; 751 private boolean mScreenshotChordVolumeUpKeyTriggered; 752 private boolean mScreenshotChordPowerKeyTriggered; 753 private long mScreenshotChordPowerKeyTime; 754 755 /* The number of steps between min and max brightness */ 756 private static final int BRIGHTNESS_STEPS = 10; 757 758 SettingsObserver mSettingsObserver; 759 ShortcutManager mShortcutManager; 760 PowerManager.WakeLock mBroadcastWakeLock; 761 PowerManager.WakeLock mPowerKeyWakeLock; 762 boolean mHavePendingMediaKeyRepeatWithWakeLock; 763 764 private int mCurrentUserId; 765 766 // Maps global key codes to the components that will handle them. 767 private GlobalKeyManager mGlobalKeyManager; 768 769 // Fallback actions by key code. 770 private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions = 771 new SparseArray<KeyCharacterMap.FallbackAction>(); 772 773 private final LogDecelerateInterpolator mLogDecelerateInterpolator 774 = new LogDecelerateInterpolator(100, 0); 775 776 private final MutableBoolean mTmpBoolean = new MutableBoolean(false); 777 778 private static final int MSG_ENABLE_POINTER_LOCATION = 1; 779 private static final int MSG_DISABLE_POINTER_LOCATION = 2; 780 private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; 781 private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4; 782 private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5; 783 private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6; 784 private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7; 785 private static final int MSG_DISPATCH_SHOW_RECENTS = 9; 786 private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10; 787 private static final int MSG_HIDE_BOOT_MESSAGE = 11; 788 private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12; 789 private static final int MSG_POWER_DELAYED_PRESS = 13; 790 private static final int MSG_POWER_LONG_PRESS = 14; 791 private static final int MSG_UPDATE_DREAMING_SLEEP_TOKEN = 15; 792 private static final int MSG_REQUEST_TRANSIENT_BARS = 16; 793 private static final int MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU = 17; 794 private static final int MSG_BACK_LONG_PRESS = 18; 795 private static final int MSG_DISPOSE_INPUT_CONSUMER = 19; 796 private static final int MSG_BACK_DELAYED_PRESS = 20; 797 798 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0; 799 private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1; 800 801 private class PolicyHandler extends Handler { 802 @Override 803 public void handleMessage(Message msg) { 804 switch (msg.what) { 805 case MSG_ENABLE_POINTER_LOCATION: 806 enablePointerLocation(); 807 break; 808 case MSG_DISABLE_POINTER_LOCATION: 809 disablePointerLocation(); 810 break; 811 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK: 812 dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj); 813 break; 814 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK: 815 dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj); 816 break; 817 case MSG_DISPATCH_SHOW_RECENTS: 818 showRecentApps(false, msg.arg1 != 0); 819 break; 820 case MSG_DISPATCH_SHOW_GLOBAL_ACTIONS: 821 showGlobalActionsInternal(); 822 break; 823 case MSG_KEYGUARD_DRAWN_COMPLETE: 824 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete"); 825 finishKeyguardDrawn(); 826 break; 827 case MSG_KEYGUARD_DRAWN_TIMEOUT: 828 Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete"); 829 finishKeyguardDrawn(); 830 break; 831 case MSG_WINDOW_MANAGER_DRAWN_COMPLETE: 832 if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete"); 833 finishWindowsDrawn(); 834 break; 835 case MSG_HIDE_BOOT_MESSAGE: 836 handleHideBootMessage(); 837 break; 838 case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK: 839 launchVoiceAssistWithWakeLock(msg.arg1 != 0); 840 break; 841 case MSG_POWER_DELAYED_PRESS: 842 powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2); 843 finishPowerKeyPress(); 844 break; 845 case MSG_POWER_LONG_PRESS: 846 powerLongPress(); 847 break; 848 case MSG_UPDATE_DREAMING_SLEEP_TOKEN: 849 updateDreamingSleepToken(msg.arg1 != 0); 850 break; 851 case MSG_REQUEST_TRANSIENT_BARS: 852 WindowState targetBar = (msg.arg1 == MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS) ? 853 mStatusBar : mNavigationBar; 854 if (targetBar != null) { 855 requestTransientBars(targetBar); 856 } 857 break; 858 case MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU: 859 showTvPictureInPictureMenuInternal(); 860 break; 861 case MSG_BACK_LONG_PRESS: 862 backLongPress(); 863 finishBackKeyPress(); 864 break; 865 case MSG_DISPOSE_INPUT_CONSUMER: 866 disposeInputConsumer((InputConsumer) msg.obj); 867 break; 868 case MSG_BACK_DELAYED_PRESS: 869 backMultiPressAction((Long) msg.obj, msg.arg1); 870 finishBackKeyPress(); 871 break; 872 } 873 } 874 } 875 876 private UEventObserver mHDMIObserver = new UEventObserver() { 877 @Override 878 public void onUEvent(UEventObserver.UEvent event) { 879 setHdmiPlugged("1".equals(event.get("SWITCH_STATE"))); 880 } 881 }; 882 883 class SettingsObserver extends ContentObserver { 884 SettingsObserver(Handler handler) { 885 super(handler); 886 } 887 888 void observe() { 889 // Observe all users' changes 890 ContentResolver resolver = mContext.getContentResolver(); 891 resolver.registerContentObserver(Settings.System.getUriFor( 892 Settings.System.END_BUTTON_BEHAVIOR), false, this, 893 UserHandle.USER_ALL); 894 resolver.registerContentObserver(Settings.Secure.getUriFor( 895 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this, 896 UserHandle.USER_ALL); 897 resolver.registerContentObserver(Settings.Secure.getUriFor( 898 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR), false, this, 899 UserHandle.USER_ALL); 900 resolver.registerContentObserver(Settings.Secure.getUriFor( 901 Settings.Secure.WAKE_GESTURE_ENABLED), false, this, 902 UserHandle.USER_ALL); 903 resolver.registerContentObserver(Settings.System.getUriFor( 904 Settings.System.ACCELEROMETER_ROTATION), false, this, 905 UserHandle.USER_ALL); 906 resolver.registerContentObserver(Settings.System.getUriFor( 907 Settings.System.USER_ROTATION), false, this, 908 UserHandle.USER_ALL); 909 resolver.registerContentObserver(Settings.System.getUriFor( 910 Settings.System.SCREEN_OFF_TIMEOUT), false, this, 911 UserHandle.USER_ALL); 912 resolver.registerContentObserver(Settings.System.getUriFor( 913 Settings.System.POINTER_LOCATION), false, this, 914 UserHandle.USER_ALL); 915 resolver.registerContentObserver(Settings.Secure.getUriFor( 916 Settings.Secure.DEFAULT_INPUT_METHOD), false, this, 917 UserHandle.USER_ALL); 918 resolver.registerContentObserver(Settings.Secure.getUriFor( 919 Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this, 920 UserHandle.USER_ALL); 921 resolver.registerContentObserver(Settings.Global.getUriFor( 922 Settings.Global.POLICY_CONTROL), false, this, 923 UserHandle.USER_ALL); 924 updateSettings(); 925 } 926 927 @Override public void onChange(boolean selfChange) { 928 updateSettings(); 929 updateRotation(false); 930 } 931 } 932 933 class MyWakeGestureListener extends WakeGestureListener { 934 MyWakeGestureListener(Context context, Handler handler) { 935 super(context, handler); 936 } 937 938 @Override 939 public void onWakeUp() { 940 synchronized (mLock) { 941 if (shouldEnableWakeGestureLp()) { 942 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 943 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture, 944 "android.policy:GESTURE"); 945 } 946 } 947 } 948 } 949 950 class MyOrientationListener extends WindowOrientationListener { 951 private final Runnable mUpdateRotationRunnable = new Runnable() { 952 @Override 953 public void run() { 954 // send interaction hint to improve redraw performance 955 mPowerManagerInternal.powerHint(PowerHint.INTERACTION, 0); 956 updateRotation(false); 957 } 958 }; 959 960 MyOrientationListener(Context context, Handler handler) { 961 super(context, handler); 962 } 963 964 @Override 965 public void onProposedRotationChanged(int rotation) { 966 if (localLOGV) Slog.v(TAG, "onProposedRotationChanged, rotation=" + rotation); 967 mHandler.post(mUpdateRotationRunnable); 968 } 969 } 970 MyOrientationListener mOrientationListener; 971 972 private final StatusBarController mStatusBarController = new StatusBarController(); 973 974 private final BarController mNavigationBarController = new BarController("NavigationBar", 975 View.NAVIGATION_BAR_TRANSIENT, 976 View.NAVIGATION_BAR_UNHIDE, 977 View.NAVIGATION_BAR_TRANSLUCENT, 978 StatusBarManager.WINDOW_NAVIGATION_BAR, 979 WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, 980 View.NAVIGATION_BAR_TRANSPARENT); 981 982 private ImmersiveModeConfirmation mImmersiveModeConfirmation; 983 984 private SystemGesturesPointerEventListener mSystemGestures; 985 986 IStatusBarService getStatusBarService() { 987 synchronized (mServiceAquireLock) { 988 if (mStatusBarService == null) { 989 mStatusBarService = IStatusBarService.Stub.asInterface( 990 ServiceManager.getService("statusbar")); 991 } 992 return mStatusBarService; 993 } 994 } 995 996 StatusBarManagerInternal getStatusBarManagerInternal() { 997 synchronized (mServiceAquireLock) { 998 if (mStatusBarManagerInternal == null) { 999 mStatusBarManagerInternal = 1000 LocalServices.getService(StatusBarManagerInternal.class); 1001 } 1002 return mStatusBarManagerInternal; 1003 } 1004 } 1005 1006 /* 1007 * We always let the sensor be switched on by default except when 1008 * the user has explicitly disabled sensor based rotation or when the 1009 * screen is switched off. 1010 */ 1011 boolean needSensorRunningLp() { 1012 if (mSupportAutoRotation) { 1013 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 1014 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 1015 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT 1016 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) { 1017 // If the application has explicitly requested to follow the 1018 // orientation, then we need to turn the sensor on. 1019 return true; 1020 } 1021 } 1022 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) || 1023 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 1024 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 1025 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) { 1026 // enable accelerometer if we are docked in a dock that enables accelerometer 1027 // orientation management, 1028 return true; 1029 } 1030 if (mUserRotationMode == USER_ROTATION_LOCKED) { 1031 // If the setting for using the sensor by default is enabled, then 1032 // we will always leave it on. Note that the user could go to 1033 // a window that forces an orientation that does not use the 1034 // sensor and in theory we could turn it off... however, when next 1035 // turning it on we won't have a good value for the current 1036 // orientation for a little bit, which can cause orientation 1037 // changes to lag, so we'd like to keep it always on. (It will 1038 // still be turned off when the screen is off.) 1039 return false; 1040 } 1041 return mSupportAutoRotation; 1042 } 1043 1044 /* 1045 * Various use cases for invoking this function 1046 * screen turning off, should always disable listeners if already enabled 1047 * screen turned on and current app has sensor based orientation, enable listeners 1048 * if not already enabled 1049 * screen turned on and current app does not have sensor orientation, disable listeners if 1050 * already enabled 1051 * screen turning on and current app has sensor based orientation, enable listeners if needed 1052 * screen turning on and current app has nosensor based orientation, do nothing 1053 */ 1054 void updateOrientationListenerLp() { 1055 if (!mOrientationListener.canDetectOrientation()) { 1056 // If sensor is turned off or nonexistent for some reason 1057 return; 1058 } 1059 // Could have been invoked due to screen turning on or off or 1060 // change of the currently visible window's orientation. 1061 if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly 1062 + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation 1063 + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled 1064 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 1065 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 1066 boolean disable = true; 1067 // Note: We postpone the rotating of the screen until the keyguard as well as the 1068 // window manager have reported a draw complete. 1069 if (mScreenOnEarly && mAwake && 1070 mKeyguardDrawComplete && mWindowManagerDrawComplete) { 1071 if (needSensorRunningLp()) { 1072 disable = false; 1073 //enable listener if not already enabled 1074 if (!mOrientationSensorEnabled) { 1075 mOrientationListener.enable(); 1076 if(localLOGV) Slog.v(TAG, "Enabling listeners"); 1077 mOrientationSensorEnabled = true; 1078 } 1079 } 1080 } 1081 //check if sensors need to be disabled 1082 if (disable && mOrientationSensorEnabled) { 1083 mOrientationListener.disable(); 1084 if(localLOGV) Slog.v(TAG, "Disabling listeners"); 1085 mOrientationSensorEnabled = false; 1086 } 1087 } 1088 1089 private void interceptBackKeyDown() { 1090 MetricsLogger.count(mContext, "key_back_down", 1); 1091 // Reset back key state for long press 1092 mBackKeyHandled = false; 1093 1094 // Cancel multi-press detection timeout. 1095 if (hasPanicPressOnBackBehavior()) { 1096 if (mBackKeyPressCounter != 0 1097 && mBackKeyPressCounter < PANIC_PRESS_BACK_COUNT) { 1098 mHandler.removeMessages(MSG_BACK_DELAYED_PRESS); 1099 } 1100 } 1101 1102 if (hasLongPressOnBackBehavior()) { 1103 Message msg = mHandler.obtainMessage(MSG_BACK_LONG_PRESS); 1104 msg.setAsynchronous(true); 1105 mHandler.sendMessageDelayed(msg, 1106 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1107 } 1108 } 1109 1110 // returns true if the key was handled and should not be passed to the user 1111 private boolean interceptBackKeyUp(KeyEvent event) { 1112 // Cache handled state 1113 boolean handled = mBackKeyHandled; 1114 1115 if (hasPanicPressOnBackBehavior()) { 1116 // Check for back key panic press 1117 ++mBackKeyPressCounter; 1118 1119 final long eventTime = event.getDownTime(); 1120 1121 if (mBackKeyPressCounter <= PANIC_PRESS_BACK_COUNT) { 1122 // This could be a multi-press. Wait a little bit longer to confirm. 1123 Message msg = mHandler.obtainMessage(MSG_BACK_DELAYED_PRESS, 1124 mBackKeyPressCounter, 0, eventTime); 1125 msg.setAsynchronous(true); 1126 mHandler.sendMessageDelayed(msg, ViewConfiguration.getMultiPressTimeout()); 1127 } 1128 } 1129 1130 // Reset back long press state 1131 cancelPendingBackKeyAction(); 1132 1133 if (mHasFeatureWatch) { 1134 TelecomManager telecomManager = getTelecommService(); 1135 1136 if (telecomManager != null) { 1137 if (telecomManager.isRinging()) { 1138 // Pressing back while there's a ringing incoming 1139 // call should silence the ringer. 1140 telecomManager.silenceRinger(); 1141 1142 // It should not prevent navigating away 1143 return false; 1144 } else if ( 1145 (mIncallBackBehavior & Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_HANGUP) != 0 1146 && telecomManager.isInCall()) { 1147 // Otherwise, if "Back button ends call" is enabled, 1148 // the Back button will hang up any current active call. 1149 return telecomManager.endCall(); 1150 } 1151 } 1152 } 1153 1154 return handled; 1155 } 1156 1157 private void interceptPowerKeyDown(KeyEvent event, boolean interactive) { 1158 // Hold a wake lock until the power key is released. 1159 if (!mPowerKeyWakeLock.isHeld()) { 1160 mPowerKeyWakeLock.acquire(); 1161 } 1162 1163 // Cancel multi-press detection timeout. 1164 if (mPowerKeyPressCounter != 0) { 1165 mHandler.removeMessages(MSG_POWER_DELAYED_PRESS); 1166 } 1167 1168 // Detect user pressing the power button in panic when an application has 1169 // taken over the whole screen. 1170 boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive, 1171 SystemClock.elapsedRealtime(), isImmersiveMode(mLastSystemUiFlags), 1172 isNavBarEmpty(mLastSystemUiFlags)); 1173 if (panic) { 1174 mHandler.post(mHiddenNavPanic); 1175 } 1176 1177 // Latch power key state to detect screenshot chord. 1178 if (interactive && !mScreenshotChordPowerKeyTriggered 1179 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 1180 mScreenshotChordPowerKeyTriggered = true; 1181 mScreenshotChordPowerKeyTime = event.getDownTime(); 1182 interceptScreenshotChord(); 1183 } 1184 1185 // Stop ringing or end call if configured to do so when power is pressed. 1186 TelecomManager telecomManager = getTelecommService(); 1187 boolean hungUp = false; 1188 if (telecomManager != null) { 1189 if (telecomManager.isRinging()) { 1190 // Pressing Power while there's a ringing incoming 1191 // call should silence the ringer. 1192 telecomManager.silenceRinger(); 1193 } else if ((mIncallPowerBehavior 1194 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 1195 && telecomManager.isInCall() && interactive) { 1196 // Otherwise, if "Power button ends call" is enabled, 1197 // the Power button will hang up any current active call. 1198 hungUp = telecomManager.endCall(); 1199 } 1200 } 1201 1202 GestureLauncherService gestureService = LocalServices.getService( 1203 GestureLauncherService.class); 1204 boolean gesturedServiceIntercepted = false; 1205 if (gestureService != null) { 1206 gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive, 1207 mTmpBoolean); 1208 if (mTmpBoolean.value && mGoingToSleep) { 1209 mCameraGestureTriggeredDuringGoingToSleep = true; 1210 } 1211 } 1212 1213 // If the power key has still not yet been handled, then detect short 1214 // press, long press, or multi press and decide what to do. 1215 mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered 1216 || mScreenshotChordVolumeUpKeyTriggered || gesturedServiceIntercepted; 1217 if (!mPowerKeyHandled) { 1218 if (interactive) { 1219 // When interactive, we're already awake. 1220 // Wait for a long press or for the button to be released to decide what to do. 1221 if (hasLongPressOnPowerBehavior()) { 1222 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); 1223 msg.setAsynchronous(true); 1224 mHandler.sendMessageDelayed(msg, 1225 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1226 } 1227 } else { 1228 wakeUpFromPowerKey(event.getDownTime()); 1229 1230 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) { 1231 Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); 1232 msg.setAsynchronous(true); 1233 mHandler.sendMessageDelayed(msg, 1234 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1235 mBeganFromNonInteractive = true; 1236 } else { 1237 final int maxCount = getMaxMultiPressPowerCount(); 1238 1239 if (maxCount <= 1) { 1240 mPowerKeyHandled = true; 1241 } else { 1242 mBeganFromNonInteractive = true; 1243 } 1244 } 1245 } 1246 } 1247 } 1248 1249 private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) { 1250 final boolean handled = canceled || mPowerKeyHandled; 1251 mScreenshotChordPowerKeyTriggered = false; 1252 cancelPendingScreenshotChordAction(); 1253 cancelPendingPowerKeyAction(); 1254 1255 if (!handled) { 1256 // Figure out how to handle the key now that it has been released. 1257 mPowerKeyPressCounter += 1; 1258 1259 final int maxCount = getMaxMultiPressPowerCount(); 1260 final long eventTime = event.getDownTime(); 1261 if (mPowerKeyPressCounter < maxCount) { 1262 // This could be a multi-press. Wait a little bit longer to confirm. 1263 // Continue holding the wake lock. 1264 Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS, 1265 interactive ? 1 : 0, mPowerKeyPressCounter, eventTime); 1266 msg.setAsynchronous(true); 1267 mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout()); 1268 return; 1269 } 1270 1271 // No other actions. Handle it immediately. 1272 powerPress(eventTime, interactive, mPowerKeyPressCounter); 1273 } 1274 1275 // Done. Reset our state. 1276 finishPowerKeyPress(); 1277 } 1278 1279 private void finishPowerKeyPress() { 1280 mBeganFromNonInteractive = false; 1281 mPowerKeyPressCounter = 0; 1282 if (mPowerKeyWakeLock.isHeld()) { 1283 mPowerKeyWakeLock.release(); 1284 } 1285 } 1286 1287 private void finishBackKeyPress() { 1288 mBackKeyPressCounter = 0; 1289 } 1290 1291 private void cancelPendingPowerKeyAction() { 1292 if (!mPowerKeyHandled) { 1293 mPowerKeyHandled = true; 1294 mHandler.removeMessages(MSG_POWER_LONG_PRESS); 1295 } 1296 } 1297 1298 private void cancelPendingBackKeyAction() { 1299 if (!mBackKeyHandled) { 1300 mBackKeyHandled = true; 1301 mHandler.removeMessages(MSG_BACK_LONG_PRESS); 1302 } 1303 } 1304 1305 private void backMultiPressAction(long eventTime, int count) { 1306 if (count >= PANIC_PRESS_BACK_COUNT) { 1307 switch (mPanicPressOnBackBehavior) { 1308 case PANIC_PRESS_BACK_NOTHING: 1309 break; 1310 case PANIC_PRESS_BACK_HOME: 1311 launchHomeFromHotKey(); 1312 break; 1313 } 1314 } 1315 } 1316 1317 private void powerPress(long eventTime, boolean interactive, int count) { 1318 if (mScreenOnEarly && !mScreenOnFully) { 1319 Slog.i(TAG, "Suppressed redundant power key press while " 1320 + "already in the process of turning the screen on."); 1321 return; 1322 } 1323 1324 if (count == 2) { 1325 powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior); 1326 } else if (count == 3) { 1327 powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior); 1328 } else if (interactive && !mBeganFromNonInteractive) { 1329 switch (mShortPressOnPowerBehavior) { 1330 case SHORT_PRESS_POWER_NOTHING: 1331 break; 1332 case SHORT_PRESS_POWER_GO_TO_SLEEP: 1333 mPowerManager.goToSleep(eventTime, 1334 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 1335 break; 1336 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP: 1337 mPowerManager.goToSleep(eventTime, 1338 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 1339 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 1340 break; 1341 case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME: 1342 mPowerManager.goToSleep(eventTime, 1343 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 1344 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 1345 launchHomeFromHotKey(); 1346 break; 1347 case SHORT_PRESS_POWER_GO_HOME: 1348 launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/); 1349 break; 1350 } 1351 } 1352 } 1353 1354 private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) { 1355 switch (behavior) { 1356 case MULTI_PRESS_POWER_NOTHING: 1357 break; 1358 case MULTI_PRESS_POWER_THEATER_MODE: 1359 if (!isUserSetupComplete()) { 1360 Slog.i(TAG, "Ignoring toggling theater mode - device not setup."); 1361 break; 1362 } 1363 1364 if (isTheaterModeEnabled()) { 1365 Slog.i(TAG, "Toggling theater mode off."); 1366 Settings.Global.putInt(mContext.getContentResolver(), 1367 Settings.Global.THEATER_MODE_ON, 0); 1368 if (!interactive) { 1369 wakeUpFromPowerKey(eventTime); 1370 } 1371 } else { 1372 Slog.i(TAG, "Toggling theater mode on."); 1373 Settings.Global.putInt(mContext.getContentResolver(), 1374 Settings.Global.THEATER_MODE_ON, 1); 1375 1376 if (mGoToSleepOnButtonPressTheaterMode && interactive) { 1377 mPowerManager.goToSleep(eventTime, 1378 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 1379 } 1380 } 1381 break; 1382 case MULTI_PRESS_POWER_BRIGHTNESS_BOOST: 1383 Slog.i(TAG, "Starting brightness boost."); 1384 if (!interactive) { 1385 wakeUpFromPowerKey(eventTime); 1386 } 1387 mPowerManager.boostScreenBrightness(eventTime); 1388 break; 1389 } 1390 } 1391 1392 private int getMaxMultiPressPowerCount() { 1393 if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) { 1394 return 3; 1395 } 1396 if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) { 1397 return 2; 1398 } 1399 return 1; 1400 } 1401 1402 private void powerLongPress() { 1403 final int behavior = getResolvedLongPressOnPowerBehavior(); 1404 switch (behavior) { 1405 case LONG_PRESS_POWER_NOTHING: 1406 break; 1407 case LONG_PRESS_POWER_GLOBAL_ACTIONS: 1408 mPowerKeyHandled = true; 1409 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) { 1410 performAuditoryFeedbackForAccessibilityIfNeed(); 1411 } 1412 showGlobalActionsInternal(); 1413 break; 1414 case LONG_PRESS_POWER_SHUT_OFF: 1415 case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM: 1416 mPowerKeyHandled = true; 1417 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 1418 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); 1419 mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF); 1420 break; 1421 } 1422 } 1423 1424 private void backLongPress() { 1425 mBackKeyHandled = true; 1426 1427 switch (mLongPressOnBackBehavior) { 1428 case LONG_PRESS_BACK_NOTHING: 1429 break; 1430 case LONG_PRESS_BACK_GO_TO_VOICE_ASSIST: 1431 final boolean keyguardActive = mKeyguardDelegate == null 1432 ? false 1433 : mKeyguardDelegate.isShowing(); 1434 if (!keyguardActive) { 1435 Intent intent = new Intent(Intent.ACTION_VOICE_ASSIST); 1436 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 1437 } 1438 break; 1439 } 1440 } 1441 1442 private void disposeInputConsumer(InputConsumer inputConsumer) { 1443 if (inputConsumer != null) { 1444 inputConsumer.dismiss(); 1445 } 1446 } 1447 1448 private void sleepPress(long eventTime) { 1449 if (mShortPressOnSleepBehavior == SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME) { 1450 launchHomeFromHotKey(false /* awakenDreams */, true /*respectKeyguard*/); 1451 } 1452 } 1453 1454 private void sleepRelease(long eventTime) { 1455 switch (mShortPressOnSleepBehavior) { 1456 case SHORT_PRESS_SLEEP_GO_TO_SLEEP: 1457 case SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME: 1458 Slog.i(TAG, "sleepRelease() calling goToSleep(GO_TO_SLEEP_REASON_SLEEP_BUTTON)"); 1459 mPowerManager.goToSleep(eventTime, 1460 PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON, 0); 1461 break; 1462 } 1463 } 1464 1465 private int getResolvedLongPressOnPowerBehavior() { 1466 if (FactoryTest.isLongPressOnPowerOffEnabled()) { 1467 return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM; 1468 } 1469 return mLongPressOnPowerBehavior; 1470 } 1471 1472 private boolean hasLongPressOnPowerBehavior() { 1473 return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING; 1474 } 1475 1476 private boolean hasLongPressOnBackBehavior() { 1477 return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING; 1478 } 1479 1480 private boolean hasPanicPressOnBackBehavior() { 1481 return mPanicPressOnBackBehavior != PANIC_PRESS_BACK_NOTHING; 1482 } 1483 1484 private void interceptScreenshotChord() { 1485 if (mScreenshotChordEnabled 1486 && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered 1487 && !mScreenshotChordVolumeUpKeyTriggered) { 1488 final long now = SystemClock.uptimeMillis(); 1489 if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS 1490 && now <= mScreenshotChordPowerKeyTime 1491 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) { 1492 mScreenshotChordVolumeDownKeyConsumed = true; 1493 cancelPendingPowerKeyAction(); 1494 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN); 1495 mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay()); 1496 } 1497 } 1498 } 1499 1500 private long getScreenshotChordLongPressDelay() { 1501 if (mKeyguardDelegate.isShowing()) { 1502 // Double the time it takes to take a screenshot from the keyguard 1503 return (long) (KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER * 1504 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1505 } 1506 return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout(); 1507 } 1508 1509 private void cancelPendingScreenshotChordAction() { 1510 mHandler.removeCallbacks(mScreenshotRunnable); 1511 } 1512 1513 private final Runnable mEndCallLongPress = new Runnable() { 1514 @Override 1515 public void run() { 1516 mEndCallKeyHandled = true; 1517 if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) { 1518 performAuditoryFeedbackForAccessibilityIfNeed(); 1519 } 1520 showGlobalActionsInternal(); 1521 } 1522 }; 1523 1524 private class ScreenshotRunnable implements Runnable { 1525 private int mScreenshotType = TAKE_SCREENSHOT_FULLSCREEN; 1526 1527 public void setScreenshotType(int screenshotType) { 1528 mScreenshotType = screenshotType; 1529 } 1530 1531 @Override 1532 public void run() { 1533 takeScreenshot(mScreenshotType); 1534 } 1535 } 1536 1537 private final ScreenshotRunnable mScreenshotRunnable = new ScreenshotRunnable(); 1538 1539 @Override 1540 public void showGlobalActions() { 1541 mHandler.removeMessages(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS); 1542 mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_GLOBAL_ACTIONS); 1543 } 1544 1545 void showGlobalActionsInternal() { 1546 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); 1547 if (mGlobalActions == null) { 1548 mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs); 1549 } 1550 final boolean keyguardShowing = isKeyguardShowingAndNotOccluded(); 1551 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned()); 1552 if (keyguardShowing) { 1553 // since it took two seconds of long press to bring this up, 1554 // poke the wake lock so they have some time to see the dialog. 1555 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 1556 } 1557 } 1558 1559 boolean isDeviceProvisioned() { 1560 return Settings.Global.getInt( 1561 mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0; 1562 } 1563 1564 boolean isUserSetupComplete() { 1565 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 1566 Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; 1567 } 1568 1569 private void handleShortPressOnHome() { 1570 // Turn on the connected TV and switch HDMI input if we're a HDMI playback device. 1571 final HdmiControl hdmiControl = getHdmiControl(); 1572 if (hdmiControl != null) { 1573 hdmiControl.turnOnTv(); 1574 } 1575 1576 // If there's a dream running then use home to escape the dream 1577 // but don't actually go home. 1578 if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) { 1579 mDreamManagerInternal.stopDream(false /*immediate*/); 1580 return; 1581 } 1582 1583 // Go home! 1584 launchHomeFromHotKey(); 1585 } 1586 1587 /** 1588 * Creates an accessor to HDMI control service that performs the operation of 1589 * turning on TV (optional) and switching input to us. If HDMI control service 1590 * is not available or we're not a HDMI playback device, the operation is no-op. 1591 * @return {@link HdmiControl} instance if available, null otherwise. 1592 */ 1593 private HdmiControl getHdmiControl() { 1594 if (null == mHdmiControl) { 1595 if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_HDMI_CEC)) { 1596 return null; 1597 } 1598 HdmiControlManager manager = (HdmiControlManager) mContext.getSystemService( 1599 Context.HDMI_CONTROL_SERVICE); 1600 HdmiPlaybackClient client = null; 1601 if (manager != null) { 1602 client = manager.getPlaybackClient(); 1603 } 1604 mHdmiControl = new HdmiControl(client); 1605 } 1606 return mHdmiControl; 1607 } 1608 1609 private static class HdmiControl { 1610 private final HdmiPlaybackClient mClient; 1611 1612 private HdmiControl(HdmiPlaybackClient client) { 1613 mClient = client; 1614 } 1615 1616 public void turnOnTv() { 1617 if (mClient == null) { 1618 return; 1619 } 1620 mClient.oneTouchPlay(new OneTouchPlayCallback() { 1621 @Override 1622 public void onComplete(int result) { 1623 if (result != HdmiControlManager.RESULT_SUCCESS) { 1624 Log.w(TAG, "One touch play failed: " + result); 1625 } 1626 } 1627 }); 1628 } 1629 } 1630 1631 private void handleLongPressOnHome(int deviceId) { 1632 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_NOTHING) { 1633 return; 1634 } 1635 mHomeConsumed = true; 1636 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 1637 1638 switch (mLongPressOnHomeBehavior) { 1639 case LONG_PRESS_HOME_RECENT_SYSTEM_UI: 1640 toggleRecentApps(); 1641 break; 1642 case LONG_PRESS_HOME_ASSIST: 1643 launchAssistAction(null, deviceId); 1644 break; 1645 default: 1646 Log.w(TAG, "Undefined home long press behavior: " + mLongPressOnHomeBehavior); 1647 break; 1648 } 1649 } 1650 1651 private void handleDoubleTapOnHome() { 1652 if (mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { 1653 mHomeConsumed = true; 1654 toggleRecentApps(); 1655 } 1656 } 1657 1658 private void showTvPictureInPictureMenu(KeyEvent event) { 1659 if (DEBUG_INPUT) Log.d(TAG, "showTvPictureInPictureMenu event=" + event); 1660 mHandler.removeMessages(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU); 1661 Message msg = mHandler.obtainMessage(MSG_SHOW_TV_PICTURE_IN_PICTURE_MENU); 1662 msg.setAsynchronous(true); 1663 msg.sendToTarget(); 1664 } 1665 1666 private void showTvPictureInPictureMenuInternal() { 1667 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 1668 if (statusbar != null) { 1669 statusbar.showTvPictureInPictureMenu(); 1670 } 1671 } 1672 1673 private final Runnable mHomeDoubleTapTimeoutRunnable = new Runnable() { 1674 @Override 1675 public void run() { 1676 if (mHomeDoubleTapPending) { 1677 mHomeDoubleTapPending = false; 1678 handleShortPressOnHome(); 1679 } 1680 } 1681 }; 1682 1683 private boolean isRoundWindow() { 1684 return mContext.getResources().getConfiguration().isScreenRound(); 1685 } 1686 1687 /** {@inheritDoc} */ 1688 @Override 1689 public void init(Context context, IWindowManager windowManager, 1690 WindowManagerFuncs windowManagerFuncs) { 1691 mContext = context; 1692 mWindowManager = windowManager; 1693 mWindowManagerFuncs = windowManagerFuncs; 1694 mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); 1695 mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class); 1696 mInputManagerInternal = LocalServices.getService(InputManagerInternal.class); 1697 mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); 1698 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 1699 mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); 1700 mHasFeatureWatch = mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH); 1701 1702 // Init display burn-in protection 1703 boolean burnInProtectionEnabled = context.getResources().getBoolean( 1704 com.android.internal.R.bool.config_enableBurnInProtection); 1705 // Allow a system property to override this. Used by developer settings. 1706 boolean burnInProtectionDevMode = 1707 SystemProperties.getBoolean("persist.debug.force_burn_in", false); 1708 if (burnInProtectionEnabled || burnInProtectionDevMode) { 1709 final int minHorizontal; 1710 final int maxHorizontal; 1711 final int minVertical; 1712 final int maxVertical; 1713 final int maxRadius; 1714 if (burnInProtectionDevMode) { 1715 minHorizontal = -8; 1716 maxHorizontal = 8; 1717 minVertical = -8; 1718 maxVertical = -4; 1719 maxRadius = (isRoundWindow()) ? 6 : -1; 1720 } else { 1721 Resources resources = context.getResources(); 1722 minHorizontal = resources.getInteger( 1723 com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset); 1724 maxHorizontal = resources.getInteger( 1725 com.android.internal.R.integer.config_burnInProtectionMaxHorizontalOffset); 1726 minVertical = resources.getInteger( 1727 com.android.internal.R.integer.config_burnInProtectionMinVerticalOffset); 1728 maxVertical = resources.getInteger( 1729 com.android.internal.R.integer.config_burnInProtectionMaxVerticalOffset); 1730 maxRadius = resources.getInteger( 1731 com.android.internal.R.integer.config_burnInProtectionMaxRadius); 1732 } 1733 mBurnInProtectionHelper = new BurnInProtectionHelper( 1734 context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius); 1735 } 1736 1737 mHandler = new PolicyHandler(); 1738 mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler); 1739 mOrientationListener = new MyOrientationListener(mContext, mHandler); 1740 try { 1741 mOrientationListener.setCurrentRotation(windowManager.getRotation()); 1742 } catch (RemoteException ex) { } 1743 mSettingsObserver = new SettingsObserver(mHandler); 1744 mSettingsObserver.observe(); 1745 mShortcutManager = new ShortcutManager(context); 1746 mUiMode = context.getResources().getInteger( 1747 com.android.internal.R.integer.config_defaultUiModeType); 1748 mHomeIntent = new Intent(Intent.ACTION_MAIN, null); 1749 mHomeIntent.addCategory(Intent.CATEGORY_HOME); 1750 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1751 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 1752 mEnableCarDockHomeCapture = context.getResources().getBoolean( 1753 com.android.internal.R.bool.config_enableCarDockHomeLaunch); 1754 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null); 1755 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK); 1756 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1757 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 1758 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null); 1759 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK); 1760 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1761 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 1762 1763 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 1764 mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 1765 "PhoneWindowManager.mBroadcastWakeLock"); 1766 mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 1767 "PhoneWindowManager.mPowerKeyWakeLock"); 1768 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable")); 1769 mSupportAutoRotation = mContext.getResources().getBoolean( 1770 com.android.internal.R.bool.config_supportAutoRotation); 1771 mLidOpenRotation = readRotation( 1772 com.android.internal.R.integer.config_lidOpenRotation); 1773 mCarDockRotation = readRotation( 1774 com.android.internal.R.integer.config_carDockRotation); 1775 mDeskDockRotation = readRotation( 1776 com.android.internal.R.integer.config_deskDockRotation); 1777 mUndockedHdmiRotation = readRotation( 1778 com.android.internal.R.integer.config_undockedHdmiRotation); 1779 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean( 1780 com.android.internal.R.bool.config_carDockEnablesAccelerometer); 1781 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean( 1782 com.android.internal.R.bool.config_deskDockEnablesAccelerometer); 1783 mLidKeyboardAccessibility = mContext.getResources().getInteger( 1784 com.android.internal.R.integer.config_lidKeyboardAccessibility); 1785 mLidNavigationAccessibility = mContext.getResources().getInteger( 1786 com.android.internal.R.integer.config_lidNavigationAccessibility); 1787 mLidControlsScreenLock = mContext.getResources().getBoolean( 1788 com.android.internal.R.bool.config_lidControlsScreenLock); 1789 mLidControlsSleep = mContext.getResources().getBoolean( 1790 com.android.internal.R.bool.config_lidControlsSleep); 1791 mTranslucentDecorEnabled = mContext.getResources().getBoolean( 1792 com.android.internal.R.bool.config_enableTranslucentDecor); 1793 1794 mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean( 1795 com.android.internal.R.bool.config_allowTheaterModeWakeFromKey); 1796 mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey 1797 || mContext.getResources().getBoolean( 1798 com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey); 1799 mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean( 1800 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion); 1801 mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean( 1802 com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming); 1803 mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean( 1804 com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens); 1805 mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean( 1806 com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch); 1807 mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean( 1808 com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture); 1809 1810 mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean( 1811 com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode); 1812 1813 mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean( 1814 com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive); 1815 1816 mLongPressOnBackBehavior = mContext.getResources().getInteger( 1817 com.android.internal.R.integer.config_longPressOnBackBehavior); 1818 mPanicPressOnBackBehavior = mContext.getResources().getInteger( 1819 com.android.internal.R.integer.config_backPanicBehavior); 1820 1821 mShortPressOnPowerBehavior = mContext.getResources().getInteger( 1822 com.android.internal.R.integer.config_shortPressOnPowerBehavior); 1823 mLongPressOnPowerBehavior = mContext.getResources().getInteger( 1824 com.android.internal.R.integer.config_longPressOnPowerBehavior); 1825 mDoublePressOnPowerBehavior = mContext.getResources().getInteger( 1826 com.android.internal.R.integer.config_doublePressOnPowerBehavior); 1827 mTriplePressOnPowerBehavior = mContext.getResources().getInteger( 1828 com.android.internal.R.integer.config_triplePressOnPowerBehavior); 1829 mShortPressOnSleepBehavior = mContext.getResources().getInteger( 1830 com.android.internal.R.integer.config_shortPressOnSleepBehavior); 1831 1832 mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION; 1833 1834 readConfigurationDependentBehaviors(); 1835 1836 mAccessibilityManager = (AccessibilityManager) context.getSystemService( 1837 Context.ACCESSIBILITY_SERVICE); 1838 1839 // register for dock events 1840 IntentFilter filter = new IntentFilter(); 1841 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE); 1842 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE); 1843 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE); 1844 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE); 1845 filter.addAction(Intent.ACTION_DOCK_EVENT); 1846 Intent intent = context.registerReceiver(mDockReceiver, filter); 1847 if (intent != null) { 1848 // Retrieve current sticky dock event broadcast. 1849 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 1850 Intent.EXTRA_DOCK_STATE_UNDOCKED); 1851 } 1852 1853 // register for dream-related broadcasts 1854 filter = new IntentFilter(); 1855 filter.addAction(Intent.ACTION_DREAMING_STARTED); 1856 filter.addAction(Intent.ACTION_DREAMING_STOPPED); 1857 context.registerReceiver(mDreamReceiver, filter); 1858 1859 // register for multiuser-relevant broadcasts 1860 filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); 1861 context.registerReceiver(mMultiuserReceiver, filter); 1862 1863 // monitor for system gestures 1864 mSystemGestures = new SystemGesturesPointerEventListener(context, 1865 new SystemGesturesPointerEventListener.Callbacks() { 1866 @Override 1867 public void onSwipeFromTop() { 1868 if (mStatusBar != null) { 1869 requestTransientBars(mStatusBar); 1870 } 1871 } 1872 @Override 1873 public void onSwipeFromBottom() { 1874 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_BOTTOM) { 1875 requestTransientBars(mNavigationBar); 1876 } 1877 } 1878 @Override 1879 public void onSwipeFromRight() { 1880 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_RIGHT) { 1881 requestTransientBars(mNavigationBar); 1882 } 1883 } 1884 @Override 1885 public void onSwipeFromLeft() { 1886 if (mNavigationBar != null && mNavigationBarPosition == NAV_BAR_LEFT) { 1887 requestTransientBars(mNavigationBar); 1888 } 1889 } 1890 @Override 1891 public void onFling(int duration) { 1892 if (mPowerManagerInternal != null) { 1893 mPowerManagerInternal.powerHint( 1894 PowerHint.INTERACTION, duration); 1895 } 1896 } 1897 @Override 1898 public void onDebug() { 1899 // no-op 1900 } 1901 @Override 1902 public void onDown() { 1903 mOrientationListener.onTouchStart(); 1904 } 1905 @Override 1906 public void onUpOrCancel() { 1907 mOrientationListener.onTouchEnd(); 1908 } 1909 @Override 1910 public void onMouseHoverAtTop() { 1911 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); 1912 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); 1913 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS; 1914 mHandler.sendMessageDelayed(msg, 500); 1915 } 1916 @Override 1917 public void onMouseHoverAtBottom() { 1918 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); 1919 Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS); 1920 msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION; 1921 mHandler.sendMessageDelayed(msg, 500); 1922 } 1923 @Override 1924 public void onMouseLeaveFromEdge() { 1925 mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS); 1926 } 1927 }); 1928 mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext); 1929 mWindowManagerFuncs.registerPointerEventListener(mSystemGestures); 1930 1931 mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); 1932 mLongPressVibePattern = getLongIntArray(mContext.getResources(), 1933 com.android.internal.R.array.config_longPressVibePattern); 1934 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(), 1935 com.android.internal.R.array.config_virtualKeyVibePattern); 1936 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(), 1937 com.android.internal.R.array.config_keyboardTapVibePattern); 1938 mClockTickVibePattern = getLongIntArray(mContext.getResources(), 1939 com.android.internal.R.array.config_clockTickVibePattern); 1940 mCalendarDateVibePattern = getLongIntArray(mContext.getResources(), 1941 com.android.internal.R.array.config_calendarDateVibePattern); 1942 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(), 1943 com.android.internal.R.array.config_safeModeDisabledVibePattern); 1944 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(), 1945 com.android.internal.R.array.config_safeModeEnabledVibePattern); 1946 mContextClickVibePattern = getLongIntArray(mContext.getResources(), 1947 com.android.internal.R.array.config_contextClickVibePattern); 1948 1949 mScreenshotChordEnabled = mContext.getResources().getBoolean( 1950 com.android.internal.R.bool.config_enableScreenshotChord); 1951 1952 mGlobalKeyManager = new GlobalKeyManager(mContext); 1953 1954 // Controls rotation and the like. 1955 initializeHdmiState(); 1956 1957 // Match current screen state. 1958 if (!mPowerManager.isInteractive()) { 1959 startedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER); 1960 finishedGoingToSleep(WindowManagerPolicy.OFF_BECAUSE_OF_USER); 1961 } 1962 1963 mWindowManagerInternal.registerAppTransitionListener( 1964 mStatusBarController.getAppTransitionListener()); 1965 mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() { 1966 @Override 1967 public int onAppTransitionStartingLocked(int transit, IBinder openToken, 1968 IBinder closeToken, 1969 Animation openAnimation, Animation closeAnimation) { 1970 return handleStartTransitionForKeyguardLw(transit, openAnimation); 1971 } 1972 1973 @Override 1974 public void onAppTransitionCancelledLocked(int transit) { 1975 handleStartTransitionForKeyguardLw(transit, null /* transit */); 1976 } 1977 }); 1978 } 1979 1980 /** 1981 * Read values from config.xml that may be overridden depending on 1982 * the configuration of the device. 1983 * eg. Disable long press on home goes to recents on sw600dp. 1984 */ 1985 private void readConfigurationDependentBehaviors() { 1986 final Resources res = mContext.getResources(); 1987 1988 mLongPressOnHomeBehavior = res.getInteger( 1989 com.android.internal.R.integer.config_longPressOnHomeBehavior); 1990 if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING || 1991 mLongPressOnHomeBehavior > LAST_LONG_PRESS_HOME_BEHAVIOR) { 1992 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING; 1993 } 1994 1995 mDoubleTapOnHomeBehavior = res.getInteger( 1996 com.android.internal.R.integer.config_doubleTapOnHomeBehavior); 1997 if (mDoubleTapOnHomeBehavior < DOUBLE_TAP_HOME_NOTHING || 1998 mDoubleTapOnHomeBehavior > DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { 1999 mDoubleTapOnHomeBehavior = LONG_PRESS_HOME_NOTHING; 2000 } 2001 2002 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_NOTHING; 2003 if (mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { 2004 mShortPressWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE; 2005 } 2006 2007 mNavBarOpacityMode = res.getInteger( 2008 com.android.internal.R.integer.config_navBarOpacityMode); 2009 } 2010 2011 @Override 2012 public void setInitialDisplaySize(Display display, int width, int height, int density) { 2013 // This method might be called before the policy has been fully initialized 2014 // or for other displays we don't care about. 2015 // TODO(multi-display): Define policy for secondary displays. 2016 if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) { 2017 return; 2018 } 2019 mDisplay = display; 2020 2021 final Resources res = mContext.getResources(); 2022 int shortSize, longSize; 2023 if (width > height) { 2024 shortSize = height; 2025 longSize = width; 2026 mLandscapeRotation = Surface.ROTATION_0; 2027 mSeascapeRotation = Surface.ROTATION_180; 2028 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) { 2029 mPortraitRotation = Surface.ROTATION_90; 2030 mUpsideDownRotation = Surface.ROTATION_270; 2031 } else { 2032 mPortraitRotation = Surface.ROTATION_270; 2033 mUpsideDownRotation = Surface.ROTATION_90; 2034 } 2035 } else { 2036 shortSize = width; 2037 longSize = height; 2038 mPortraitRotation = Surface.ROTATION_0; 2039 mUpsideDownRotation = Surface.ROTATION_180; 2040 if (res.getBoolean(com.android.internal.R.bool.config_reverseDefaultRotation)) { 2041 mLandscapeRotation = Surface.ROTATION_270; 2042 mSeascapeRotation = Surface.ROTATION_90; 2043 } else { 2044 mLandscapeRotation = Surface.ROTATION_90; 2045 mSeascapeRotation = Surface.ROTATION_270; 2046 } 2047 } 2048 2049 // SystemUI (status bar) layout policy 2050 int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density; 2051 int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density; 2052 2053 // Allow the navigation bar to move on non-square small devices (phones). 2054 mNavigationBarCanMove = width != height && shortSizeDp < 600; 2055 2056 mHasNavigationBar = res.getBoolean(com.android.internal.R.bool.config_showNavigationBar); 2057 2058 // Allow a system property to override this. Used by the emulator. 2059 // See also hasNavigationBar(). 2060 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); 2061 if ("1".equals(navBarOverride)) { 2062 mHasNavigationBar = false; 2063 } else if ("0".equals(navBarOverride)) { 2064 mHasNavigationBar = true; 2065 } 2066 2067 // For demo purposes, allow the rotation of the HDMI display to be controlled. 2068 // By default, HDMI locks rotation to landscape. 2069 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) { 2070 mDemoHdmiRotation = mPortraitRotation; 2071 } else { 2072 mDemoHdmiRotation = mLandscapeRotation; 2073 } 2074 mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false); 2075 2076 // For demo purposes, allow the rotation of the remote display to be controlled. 2077 // By default, remote display locks rotation to landscape. 2078 if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) { 2079 mDemoRotation = mPortraitRotation; 2080 } else { 2081 mDemoRotation = mLandscapeRotation; 2082 } 2083 mDemoRotationLock = SystemProperties.getBoolean( 2084 "persist.demo.rotationlock", false); 2085 2086 // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per 2087 // http://developer.android.com/guide/practices/screens_support.html#range 2088 mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 && 2089 res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) && 2090 // For debug purposes the next line turns this feature off with: 2091 // $ adb shell setprop config.override_forced_orient true 2092 // $ adb shell wm size reset 2093 !"true".equals(SystemProperties.get("config.override_forced_orient")); 2094 } 2095 2096 /** 2097 * @return whether the navigation bar can be hidden, e.g. the device has a 2098 * navigation bar and touch exploration is not enabled 2099 */ 2100 private boolean canHideNavigationBar() { 2101 return mHasNavigationBar; 2102 } 2103 2104 @Override 2105 public boolean isDefaultOrientationForced() { 2106 return mForceDefaultOrientation; 2107 } 2108 2109 @Override 2110 public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) { 2111 // TODO(multi-display): Define policy for secondary displays. 2112 if (display.getDisplayId() == Display.DEFAULT_DISPLAY) { 2113 mOverscanLeft = left; 2114 mOverscanTop = top; 2115 mOverscanRight = right; 2116 mOverscanBottom = bottom; 2117 } 2118 } 2119 2120 public void updateSettings() { 2121 ContentResolver resolver = mContext.getContentResolver(); 2122 boolean updateRotation = false; 2123 synchronized (mLock) { 2124 mEndcallBehavior = Settings.System.getIntForUser(resolver, 2125 Settings.System.END_BUTTON_BEHAVIOR, 2126 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT, 2127 UserHandle.USER_CURRENT); 2128 mIncallPowerBehavior = Settings.Secure.getIntForUser(resolver, 2129 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, 2130 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT, 2131 UserHandle.USER_CURRENT); 2132 mIncallBackBehavior = Settings.Secure.getIntForUser(resolver, 2133 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR, 2134 Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT, 2135 UserHandle.USER_CURRENT); 2136 2137 // Configure wake gesture. 2138 boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver, 2139 Settings.Secure.WAKE_GESTURE_ENABLED, 0, 2140 UserHandle.USER_CURRENT) != 0; 2141 if (mWakeGestureEnabledSetting != wakeGestureEnabledSetting) { 2142 mWakeGestureEnabledSetting = wakeGestureEnabledSetting; 2143 updateWakeGestureListenerLp(); 2144 } 2145 2146 // Configure rotation lock. 2147 int userRotation = Settings.System.getIntForUser(resolver, 2148 Settings.System.USER_ROTATION, Surface.ROTATION_0, 2149 UserHandle.USER_CURRENT); 2150 if (mUserRotation != userRotation) { 2151 mUserRotation = userRotation; 2152 updateRotation = true; 2153 } 2154 int userRotationMode = Settings.System.getIntForUser(resolver, 2155 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 2156 WindowManagerPolicy.USER_ROTATION_FREE : 2157 WindowManagerPolicy.USER_ROTATION_LOCKED; 2158 if (mUserRotationMode != userRotationMode) { 2159 mUserRotationMode = userRotationMode; 2160 updateRotation = true; 2161 updateOrientationListenerLp(); 2162 } 2163 2164 if (mSystemReady) { 2165 int pointerLocation = Settings.System.getIntForUser(resolver, 2166 Settings.System.POINTER_LOCATION, 0, UserHandle.USER_CURRENT); 2167 if (mPointerLocationMode != pointerLocation) { 2168 mPointerLocationMode = pointerLocation; 2169 mHandler.sendEmptyMessage(pointerLocation != 0 ? 2170 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION); 2171 } 2172 } 2173 // use screen off timeout setting as the timeout for the lockscreen 2174 mLockScreenTimeout = Settings.System.getIntForUser(resolver, 2175 Settings.System.SCREEN_OFF_TIMEOUT, 0, UserHandle.USER_CURRENT); 2176 String imId = Settings.Secure.getStringForUser(resolver, 2177 Settings.Secure.DEFAULT_INPUT_METHOD, UserHandle.USER_CURRENT); 2178 boolean hasSoftInput = imId != null && imId.length() > 0; 2179 if (mHasSoftInput != hasSoftInput) { 2180 mHasSoftInput = hasSoftInput; 2181 updateRotation = true; 2182 } 2183 if (mImmersiveModeConfirmation != null) { 2184 mImmersiveModeConfirmation.loadSetting(mCurrentUserId); 2185 } 2186 } 2187 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 2188 PolicyControl.reloadFromSetting(mContext); 2189 } 2190 if (updateRotation) { 2191 updateRotation(true); 2192 } 2193 } 2194 2195 private void updateWakeGestureListenerLp() { 2196 if (shouldEnableWakeGestureLp()) { 2197 mWakeGestureListener.requestWakeUpTrigger(); 2198 } else { 2199 mWakeGestureListener.cancelWakeUpTrigger(); 2200 } 2201 } 2202 2203 private boolean shouldEnableWakeGestureLp() { 2204 return mWakeGestureEnabledSetting && !mAwake 2205 && (!mLidControlsSleep || mLidState != LID_CLOSED) 2206 && mWakeGestureListener.isSupported(); 2207 } 2208 2209 private void enablePointerLocation() { 2210 if (mPointerLocationView == null) { 2211 mPointerLocationView = new PointerLocationView(mContext); 2212 mPointerLocationView.setPrintCoords(false); 2213 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 2214 WindowManager.LayoutParams.MATCH_PARENT, 2215 WindowManager.LayoutParams.MATCH_PARENT); 2216 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; 2217 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN 2218 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE 2219 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 2220 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 2221 if (ActivityManager.isHighEndGfx()) { 2222 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; 2223 lp.privateFlags |= 2224 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED; 2225 } 2226 lp.format = PixelFormat.TRANSLUCENT; 2227 lp.setTitle("PointerLocation"); 2228 WindowManager wm = (WindowManager) 2229 mContext.getSystemService(Context.WINDOW_SERVICE); 2230 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 2231 wm.addView(mPointerLocationView, lp); 2232 mWindowManagerFuncs.registerPointerEventListener(mPointerLocationView); 2233 } 2234 } 2235 2236 private void disablePointerLocation() { 2237 if (mPointerLocationView != null) { 2238 mWindowManagerFuncs.unregisterPointerEventListener(mPointerLocationView); 2239 WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 2240 wm.removeView(mPointerLocationView); 2241 mPointerLocationView = null; 2242 } 2243 } 2244 2245 private int readRotation(int resID) { 2246 try { 2247 int rotation = mContext.getResources().getInteger(resID); 2248 switch (rotation) { 2249 case 0: 2250 return Surface.ROTATION_0; 2251 case 90: 2252 return Surface.ROTATION_90; 2253 case 180: 2254 return Surface.ROTATION_180; 2255 case 270: 2256 return Surface.ROTATION_270; 2257 } 2258 } catch (Resources.NotFoundException e) { 2259 // fall through 2260 } 2261 return -1; 2262 } 2263 2264 /** {@inheritDoc} */ 2265 @Override 2266 public int checkAddPermission(WindowManager.LayoutParams attrs, int[] outAppOp) { 2267 int type = attrs.type; 2268 2269 outAppOp[0] = AppOpsManager.OP_NONE; 2270 2271 if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) 2272 || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) 2273 || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) { 2274 return WindowManagerGlobal.ADD_INVALID_TYPE; 2275 } 2276 2277 if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) { 2278 // Window manager will make sure these are okay. 2279 return WindowManagerGlobal.ADD_OKAY; 2280 } 2281 String permission = null; 2282 switch (type) { 2283 case TYPE_TOAST: 2284 // XXX right now the app process has complete control over 2285 // this... should introduce a token to let the system 2286 // monitor/control what they are doing. 2287 outAppOp[0] = AppOpsManager.OP_TOAST_WINDOW; 2288 break; 2289 case TYPE_DREAM: 2290 case TYPE_INPUT_METHOD: 2291 case TYPE_WALLPAPER: 2292 case TYPE_PRESENTATION: 2293 case TYPE_PRIVATE_PRESENTATION: 2294 case TYPE_VOICE_INTERACTION: 2295 case TYPE_ACCESSIBILITY_OVERLAY: 2296 case TYPE_QS_DIALOG: 2297 // The window manager will check these. 2298 break; 2299 case TYPE_PHONE: 2300 case TYPE_PRIORITY_PHONE: 2301 case TYPE_SYSTEM_ALERT: 2302 case TYPE_SYSTEM_ERROR: 2303 case TYPE_SYSTEM_OVERLAY: 2304 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW; 2305 outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW; 2306 break; 2307 default: 2308 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 2309 } 2310 if (permission != null) { 2311 if (android.Manifest.permission.SYSTEM_ALERT_WINDOW.equals(permission)) { 2312 final int callingUid = Binder.getCallingUid(); 2313 // system processes will be automatically allowed privilege to draw 2314 if (callingUid == Process.SYSTEM_UID) { 2315 return WindowManagerGlobal.ADD_OKAY; 2316 } 2317 2318 // check if user has enabled this operation. SecurityException will be thrown if 2319 // this app has not been allowed by the user 2320 final int mode = mAppOpsManager.checkOpNoThrow(outAppOp[0], callingUid, 2321 attrs.packageName); 2322 switch (mode) { 2323 case AppOpsManager.MODE_ALLOWED: 2324 case AppOpsManager.MODE_IGNORED: 2325 // although we return ADD_OKAY for MODE_IGNORED, the added window will 2326 // actually be hidden in WindowManagerService 2327 return WindowManagerGlobal.ADD_OKAY; 2328 case AppOpsManager.MODE_ERRORED: 2329 try { 2330 ApplicationInfo appInfo = mContext.getPackageManager() 2331 .getApplicationInfo(attrs.packageName, 2332 UserHandle.getUserId(callingUid)); 2333 // Don't crash legacy apps 2334 if (appInfo.targetSdkVersion < Build.VERSION_CODES.M) { 2335 return WindowManagerGlobal.ADD_OKAY; 2336 } 2337 } catch (PackageManager.NameNotFoundException e) { 2338 /* ignore */ 2339 } 2340 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2341 default: 2342 // in the default mode, we will make a decision here based on 2343 // checkCallingPermission() 2344 if (mContext.checkCallingPermission(permission) != 2345 PackageManager.PERMISSION_GRANTED) { 2346 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2347 } else { 2348 return WindowManagerGlobal.ADD_OKAY; 2349 } 2350 } 2351 } 2352 2353 if (mContext.checkCallingOrSelfPermission(permission) 2354 != PackageManager.PERMISSION_GRANTED) { 2355 return WindowManagerGlobal.ADD_PERMISSION_DENIED; 2356 } 2357 } 2358 return WindowManagerGlobal.ADD_OKAY; 2359 } 2360 2361 @Override 2362 public boolean checkShowToOwnerOnly(WindowManager.LayoutParams attrs) { 2363 2364 // If this switch statement is modified, modify the comment in the declarations of 2365 // the type in {@link WindowManager.LayoutParams} as well. 2366 switch (attrs.type) { 2367 default: 2368 // These are the windows that by default are shown only to the user that created 2369 // them. If this needs to be overridden, set 2370 // {@link WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS} in 2371 // {@link WindowManager.LayoutParams}. Note that permission 2372 // {@link android.Manifest.permission.INTERNAL_SYSTEM_WINDOW} is required as well. 2373 if ((attrs.privateFlags & PRIVATE_FLAG_SHOW_FOR_ALL_USERS) == 0) { 2374 return true; 2375 } 2376 break; 2377 2378 // These are the windows that by default are shown to all users. However, to 2379 // protect against spoofing, check permissions below. 2380 case TYPE_APPLICATION_STARTING: 2381 case TYPE_BOOT_PROGRESS: 2382 case TYPE_DISPLAY_OVERLAY: 2383 case TYPE_INPUT_CONSUMER: 2384 case TYPE_KEYGUARD_DIALOG: 2385 case TYPE_MAGNIFICATION_OVERLAY: 2386 case TYPE_NAVIGATION_BAR: 2387 case TYPE_NAVIGATION_BAR_PANEL: 2388 case TYPE_PHONE: 2389 case TYPE_POINTER: 2390 case TYPE_PRIORITY_PHONE: 2391 case TYPE_SEARCH_BAR: 2392 case TYPE_STATUS_BAR: 2393 case TYPE_STATUS_BAR_PANEL: 2394 case TYPE_STATUS_BAR_SUB_PANEL: 2395 case TYPE_SYSTEM_DIALOG: 2396 case TYPE_VOLUME_OVERLAY: 2397 case TYPE_PRESENTATION: 2398 case TYPE_PRIVATE_PRESENTATION: 2399 case TYPE_DOCK_DIVIDER: 2400 break; 2401 } 2402 2403 // Check if third party app has set window to system window type. 2404 return mContext.checkCallingOrSelfPermission( 2405 android.Manifest.permission.INTERNAL_SYSTEM_WINDOW) 2406 != PackageManager.PERMISSION_GRANTED; 2407 } 2408 2409 @Override 2410 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) { 2411 switch (attrs.type) { 2412 case TYPE_SYSTEM_OVERLAY: 2413 case TYPE_SECURE_SYSTEM_OVERLAY: 2414 // These types of windows can't receive input events. 2415 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 2416 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 2417 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; 2418 break; 2419 case TYPE_STATUS_BAR: 2420 2421 // If the Keyguard is in a hidden state (occluded by another window), we force to 2422 // remove the wallpaper and keyguard flag so that any change in-flight after setting 2423 // the keyguard as occluded wouldn't set these flags again. 2424 // See {@link #processKeyguardSetHiddenResultLw}. 2425 if (mKeyguardOccluded) { 2426 attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; 2427 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 2428 } 2429 break; 2430 2431 case TYPE_SCREENSHOT: 2432 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 2433 break; 2434 2435 case TYPE_TOAST: 2436 // While apps should use the dedicated toast APIs to add such windows 2437 // it possible legacy apps to add the window directly. Therefore, we 2438 // make windows added directly by the app behave as a toast as much 2439 // as possible in terms of timeout and animation. 2440 if (attrs.hideTimeoutMilliseconds < 0 2441 || attrs.hideTimeoutMilliseconds > TOAST_WINDOW_TIMEOUT) { 2442 attrs.hideTimeoutMilliseconds = TOAST_WINDOW_TIMEOUT; 2443 } 2444 attrs.windowAnimations = com.android.internal.R.style.Animation_Toast; 2445 break; 2446 } 2447 2448 if (attrs.type != TYPE_STATUS_BAR) { 2449 // The status bar is the only window allowed to exhibit keyguard behavior. 2450 attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD; 2451 } 2452 2453 if (ActivityManager.isHighEndGfx()) { 2454 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) { 2455 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; 2456 } 2457 final boolean forceWindowDrawsStatusBarBackground = 2458 (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) 2459 != 0; 2460 if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 2461 || forceWindowDrawsStatusBarBackground 2462 && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) { 2463 attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; 2464 } 2465 } 2466 } 2467 2468 void readLidState() { 2469 mLidState = mWindowManagerFuncs.getLidState(); 2470 } 2471 2472 private void readCameraLensCoverState() { 2473 mCameraLensCoverState = mWindowManagerFuncs.getCameraLensCoverState(); 2474 } 2475 2476 private boolean isHidden(int accessibilityMode) { 2477 switch (accessibilityMode) { 2478 case 1: 2479 return mLidState == LID_CLOSED; 2480 case 2: 2481 return mLidState == LID_OPEN; 2482 default: 2483 return false; 2484 } 2485 } 2486 2487 /** {@inheritDoc} */ 2488 @Override 2489 public void adjustConfigurationLw(Configuration config, int keyboardPresence, 2490 int navigationPresence) { 2491 mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0; 2492 2493 readConfigurationDependentBehaviors(); 2494 readLidState(); 2495 2496 if (config.keyboard == Configuration.KEYBOARD_NOKEYS 2497 || (keyboardPresence == PRESENCE_INTERNAL 2498 && isHidden(mLidKeyboardAccessibility))) { 2499 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES; 2500 if (!mHasSoftInput) { 2501 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES; 2502 } 2503 } 2504 2505 if (config.navigation == Configuration.NAVIGATION_NONAV 2506 || (navigationPresence == PRESENCE_INTERNAL 2507 && isHidden(mLidNavigationAccessibility))) { 2508 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES; 2509 } 2510 } 2511 2512 @Override 2513 public void onConfigurationChanged() { 2514 // TODO(multi-display): Define policy for secondary displays. 2515 final Resources res = mContext.getResources(); 2516 2517 mStatusBarHeight = 2518 res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height); 2519 2520 // Height of the navigation bar when presented horizontally at bottom 2521 mNavigationBarHeightForRotationDefault[mPortraitRotation] = 2522 mNavigationBarHeightForRotationDefault[mUpsideDownRotation] = 2523 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height); 2524 mNavigationBarHeightForRotationDefault[mLandscapeRotation] = 2525 mNavigationBarHeightForRotationDefault[mSeascapeRotation] = res.getDimensionPixelSize( 2526 com.android.internal.R.dimen.navigation_bar_height_landscape); 2527 2528 // Width of the navigation bar when presented vertically along one side 2529 mNavigationBarWidthForRotationDefault[mPortraitRotation] = 2530 mNavigationBarWidthForRotationDefault[mUpsideDownRotation] = 2531 mNavigationBarWidthForRotationDefault[mLandscapeRotation] = 2532 mNavigationBarWidthForRotationDefault[mSeascapeRotation] = 2533 res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width); 2534 2535 if (ALTERNATE_CAR_MODE_NAV_SIZE) { 2536 // Height of the navigation bar when presented horizontally at bottom 2537 mNavigationBarHeightForRotationInCarMode[mPortraitRotation] = 2538 mNavigationBarHeightForRotationInCarMode[mUpsideDownRotation] = 2539 res.getDimensionPixelSize( 2540 com.android.internal.R.dimen.navigation_bar_height_car_mode); 2541 mNavigationBarHeightForRotationInCarMode[mLandscapeRotation] = 2542 mNavigationBarHeightForRotationInCarMode[mSeascapeRotation] = res.getDimensionPixelSize( 2543 com.android.internal.R.dimen.navigation_bar_height_landscape_car_mode); 2544 2545 // Width of the navigation bar when presented vertically along one side 2546 mNavigationBarWidthForRotationInCarMode[mPortraitRotation] = 2547 mNavigationBarWidthForRotationInCarMode[mUpsideDownRotation] = 2548 mNavigationBarWidthForRotationInCarMode[mLandscapeRotation] = 2549 mNavigationBarWidthForRotationInCarMode[mSeascapeRotation] = 2550 res.getDimensionPixelSize( 2551 com.android.internal.R.dimen.navigation_bar_width_car_mode); 2552 } 2553 } 2554 2555 /** {@inheritDoc} */ 2556 @Override 2557 public int windowTypeToLayerLw(int type) { 2558 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 2559 return 2; 2560 } 2561 switch (type) { 2562 case TYPE_WALLPAPER: 2563 // wallpaper is at the bottom, though the window manager may move it. 2564 return 1; 2565 case TYPE_PRESENTATION: 2566 case TYPE_PRIVATE_PRESENTATION: 2567 return 2; 2568 case TYPE_DOCK_DIVIDER: 2569 return 2; 2570 case TYPE_QS_DIALOG: 2571 return 2; 2572 case TYPE_PHONE: 2573 return 3; 2574 case TYPE_SEARCH_BAR: 2575 case TYPE_VOICE_INTERACTION_STARTING: 2576 return 4; 2577 case TYPE_VOICE_INTERACTION: 2578 // voice interaction layer is almost immediately above apps. 2579 return 5; 2580 case TYPE_INPUT_CONSUMER: 2581 return 6; 2582 case TYPE_SYSTEM_DIALOG: 2583 return 7; 2584 case TYPE_TOAST: 2585 // toasts and the plugged-in battery thing 2586 return 8; 2587 case TYPE_PRIORITY_PHONE: 2588 // SIM errors and unlock. Not sure if this really should be in a high layer. 2589 return 9; 2590 case TYPE_DREAM: 2591 // used for Dreams (screensavers with TYPE_DREAM windows) 2592 return 10; 2593 case TYPE_SYSTEM_ALERT: 2594 // like the ANR / app crashed dialogs 2595 return 11; 2596 case TYPE_INPUT_METHOD: 2597 // on-screen keyboards and other such input method user interfaces go here. 2598 return 12; 2599 case TYPE_INPUT_METHOD_DIALOG: 2600 // on-screen keyboards and other such input method user interfaces go here. 2601 return 13; 2602 case TYPE_STATUS_BAR_SUB_PANEL: 2603 return 15; 2604 case TYPE_STATUS_BAR: 2605 return 16; 2606 case TYPE_STATUS_BAR_PANEL: 2607 return 17; 2608 case TYPE_KEYGUARD_DIALOG: 2609 return 18; 2610 case TYPE_VOLUME_OVERLAY: 2611 // the on-screen volume indicator and controller shown when the user 2612 // changes the device volume 2613 return 19; 2614 case TYPE_SYSTEM_OVERLAY: 2615 // the on-screen volume indicator and controller shown when the user 2616 // changes the device volume 2617 return 20; 2618 case TYPE_NAVIGATION_BAR: 2619 // the navigation bar, if available, shows atop most things 2620 return 21; 2621 case TYPE_NAVIGATION_BAR_PANEL: 2622 // some panels (e.g. search) need to show on top of the navigation bar 2623 return 22; 2624 case TYPE_SCREENSHOT: 2625 // screenshot selection layer shouldn't go above system error, but it should cover 2626 // navigation bars at the very least. 2627 return 23; 2628 case TYPE_SYSTEM_ERROR: 2629 // system-level error dialogs 2630 return 24; 2631 case TYPE_MAGNIFICATION_OVERLAY: 2632 // used to highlight the magnified portion of a display 2633 return 25; 2634 case TYPE_DISPLAY_OVERLAY: 2635 // used to simulate secondary display devices 2636 return 26; 2637 case TYPE_DRAG: 2638 // the drag layer: input for drag-and-drop is associated with this window, 2639 // which sits above all other focusable windows 2640 return 27; 2641 case TYPE_ACCESSIBILITY_OVERLAY: 2642 // overlay put by accessibility services to intercept user interaction 2643 return 28; 2644 case TYPE_SECURE_SYSTEM_OVERLAY: 2645 return 29; 2646 case TYPE_BOOT_PROGRESS: 2647 return 30; 2648 case TYPE_POINTER: 2649 // the (mouse) pointer layer 2650 return 31; 2651 } 2652 Log.e(TAG, "Unknown window type: " + type); 2653 return 2; 2654 } 2655 2656 /** {@inheritDoc} */ 2657 @Override 2658 public int subWindowTypeToLayerLw(int type) { 2659 switch (type) { 2660 case TYPE_APPLICATION_PANEL: 2661 case TYPE_APPLICATION_ATTACHED_DIALOG: 2662 return APPLICATION_PANEL_SUBLAYER; 2663 case TYPE_APPLICATION_MEDIA: 2664 return APPLICATION_MEDIA_SUBLAYER; 2665 case TYPE_APPLICATION_MEDIA_OVERLAY: 2666 return APPLICATION_MEDIA_OVERLAY_SUBLAYER; 2667 case TYPE_APPLICATION_SUB_PANEL: 2668 return APPLICATION_SUB_PANEL_SUBLAYER; 2669 case TYPE_APPLICATION_ABOVE_SUB_PANEL: 2670 return APPLICATION_ABOVE_SUB_PANEL_SUBLAYER; 2671 } 2672 Log.e(TAG, "Unknown sub-window type: " + type); 2673 return 0; 2674 } 2675 2676 @Override 2677 public int getMaxWallpaperLayer() { 2678 return windowTypeToLayerLw(TYPE_STATUS_BAR); 2679 } 2680 2681 private int getNavigationBarWidth(int rotation, int uiMode) { 2682 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) { 2683 return mNavigationBarWidthForRotationInCarMode[rotation]; 2684 } else { 2685 return mNavigationBarWidthForRotationDefault[rotation]; 2686 } 2687 } 2688 2689 @Override 2690 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode, 2691 int displayId) { 2692 // TODO(multi-display): Support navigation bar on secondary displays. 2693 if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) { 2694 // For a basic navigation bar, when we are in landscape mode we place 2695 // the navigation bar to the side. 2696 if (mNavigationBarCanMove && fullWidth > fullHeight) { 2697 return fullWidth - getNavigationBarWidth(rotation, uiMode); 2698 } 2699 } 2700 return fullWidth; 2701 } 2702 2703 private int getNavigationBarHeight(int rotation, int uiMode) { 2704 if (ALTERNATE_CAR_MODE_NAV_SIZE && (uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_CAR) { 2705 return mNavigationBarHeightForRotationInCarMode[rotation]; 2706 } else { 2707 return mNavigationBarHeightForRotationDefault[rotation]; 2708 } 2709 } 2710 2711 @Override 2712 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode, 2713 int displayId) { 2714 // TODO(multi-display): Support navigation bar on secondary displays. 2715 if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) { 2716 // For a basic navigation bar, when we are in portrait mode we place 2717 // the navigation bar to the bottom. 2718 if (!mNavigationBarCanMove || fullWidth < fullHeight) { 2719 return fullHeight - getNavigationBarHeight(rotation, uiMode); 2720 } 2721 } 2722 return fullHeight; 2723 } 2724 2725 @Override 2726 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode, 2727 int displayId) { 2728 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation, uiMode, displayId); 2729 } 2730 2731 @Override 2732 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode, 2733 int displayId) { 2734 // There is a separate status bar at the top of the display. We don't count that as part 2735 // of the fixed decor, since it can hide; however, for purposes of configurations, 2736 // we do want to exclude it since applications can't generally use that part 2737 // of the screen. 2738 // TODO(multi-display): Support status bars on secondary displays. 2739 if (displayId == Display.DEFAULT_DISPLAY) { 2740 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId) 2741 - mStatusBarHeight; 2742 } 2743 return fullHeight; 2744 } 2745 2746 @Override 2747 public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) { 2748 return attrs.type == TYPE_STATUS_BAR; 2749 } 2750 2751 @Override 2752 public boolean canBeHiddenByKeyguardLw(WindowState win) { 2753 switch (win.getAttrs().type) { 2754 case TYPE_STATUS_BAR: 2755 case TYPE_NAVIGATION_BAR: 2756 case TYPE_WALLPAPER: 2757 case TYPE_DREAM: 2758 return false; 2759 default: 2760 // Hide only windows below the keyguard host window. 2761 return windowTypeToLayerLw(win.getBaseType()) 2762 < windowTypeToLayerLw(TYPE_STATUS_BAR); 2763 } 2764 } 2765 2766 private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) { 2767 2768 // Keyguard visibility of window from activities are determined over activity visibility. 2769 if (win.getAppToken() != null) { 2770 return false; 2771 } 2772 2773 final LayoutParams attrs = win.getAttrs(); 2774 final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() && 2775 ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0 2776 || !canBeHiddenByKeyguardLw(imeTarget)); 2777 2778 // Show IME over the keyguard if the target allows it 2779 boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this) 2780 && showImeOverKeyguard;; 2781 2782 if (isKeyguardLocked() && isKeyguardOccluded()) { 2783 // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded. 2784 allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 2785 // Show error dialogs over apps that are shown on lockscreen 2786 || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0; 2787 } 2788 2789 boolean keyguardLocked = isKeyguardLocked(); 2790 boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER 2791 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 2792 return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == Display.DEFAULT_DISPLAY) 2793 || hideDockDivider; 2794 } 2795 2796 /** {@inheritDoc} */ 2797 @Override 2798 public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme, 2799 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, 2800 int logo, int windowFlags, Configuration overrideConfig) { 2801 if (!SHOW_SPLASH_SCREENS) { 2802 return null; 2803 } 2804 if (packageName == null) { 2805 return null; 2806 } 2807 2808 WindowManager wm = null; 2809 View view = null; 2810 2811 try { 2812 Context context = mContext; 2813 if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName 2814 + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme=" 2815 + Integer.toHexString(theme)); 2816 if (theme != context.getThemeResId() || labelRes != 0) { 2817 try { 2818 context = context.createPackageContext(packageName, 0); 2819 context.setTheme(theme); 2820 } catch (PackageManager.NameNotFoundException e) { 2821 // Ignore 2822 } 2823 } 2824 2825 if (overrideConfig != null && !overrideConfig.equals(EMPTY)) { 2826 if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based" 2827 + " on overrideConfig" + overrideConfig + " for splash screen"); 2828 final Context overrideContext = context.createConfigurationContext(overrideConfig); 2829 overrideContext.setTheme(theme); 2830 final TypedArray typedArray = overrideContext.obtainStyledAttributes( 2831 com.android.internal.R.styleable.Window); 2832 final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0); 2833 if (resId != 0 && overrideContext.getDrawable(resId) != null) { 2834 // We want to use the windowBackground for the override context if it is 2835 // available, otherwise we use the default one to make sure a themed starting 2836 // window is displayed for the app. 2837 if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig" 2838 + overrideConfig + " to starting window resId=" + resId); 2839 context = overrideContext; 2840 } 2841 } 2842 2843 final PhoneWindow win = new PhoneWindow(context); 2844 win.setIsStartingWindow(true); 2845 2846 CharSequence label = context.getResources().getText(labelRes, null); 2847 // Only change the accessibility title if the label is localized 2848 if (label != null) { 2849 win.setTitle(label, true); 2850 } else { 2851 win.setTitle(nonLocalizedLabel, false); 2852 } 2853 2854 win.setType( 2855 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING); 2856 2857 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 2858 // Assumes it's safe to show starting windows of launched apps while 2859 // the keyguard is being hidden. This is okay because starting windows never show 2860 // secret information. 2861 if (mKeyguardOccluded) { 2862 windowFlags |= FLAG_SHOW_WHEN_LOCKED; 2863 } 2864 } 2865 2866 // Force the window flags: this is a fake window, so it is not really 2867 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM 2868 // flag because we do know that the next window will take input 2869 // focus, so we want to get the IME window up on top of us right away. 2870 win.setFlags( 2871 windowFlags| 2872 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| 2873 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| 2874 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 2875 windowFlags| 2876 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| 2877 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| 2878 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 2879 2880 win.setDefaultIcon(icon); 2881 win.setDefaultLogo(logo); 2882 2883 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT, 2884 WindowManager.LayoutParams.MATCH_PARENT); 2885 2886 final WindowManager.LayoutParams params = win.getAttributes(); 2887 params.token = appToken; 2888 params.packageName = packageName; 2889 params.windowAnimations = win.getWindowStyle().getResourceId( 2890 com.android.internal.R.styleable.Window_windowAnimationStyle, 0); 2891 params.privateFlags |= 2892 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED; 2893 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; 2894 2895 if (!compatInfo.supportsScreen()) { 2896 params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; 2897 } 2898 2899 params.setTitle("Splash Screen " + packageName); 2900 2901 wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); 2902 view = win.getDecorView(); 2903 2904 if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for " 2905 + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null)); 2906 2907 wm.addView(view, params); 2908 2909 // Only return the view if it was successfully added to the 2910 // window manager... which we can tell by it having a parent. 2911 return view.getParent() != null ? new SplashScreenSurface(view, appToken) : null; 2912 } catch (WindowManager.BadTokenException e) { 2913 // ignore 2914 Log.w(TAG, appToken + " already running, starting window not displayed. " + 2915 e.getMessage()); 2916 } catch (RuntimeException e) { 2917 // don't crash if something else bad happens, for example a 2918 // failure loading resources because we are loading from an app 2919 // on external storage that has been unmounted. 2920 Log.w(TAG, appToken + " failed creating starting window", e); 2921 } finally { 2922 if (view != null && view.getParent() == null) { 2923 Log.w(TAG, "view not successfully added to wm, removing view"); 2924 wm.removeViewImmediate(view); 2925 } 2926 } 2927 2928 return null; 2929 } 2930 2931 /** 2932 * Preflight adding a window to the system. 2933 * 2934 * Currently enforces that three window types are singletons: 2935 * <ul> 2936 * <li>STATUS_BAR_TYPE</li> 2937 * <li>KEYGUARD_TYPE</li> 2938 * </ul> 2939 * 2940 * @param win The window to be added 2941 * @param attrs Information about the window to be added 2942 * 2943 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, 2944 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON 2945 */ 2946 @Override 2947 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) { 2948 switch (attrs.type) { 2949 case TYPE_STATUS_BAR: 2950 mContext.enforceCallingOrSelfPermission( 2951 android.Manifest.permission.STATUS_BAR_SERVICE, 2952 "PhoneWindowManager"); 2953 if (mStatusBar != null) { 2954 if (mStatusBar.isAlive()) { 2955 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; 2956 } 2957 } 2958 mStatusBar = win; 2959 mStatusBarController.setWindow(win); 2960 break; 2961 case TYPE_NAVIGATION_BAR: 2962 mContext.enforceCallingOrSelfPermission( 2963 android.Manifest.permission.STATUS_BAR_SERVICE, 2964 "PhoneWindowManager"); 2965 if (mNavigationBar != null) { 2966 if (mNavigationBar.isAlive()) { 2967 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; 2968 } 2969 } 2970 mNavigationBar = win; 2971 mNavigationBarController.setWindow(win); 2972 if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar); 2973 break; 2974 case TYPE_NAVIGATION_BAR_PANEL: 2975 case TYPE_STATUS_BAR_PANEL: 2976 case TYPE_STATUS_BAR_SUB_PANEL: 2977 case TYPE_VOICE_INTERACTION_STARTING: 2978 mContext.enforceCallingOrSelfPermission( 2979 android.Manifest.permission.STATUS_BAR_SERVICE, 2980 "PhoneWindowManager"); 2981 break; 2982 } 2983 return WindowManagerGlobal.ADD_OKAY; 2984 } 2985 2986 /** {@inheritDoc} */ 2987 @Override 2988 public void removeWindowLw(WindowState win) { 2989 if (mStatusBar == win) { 2990 mStatusBar = null; 2991 mStatusBarController.setWindow(null); 2992 } else if (mNavigationBar == win) { 2993 mNavigationBar = null; 2994 mNavigationBarController.setWindow(null); 2995 } 2996 } 2997 2998 static final boolean PRINT_ANIM = false; 2999 3000 /** {@inheritDoc} */ 3001 @Override 3002 public int selectAnimationLw(WindowState win, int transit) { 3003 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win 3004 + ": transit=" + transit); 3005 if (win == mStatusBar) { 3006 boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 3007 if (transit == TRANSIT_EXIT 3008 || transit == TRANSIT_HIDE) { 3009 return isKeyguard ? -1 : R.anim.dock_top_exit; 3010 } else if (transit == TRANSIT_ENTER 3011 || transit == TRANSIT_SHOW) { 3012 return isKeyguard ? -1 : R.anim.dock_top_enter; 3013 } 3014 } else if (win == mNavigationBar) { 3015 if (win.getAttrs().windowAnimations != 0) { 3016 return 0; 3017 } 3018 // This can be on either the bottom or the right or the left. 3019 if (mNavigationBarPosition == NAV_BAR_BOTTOM) { 3020 if (transit == TRANSIT_EXIT 3021 || transit == TRANSIT_HIDE) { 3022 if (isKeyguardShowingAndNotOccluded()) { 3023 return R.anim.dock_bottom_exit_keyguard; 3024 } else { 3025 return R.anim.dock_bottom_exit; 3026 } 3027 } else if (transit == TRANSIT_ENTER 3028 || transit == TRANSIT_SHOW) { 3029 return R.anim.dock_bottom_enter; 3030 } 3031 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { 3032 if (transit == TRANSIT_EXIT 3033 || transit == TRANSIT_HIDE) { 3034 return R.anim.dock_right_exit; 3035 } else if (transit == TRANSIT_ENTER 3036 || transit == TRANSIT_SHOW) { 3037 return R.anim.dock_right_enter; 3038 } 3039 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 3040 if (transit == TRANSIT_EXIT 3041 || transit == TRANSIT_HIDE) { 3042 return R.anim.dock_left_exit; 3043 } else if (transit == TRANSIT_ENTER 3044 || transit == TRANSIT_SHOW) { 3045 return R.anim.dock_left_enter; 3046 } 3047 } 3048 } else if (win.getAttrs().type == TYPE_DOCK_DIVIDER) { 3049 return selectDockedDividerAnimationLw(win, transit); 3050 } 3051 3052 if (transit == TRANSIT_PREVIEW_DONE) { 3053 if (win.hasAppShownWindows()) { 3054 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT"); 3055 return com.android.internal.R.anim.app_starting_exit; 3056 } 3057 } else if (win.getAttrs().type == TYPE_DREAM && mDreamingLockscreen 3058 && transit == TRANSIT_ENTER) { 3059 // Special case: we are animating in a dream, while the keyguard 3060 // is shown. We don't want an animation on the dream, because 3061 // we need it shown immediately with the keyguard animating away 3062 // to reveal it. 3063 return -1; 3064 } 3065 3066 return 0; 3067 } 3068 3069 private int selectDockedDividerAnimationLw(WindowState win, int transit) { 3070 int insets = mWindowManagerFuncs.getDockedDividerInsetsLw(); 3071 3072 // If the divider is behind the navigation bar, don't animate. 3073 final Rect frame = win.getFrameLw(); 3074 final boolean behindNavBar = mNavigationBar != null 3075 && ((mNavigationBarPosition == NAV_BAR_BOTTOM 3076 && frame.top + insets >= mNavigationBar.getFrameLw().top) 3077 || (mNavigationBarPosition == NAV_BAR_RIGHT 3078 && frame.left + insets >= mNavigationBar.getFrameLw().left) 3079 || (mNavigationBarPosition == NAV_BAR_LEFT 3080 && frame.right - insets <= mNavigationBar.getFrameLw().right)); 3081 final boolean landscape = frame.height() > frame.width(); 3082 final boolean offscreenLandscape = landscape && (frame.right - insets <= 0 3083 || frame.left + insets >= win.getDisplayFrameLw().right); 3084 final boolean offscreenPortrait = !landscape && (frame.top - insets <= 0 3085 || frame.bottom + insets >= win.getDisplayFrameLw().bottom); 3086 final boolean offscreen = offscreenLandscape || offscreenPortrait; 3087 if (behindNavBar || offscreen) { 3088 return 0; 3089 } 3090 if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) { 3091 return R.anim.fade_in; 3092 } else if (transit == TRANSIT_EXIT) { 3093 return R.anim.fade_out; 3094 } else { 3095 return 0; 3096 } 3097 } 3098 3099 @Override 3100 public void selectRotationAnimationLw(int anim[]) { 3101 if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen=" 3102 + mTopFullscreenOpaqueWindowState + " rotationAnimation=" 3103 + (mTopFullscreenOpaqueWindowState == null ? 3104 "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation)); 3105 if (mTopFullscreenOpaqueWindowState != null) { 3106 int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint(); 3107 if (animationHint < 0 && mTopIsFullscreen) { 3108 animationHint = mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation; 3109 } 3110 switch (animationHint) { 3111 case ROTATION_ANIMATION_CROSSFADE: 3112 case ROTATION_ANIMATION_SEAMLESS: // Crossfade is fallback for seamless. 3113 anim[0] = R.anim.rotation_animation_xfade_exit; 3114 anim[1] = R.anim.rotation_animation_enter; 3115 break; 3116 case ROTATION_ANIMATION_JUMPCUT: 3117 anim[0] = R.anim.rotation_animation_jump_exit; 3118 anim[1] = R.anim.rotation_animation_enter; 3119 break; 3120 case ROTATION_ANIMATION_ROTATE: 3121 default: 3122 anim[0] = anim[1] = 0; 3123 break; 3124 } 3125 } else { 3126 anim[0] = anim[1] = 0; 3127 } 3128 } 3129 3130 @Override 3131 public boolean validateRotationAnimationLw(int exitAnimId, int enterAnimId, 3132 boolean forceDefault) { 3133 switch (exitAnimId) { 3134 case R.anim.rotation_animation_xfade_exit: 3135 case R.anim.rotation_animation_jump_exit: 3136 // These are the only cases that matter. 3137 if (forceDefault) { 3138 return false; 3139 } 3140 int anim[] = new int[2]; 3141 selectRotationAnimationLw(anim); 3142 return (exitAnimId == anim[0] && enterAnimId == anim[1]); 3143 default: 3144 return true; 3145 } 3146 } 3147 3148 @Override 3149 public Animation createHiddenByKeyguardExit(boolean onWallpaper, 3150 boolean goingToNotificationShade) { 3151 if (goingToNotificationShade) { 3152 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in); 3153 } 3154 3155 AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ? 3156 R.anim.lock_screen_behind_enter_wallpaper : 3157 R.anim.lock_screen_behind_enter); 3158 3159 // TODO: Use XML interpolators when we have log interpolators available in XML. 3160 final List<Animation> animations = set.getAnimations(); 3161 for (int i = animations.size() - 1; i >= 0; --i) { 3162 animations.get(i).setInterpolator(mLogDecelerateInterpolator); 3163 } 3164 3165 return set; 3166 } 3167 3168 3169 @Override 3170 public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) { 3171 if (goingToNotificationShade) { 3172 return null; 3173 } else { 3174 return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_wallpaper_exit); 3175 } 3176 } 3177 3178 private static void awakenDreams() { 3179 IDreamManager dreamManager = getDreamManager(); 3180 if (dreamManager != null) { 3181 try { 3182 dreamManager.awaken(); 3183 } catch (RemoteException e) { 3184 // fine, stay asleep then 3185 } 3186 } 3187 } 3188 3189 static IDreamManager getDreamManager() { 3190 return IDreamManager.Stub.asInterface( 3191 ServiceManager.checkService(DreamService.DREAM_SERVICE)); 3192 } 3193 3194 TelecomManager getTelecommService() { 3195 return (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); 3196 } 3197 3198 static IAudioService getAudioService() { 3199 IAudioService audioService = IAudioService.Stub.asInterface( 3200 ServiceManager.checkService(Context.AUDIO_SERVICE)); 3201 if (audioService == null) { 3202 Log.w(TAG, "Unable to find IAudioService interface."); 3203 } 3204 return audioService; 3205 } 3206 3207 boolean keyguardOn() { 3208 return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode(); 3209 } 3210 3211 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = { 3212 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 3213 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, 3214 }; 3215 3216 /** {@inheritDoc} */ 3217 @Override 3218 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { 3219 final boolean keyguardOn = keyguardOn(); 3220 final int keyCode = event.getKeyCode(); 3221 final int repeatCount = event.getRepeatCount(); 3222 final int metaState = event.getMetaState(); 3223 final int flags = event.getFlags(); 3224 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 3225 final boolean canceled = event.isCanceled(); 3226 3227 if (DEBUG_INPUT) { 3228 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" 3229 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed 3230 + " canceled=" + canceled); 3231 } 3232 3233 // If we think we might have a volume down & power key chord on the way 3234 // but we're not sure, then tell the dispatcher to wait a little while and 3235 // try again later before dispatching. 3236 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) { 3237 if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) { 3238 final long now = SystemClock.uptimeMillis(); 3239 final long timeoutTime = mScreenshotChordVolumeDownKeyTime 3240 + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; 3241 if (now < timeoutTime) { 3242 return timeoutTime - now; 3243 } 3244 } 3245 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 3246 && mScreenshotChordVolumeDownKeyConsumed) { 3247 if (!down) { 3248 mScreenshotChordVolumeDownKeyConsumed = false; 3249 } 3250 return -1; 3251 } 3252 } 3253 3254 // Cancel any pending meta actions if we see any other keys being pressed between the down 3255 // of the meta key and its corresponding up. 3256 if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) { 3257 mPendingMetaAction = false; 3258 } 3259 // Any key that is not Alt or Meta cancels Caps Lock combo tracking. 3260 if (mPendingCapsLockToggle && !KeyEvent.isMetaKey(keyCode) && !KeyEvent.isAltKey(keyCode)) { 3261 mPendingCapsLockToggle = false; 3262 } 3263 3264 // First we always handle the home key here, so applications 3265 // can never break it, although if keyguard is on, we do let 3266 // it handle it, because that gives us the correct 5 second 3267 // timeout. 3268 if (keyCode == KeyEvent.KEYCODE_HOME) { 3269 3270 // If we have released the home key, and didn't do anything else 3271 // while it was pressed, then it is time to go home! 3272 if (!down) { 3273 cancelPreloadRecentApps(); 3274 3275 mHomePressed = false; 3276 if (mHomeConsumed) { 3277 mHomeConsumed = false; 3278 return -1; 3279 } 3280 3281 if (canceled) { 3282 Log.i(TAG, "Ignoring HOME; event canceled."); 3283 return -1; 3284 } 3285 3286 // Delay handling home if a double-tap is possible. 3287 if (mDoubleTapOnHomeBehavior != DOUBLE_TAP_HOME_NOTHING) { 3288 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); // just in case 3289 mHomeDoubleTapPending = true; 3290 mHandler.postDelayed(mHomeDoubleTapTimeoutRunnable, 3291 ViewConfiguration.getDoubleTapTimeout()); 3292 return -1; 3293 } 3294 3295 handleShortPressOnHome(); 3296 return -1; 3297 } 3298 3299 // If a system window has focus, then it doesn't make sense 3300 // right now to interact with applications. 3301 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; 3302 if (attrs != null) { 3303 final int type = attrs.type; 3304 if (type == TYPE_KEYGUARD_DIALOG 3305 || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 3306 // the "app" is keyguard, so give it the key 3307 return 0; 3308 } 3309 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; 3310 for (int i=0; i<typeCount; i++) { 3311 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { 3312 // don't do anything, but also don't pass it to the app 3313 return -1; 3314 } 3315 } 3316 } 3317 3318 // Remember that home is pressed and handle special actions. 3319 if (repeatCount == 0) { 3320 mHomePressed = true; 3321 if (mHomeDoubleTapPending) { 3322 mHomeDoubleTapPending = false; 3323 mHandler.removeCallbacks(mHomeDoubleTapTimeoutRunnable); 3324 handleDoubleTapOnHome(); 3325 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI 3326 || mDoubleTapOnHomeBehavior == DOUBLE_TAP_HOME_RECENT_SYSTEM_UI) { 3327 preloadRecentApps(); 3328 } 3329 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { 3330 if (!keyguardOn) { 3331 handleLongPressOnHome(event.getDeviceId()); 3332 } 3333 } 3334 return -1; 3335 } else if (keyCode == KeyEvent.KEYCODE_MENU) { 3336 // Hijack modified menu keys for debugging features 3337 final int chordBug = KeyEvent.META_SHIFT_ON; 3338 3339 if (down && repeatCount == 0) { 3340 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) { 3341 Intent intent = new Intent(Intent.ACTION_BUG_REPORT); 3342 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, 3343 null, null, null, 0, null, null); 3344 return -1; 3345 } 3346 } 3347 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { 3348 if (down) { 3349 if (repeatCount == 0) { 3350 mSearchKeyShortcutPending = true; 3351 mConsumeSearchKeyUp = false; 3352 } 3353 } else { 3354 mSearchKeyShortcutPending = false; 3355 if (mConsumeSearchKeyUp) { 3356 mConsumeSearchKeyUp = false; 3357 return -1; 3358 } 3359 } 3360 return 0; 3361 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { 3362 if (!keyguardOn) { 3363 if (down && repeatCount == 0) { 3364 preloadRecentApps(); 3365 } else if (!down) { 3366 toggleRecentApps(); 3367 } 3368 } 3369 return -1; 3370 } else if (keyCode == KeyEvent.KEYCODE_N && event.isMetaPressed()) { 3371 if (down) { 3372 IStatusBarService service = getStatusBarService(); 3373 if (service != null) { 3374 try { 3375 service.expandNotificationsPanel(); 3376 } catch (RemoteException e) { 3377 // do nothing. 3378 } 3379 } 3380 } 3381 } else if (keyCode == KeyEvent.KEYCODE_S && event.isMetaPressed() 3382 && event.isCtrlPressed()) { 3383 if (down && repeatCount == 0) { 3384 int type = event.isShiftPressed() ? TAKE_SCREENSHOT_SELECTED_REGION 3385 : TAKE_SCREENSHOT_FULLSCREEN; 3386 mScreenshotRunnable.setScreenshotType(type); 3387 mHandler.post(mScreenshotRunnable); 3388 return -1; 3389 } 3390 } else if (keyCode == KeyEvent.KEYCODE_SLASH && event.isMetaPressed()) { 3391 if (down && repeatCount == 0 && !isKeyguardLocked()) { 3392 toggleKeyboardShortcutsMenu(event.getDeviceId()); 3393 } 3394 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) { 3395 if (down) { 3396 if (repeatCount == 0) { 3397 mAssistKeyLongPressed = false; 3398 } else if (repeatCount == 1) { 3399 mAssistKeyLongPressed = true; 3400 if (!keyguardOn) { 3401 launchAssistLongPressAction(); 3402 } 3403 } 3404 } else { 3405 if (mAssistKeyLongPressed) { 3406 mAssistKeyLongPressed = false; 3407 } else { 3408 if (!keyguardOn) { 3409 launchAssistAction(null, event.getDeviceId()); 3410 } 3411 } 3412 } 3413 return -1; 3414 } else if (keyCode == KeyEvent.KEYCODE_VOICE_ASSIST) { 3415 if (!down) { 3416 Intent voiceIntent; 3417 if (!keyguardOn) { 3418 voiceIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH); 3419 } else { 3420 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 3421 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 3422 if (dic != null) { 3423 try { 3424 dic.exitIdle("voice-search"); 3425 } catch (RemoteException e) { 3426 } 3427 } 3428 voiceIntent = new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 3429 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, true); 3430 } 3431 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 3432 } 3433 } else if (keyCode == KeyEvent.KEYCODE_SYSRQ) { 3434 if (down && repeatCount == 0) { 3435 mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN); 3436 mHandler.post(mScreenshotRunnable); 3437 } 3438 return -1; 3439 } else if (keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP 3440 || keyCode == KeyEvent.KEYCODE_BRIGHTNESS_DOWN) { 3441 if (down) { 3442 int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1; 3443 3444 // Disable autobrightness if it's on 3445 int auto = Settings.System.getIntForUser( 3446 mContext.getContentResolver(), 3447 Settings.System.SCREEN_BRIGHTNESS_MODE, 3448 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 3449 UserHandle.USER_CURRENT_OR_SELF); 3450 if (auto != 0) { 3451 Settings.System.putIntForUser(mContext.getContentResolver(), 3452 Settings.System.SCREEN_BRIGHTNESS_MODE, 3453 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, 3454 UserHandle.USER_CURRENT_OR_SELF); 3455 } 3456 3457 int min = mPowerManager.getMinimumScreenBrightnessSetting(); 3458 int max = mPowerManager.getMaximumScreenBrightnessSetting(); 3459 int step = (max - min + BRIGHTNESS_STEPS - 1) / BRIGHTNESS_STEPS * direction; 3460 int brightness = Settings.System.getIntForUser(mContext.getContentResolver(), 3461 Settings.System.SCREEN_BRIGHTNESS, 3462 mPowerManager.getDefaultScreenBrightnessSetting(), 3463 UserHandle.USER_CURRENT_OR_SELF); 3464 brightness += step; 3465 // Make sure we don't go beyond the limits. 3466 brightness = Math.min(max, brightness); 3467 brightness = Math.max(min, brightness); 3468 3469 Settings.System.putIntForUser(mContext.getContentResolver(), 3470 Settings.System.SCREEN_BRIGHTNESS, brightness, 3471 UserHandle.USER_CURRENT_OR_SELF); 3472 startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG), 3473 UserHandle.CURRENT_OR_SELF); 3474 } 3475 return -1; 3476 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP 3477 || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 3478 || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) { 3479 if (mUseTvRouting) { 3480 // On TVs volume keys never go to the foreground app. 3481 dispatchDirectAudioEvent(event); 3482 return -1; 3483 } 3484 } 3485 3486 // Toggle Caps Lock on META-ALT. 3487 boolean actionTriggered = false; 3488 if (KeyEvent.isModifierKey(keyCode)) { 3489 if (!mPendingCapsLockToggle) { 3490 // Start tracking meta state for combo. 3491 mInitialMetaState = mMetaState; 3492 mPendingCapsLockToggle = true; 3493 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3494 int altOnMask = mMetaState & KeyEvent.META_ALT_MASK; 3495 int metaOnMask = mMetaState & KeyEvent.META_META_MASK; 3496 3497 // Check for Caps Lock toggle 3498 if ((metaOnMask != 0) && (altOnMask != 0)) { 3499 // Check if nothing else is pressed 3500 if (mInitialMetaState == (mMetaState ^ (altOnMask | metaOnMask))) { 3501 // Handle Caps Lock Toggle 3502 mInputManagerInternal.toggleCapsLock(event.getDeviceId()); 3503 actionTriggered = true; 3504 } 3505 } 3506 3507 // Always stop tracking when key goes up. 3508 mPendingCapsLockToggle = false; 3509 } 3510 } 3511 // Store current meta state to be able to evaluate it later. 3512 mMetaState = metaState; 3513 3514 if (actionTriggered) { 3515 return -1; 3516 } 3517 3518 if (KeyEvent.isMetaKey(keyCode)) { 3519 if (down) { 3520 mPendingMetaAction = true; 3521 } else if (mPendingMetaAction) { 3522 launchAssistAction(Intent.EXTRA_ASSIST_INPUT_HINT_KEYBOARD, event.getDeviceId()); 3523 } 3524 return -1; 3525 } 3526 3527 // Shortcuts are invoked through Search+key, so intercept those here 3528 // Any printing key that is chorded with Search should be consumed 3529 // even if no shortcut was invoked. This prevents text from being 3530 // inadvertently inserted when using a keyboard that has built-in macro 3531 // shortcut keys (that emit Search+x) and some of them are not registered. 3532 if (mSearchKeyShortcutPending) { 3533 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3534 if (kcm.isPrintingKey(keyCode)) { 3535 mConsumeSearchKeyUp = true; 3536 mSearchKeyShortcutPending = false; 3537 if (down && repeatCount == 0 && !keyguardOn) { 3538 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); 3539 if (shortcutIntent != null) { 3540 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3541 try { 3542 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3543 dismissKeyboardShortcutsMenu(); 3544 } catch (ActivityNotFoundException ex) { 3545 Slog.w(TAG, "Dropping shortcut key combination because " 3546 + "the activity to which it is registered was not found: " 3547 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex); 3548 } 3549 } else { 3550 Slog.i(TAG, "Dropping unregistered shortcut key combination: " 3551 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode)); 3552 } 3553 } 3554 return -1; 3555 } 3556 } 3557 3558 // Invoke shortcuts using Meta. 3559 if (down && repeatCount == 0 && !keyguardOn 3560 && (metaState & KeyEvent.META_META_ON) != 0) { 3561 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3562 if (kcm.isPrintingKey(keyCode)) { 3563 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, 3564 metaState & ~(KeyEvent.META_META_ON 3565 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON)); 3566 if (shortcutIntent != null) { 3567 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3568 try { 3569 startActivityAsUser(shortcutIntent, UserHandle.CURRENT); 3570 dismissKeyboardShortcutsMenu(); 3571 } catch (ActivityNotFoundException ex) { 3572 Slog.w(TAG, "Dropping shortcut key combination because " 3573 + "the activity to which it is registered was not found: " 3574 + "META+" + KeyEvent.keyCodeToString(keyCode), ex); 3575 } 3576 return -1; 3577 } 3578 } 3579 } 3580 3581 // Handle application launch keys. 3582 if (down && repeatCount == 0 && !keyguardOn) { 3583 String category = sApplicationLaunchKeyCategories.get(keyCode); 3584 if (category != null) { 3585 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); 3586 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3587 try { 3588 startActivityAsUser(intent, UserHandle.CURRENT); 3589 dismissKeyboardShortcutsMenu(); 3590 } catch (ActivityNotFoundException ex) { 3591 Slog.w(TAG, "Dropping application launch key because " 3592 + "the activity to which it is registered was not found: " 3593 + "keyCode=" + keyCode + ", category=" + category, ex); 3594 } 3595 return -1; 3596 } 3597 } 3598 3599 // Display task switcher for ALT-TAB. 3600 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) { 3601 if (mRecentAppsHeldModifiers == 0 && !keyguardOn && isUserSetupComplete()) { 3602 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; 3603 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)) { 3604 mRecentAppsHeldModifiers = shiftlessModifiers; 3605 showRecentApps(true, false); 3606 return -1; 3607 } 3608 } 3609 } else if (!down && mRecentAppsHeldModifiers != 0 3610 && (metaState & mRecentAppsHeldModifiers) == 0) { 3611 mRecentAppsHeldModifiers = 0; 3612 hideRecentApps(true, false); 3613 } 3614 3615 // Handle input method switching. 3616 if (down && repeatCount == 0 3617 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3618 || (keyCode == KeyEvent.KEYCODE_SPACE 3619 && (metaState & KeyEvent.META_META_MASK) != 0))) { 3620 final boolean forwardDirection = (metaState & KeyEvent.META_SHIFT_MASK) == 0; 3621 mWindowManagerFuncs.switchInputMethod(forwardDirection); 3622 return -1; 3623 } 3624 if (mLanguageSwitchKeyPressed && !down 3625 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 3626 || keyCode == KeyEvent.KEYCODE_SPACE)) { 3627 mLanguageSwitchKeyPressed = false; 3628 return -1; 3629 } 3630 3631 if (isValidGlobalKey(keyCode) 3632 && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) { 3633 return -1; 3634 } 3635 3636 if (down) { 3637 long shortcutCode = keyCode; 3638 if (event.isCtrlPressed()) { 3639 shortcutCode |= ((long) KeyEvent.META_CTRL_ON) << Integer.SIZE; 3640 } 3641 3642 if (event.isAltPressed()) { 3643 shortcutCode |= ((long) KeyEvent.META_ALT_ON) << Integer.SIZE; 3644 } 3645 3646 if (event.isShiftPressed()) { 3647 shortcutCode |= ((long) KeyEvent.META_SHIFT_ON) << Integer.SIZE; 3648 } 3649 3650 if (event.isMetaPressed()) { 3651 shortcutCode |= ((long) KeyEvent.META_META_ON) << Integer.SIZE; 3652 } 3653 3654 IShortcutService shortcutService = mShortcutKeyServices.get(shortcutCode); 3655 if (shortcutService != null) { 3656 try { 3657 if (isUserSetupComplete()) { 3658 shortcutService.notifyShortcutKeyPressed(shortcutCode); 3659 } 3660 } catch (RemoteException e) { 3661 mShortcutKeyServices.delete(shortcutCode); 3662 } 3663 return -1; 3664 } 3665 } 3666 3667 // Reserve all the META modifier combos for system behavior 3668 if ((metaState & KeyEvent.META_META_ON) != 0) { 3669 return -1; 3670 } 3671 3672 // Let the application handle the key. 3673 return 0; 3674 } 3675 3676 /** {@inheritDoc} */ 3677 @Override 3678 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) { 3679 // Note: This method is only called if the initial down was unhandled. 3680 if (DEBUG_INPUT) { 3681 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction() 3682 + ", flags=" + event.getFlags() 3683 + ", keyCode=" + event.getKeyCode() 3684 + ", scanCode=" + event.getScanCode() 3685 + ", metaState=" + event.getMetaState() 3686 + ", repeatCount=" + event.getRepeatCount() 3687 + ", policyFlags=" + policyFlags); 3688 } 3689 3690 KeyEvent fallbackEvent = null; 3691 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3692 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 3693 final int keyCode = event.getKeyCode(); 3694 final int metaState = event.getMetaState(); 3695 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN 3696 && event.getRepeatCount() == 0; 3697 3698 // Check for fallback actions specified by the key character map. 3699 final FallbackAction fallbackAction; 3700 if (initialDown) { 3701 fallbackAction = kcm.getFallbackAction(keyCode, metaState); 3702 } else { 3703 fallbackAction = mFallbackActions.get(keyCode); 3704 } 3705 3706 if (fallbackAction != null) { 3707 if (DEBUG_INPUT) { 3708 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode 3709 + " metaState=" + Integer.toHexString(fallbackAction.metaState)); 3710 } 3711 3712 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; 3713 fallbackEvent = KeyEvent.obtain( 3714 event.getDownTime(), event.getEventTime(), 3715 event.getAction(), fallbackAction.keyCode, 3716 event.getRepeatCount(), fallbackAction.metaState, 3717 event.getDeviceId(), event.getScanCode(), 3718 flags, event.getSource(), null); 3719 3720 if (!interceptFallback(win, fallbackEvent, policyFlags)) { 3721 fallbackEvent.recycle(); 3722 fallbackEvent = null; 3723 } 3724 3725 if (initialDown) { 3726 mFallbackActions.put(keyCode, fallbackAction); 3727 } else if (event.getAction() == KeyEvent.ACTION_UP) { 3728 mFallbackActions.remove(keyCode); 3729 fallbackAction.recycle(); 3730 } 3731 } 3732 } 3733 3734 if (DEBUG_INPUT) { 3735 if (fallbackEvent == null) { 3736 Slog.d(TAG, "No fallback."); 3737 } else { 3738 Slog.d(TAG, "Performing fallback: " + fallbackEvent); 3739 } 3740 } 3741 return fallbackEvent; 3742 } 3743 3744 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) { 3745 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags); 3746 if ((actions & ACTION_PASS_TO_USER) != 0) { 3747 long delayMillis = interceptKeyBeforeDispatching( 3748 win, fallbackEvent, policyFlags); 3749 if (delayMillis == 0) { 3750 return true; 3751 } 3752 } 3753 return false; 3754 } 3755 3756 @Override 3757 public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService) 3758 throws RemoteException { 3759 synchronized (mLock) { 3760 IShortcutService service = mShortcutKeyServices.get(shortcutCode); 3761 if (service != null && service.asBinder().pingBinder()) { 3762 throw new RemoteException("Key already exists."); 3763 } 3764 3765 mShortcutKeyServices.put(shortcutCode, shortcutService); 3766 } 3767 } 3768 3769 @Override 3770 public void onKeyguardOccludedChangedLw(boolean occluded) { 3771 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 3772 mPendingKeyguardOccluded = occluded; 3773 mKeyguardOccludedChanged = true; 3774 } else { 3775 setKeyguardOccludedLw(occluded); 3776 } 3777 } 3778 3779 private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) { 3780 if (mKeyguardOccludedChanged) { 3781 if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded=" 3782 + mPendingKeyguardOccluded); 3783 mKeyguardOccludedChanged = false; 3784 if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) { 3785 return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER; 3786 } 3787 } 3788 if (AppTransition.isKeyguardGoingAwayTransit(transit)) { 3789 if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation"); 3790 final long startTime = anim != null 3791 ? SystemClock.uptimeMillis() + anim.getStartOffset() 3792 : SystemClock.uptimeMillis(); 3793 final long duration = anim != null 3794 ? anim.getDuration() 3795 : 0; 3796 startKeyguardExitAnimation(startTime, duration); 3797 } 3798 return 0; 3799 } 3800 3801 private void launchAssistLongPressAction() { 3802 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 3803 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 3804 3805 // launch the search activity 3806 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS); 3807 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 3808 try { 3809 // TODO: This only stops the factory-installed search manager. 3810 // Need to formalize an API to handle others 3811 SearchManager searchManager = getSearchManager(); 3812 if (searchManager != null) { 3813 searchManager.stopSearch(); 3814 } 3815 startActivityAsUser(intent, UserHandle.CURRENT); 3816 } catch (ActivityNotFoundException e) { 3817 Slog.w(TAG, "No activity to handle assist long press action.", e); 3818 } 3819 } 3820 3821 private void launchAssistAction(String hint, int deviceId) { 3822 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 3823 if (!isUserSetupComplete()) { 3824 // Disable opening assist window during setup 3825 return; 3826 } 3827 Bundle args = null; 3828 if (deviceId > Integer.MIN_VALUE) { 3829 args = new Bundle(); 3830 args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, deviceId); 3831 } 3832 if ((mContext.getResources().getConfiguration().uiMode 3833 & Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) { 3834 // On TV, use legacy handling until assistants are implemented in the proper way. 3835 ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) 3836 .launchLegacyAssist(hint, UserHandle.myUserId(), args); 3837 } else { 3838 if (hint != null) { 3839 if (args == null) { 3840 args = new Bundle(); 3841 } 3842 args.putBoolean(hint, true); 3843 } 3844 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3845 if (statusbar != null) { 3846 statusbar.startAssist(args); 3847 } 3848 } 3849 } 3850 3851 private void startActivityAsUser(Intent intent, UserHandle handle) { 3852 if (isUserSetupComplete()) { 3853 mContext.startActivityAsUser(intent, handle); 3854 } else { 3855 Slog.i(TAG, "Not starting activity because user setup is in progress: " + intent); 3856 } 3857 } 3858 3859 private SearchManager getSearchManager() { 3860 if (mSearchManager == null) { 3861 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); 3862 } 3863 return mSearchManager; 3864 } 3865 3866 private void preloadRecentApps() { 3867 mPreloadedRecentApps = true; 3868 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3869 if (statusbar != null) { 3870 statusbar.preloadRecentApps(); 3871 } 3872 } 3873 3874 private void cancelPreloadRecentApps() { 3875 if (mPreloadedRecentApps) { 3876 mPreloadedRecentApps = false; 3877 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3878 if (statusbar != null) { 3879 statusbar.cancelPreloadRecentApps(); 3880 } 3881 } 3882 } 3883 3884 private void toggleRecentApps() { 3885 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3886 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3887 if (statusbar != null) { 3888 statusbar.toggleRecentApps(); 3889 } 3890 } 3891 3892 @Override 3893 public void showRecentApps(boolean fromHome) { 3894 mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS); 3895 mHandler.obtainMessage(MSG_DISPATCH_SHOW_RECENTS, fromHome ? 1 : 0, 0).sendToTarget(); 3896 } 3897 3898 private void showRecentApps(boolean triggeredFromAltTab, boolean fromHome) { 3899 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3900 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3901 if (statusbar != null) { 3902 statusbar.showRecentApps(triggeredFromAltTab, fromHome); 3903 } 3904 } 3905 3906 private void toggleKeyboardShortcutsMenu(int deviceId) { 3907 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3908 if (statusbar != null) { 3909 statusbar.toggleKeyboardShortcutsMenu(deviceId); 3910 } 3911 } 3912 3913 private void dismissKeyboardShortcutsMenu() { 3914 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3915 if (statusbar != null) { 3916 statusbar.dismissKeyboardShortcutsMenu(); 3917 } 3918 } 3919 3920 private void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHome) { 3921 mPreloadedRecentApps = false; // preloading no longer needs to be canceled 3922 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 3923 if (statusbar != null) { 3924 statusbar.hideRecentApps(triggeredFromAltTab, triggeredFromHome); 3925 } 3926 } 3927 3928 void launchHomeFromHotKey() { 3929 launchHomeFromHotKey(true /* awakenFromDreams */, true /*respectKeyguard*/); 3930 } 3931 3932 /** 3933 * A home key -> launch home action was detected. Take the appropriate action 3934 * given the situation with the keyguard. 3935 */ 3936 void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) { 3937 if (respectKeyguard) { 3938 if (isKeyguardShowingAndNotOccluded()) { 3939 // don't launch home if keyguard showing 3940 return; 3941 } 3942 3943 if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) { 3944 // when in keyguard restricted mode, must first verify unlock 3945 // before launching home 3946 mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() { 3947 @Override 3948 public void onKeyguardExitResult(boolean success) { 3949 if (success) { 3950 try { 3951 ActivityManager.getService().stopAppSwitches(); 3952 } catch (RemoteException e) { 3953 } 3954 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 3955 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); 3956 } 3957 } 3958 }); 3959 return; 3960 } 3961 } 3962 3963 // no keyguard stuff to worry about, just launch home! 3964 try { 3965 ActivityManager.getService().stopAppSwitches(); 3966 } catch (RemoteException e) { 3967 } 3968 if (mRecentsVisible) { 3969 // Hide Recents and notify it to launch Home 3970 if (awakenFromDreams) { 3971 awakenDreams(); 3972 } 3973 hideRecentApps(false, true); 3974 } else { 3975 // Otherwise, just launch Home 3976 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 3977 startDockOrHome(true /*fromHomeKey*/, awakenFromDreams); 3978 } 3979 } 3980 3981 private final Runnable mClearHideNavigationFlag = new Runnable() { 3982 @Override 3983 public void run() { 3984 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 3985 // Clear flags. 3986 mForceClearedSystemUiFlags &= 3987 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 3988 } 3989 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 3990 } 3991 }; 3992 3993 /** 3994 * Input handler used while nav bar is hidden. Captures any touch on the screen, 3995 * to determine when the nav bar should be shown and prevent applications from 3996 * receiving those touches. 3997 */ 3998 final class HideNavInputEventReceiver extends InputEventReceiver { 3999 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) { 4000 super(inputChannel, looper); 4001 } 4002 4003 @Override 4004 public void onInputEvent(InputEvent event) { 4005 boolean handled = false; 4006 try { 4007 if (event instanceof MotionEvent 4008 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 4009 final MotionEvent motionEvent = (MotionEvent)event; 4010 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 4011 // When the user taps down, we re-show the nav bar. 4012 boolean changed = false; 4013 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 4014 if (mInputConsumer == null) { 4015 return; 4016 } 4017 // Any user activity always causes us to show the 4018 // navigation controls, if they had been hidden. 4019 // We also clear the low profile and only content 4020 // flags so that tapping on the screen will atomically 4021 // restore all currently hidden screen decorations. 4022 int newVal = mResettingSystemUiFlags | 4023 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | 4024 View.SYSTEM_UI_FLAG_LOW_PROFILE | 4025 View.SYSTEM_UI_FLAG_FULLSCREEN; 4026 if (mResettingSystemUiFlags != newVal) { 4027 mResettingSystemUiFlags = newVal; 4028 changed = true; 4029 } 4030 // We don't allow the system's nav bar to be hidden 4031 // again for 1 second, to prevent applications from 4032 // spamming us and keeping it from being shown. 4033 newVal = mForceClearedSystemUiFlags | 4034 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 4035 if (mForceClearedSystemUiFlags != newVal) { 4036 mForceClearedSystemUiFlags = newVal; 4037 changed = true; 4038 mHandler.postDelayed(mClearHideNavigationFlag, 1000); 4039 } 4040 } 4041 if (changed) { 4042 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 4043 } 4044 } 4045 } 4046 } finally { 4047 finishInputEvent(event, handled); 4048 } 4049 } 4050 } 4051 4052 @Override 4053 public void setRecentsVisibilityLw(boolean visible) { 4054 mRecentsVisible = visible; 4055 } 4056 4057 @Override 4058 public void setTvPipVisibilityLw(boolean visible) { 4059 mTvPictureInPictureVisible = visible; 4060 } 4061 4062 @Override 4063 public int adjustSystemUiVisibilityLw(int visibility) { 4064 mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); 4065 mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); 4066 4067 // Reset any bits in mForceClearingStatusBarVisibility that 4068 // are now clear. 4069 mResettingSystemUiFlags &= visibility; 4070 // Clear any bits in the new visibility that are currently being 4071 // force cleared, before reporting it. 4072 return visibility & ~mResettingSystemUiFlags 4073 & ~mForceClearedSystemUiFlags; 4074 } 4075 4076 @Override 4077 public boolean getInsetHintLw(WindowManager.LayoutParams attrs, Rect taskBounds, 4078 int displayRotation, int displayWidth, int displayHeight, Rect outContentInsets, 4079 Rect outStableInsets, Rect outOutsets) { 4080 final int fl = PolicyControl.getWindowFlags(null, attrs); 4081 final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs); 4082 final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility); 4083 4084 final boolean useOutsets = outOutsets != null && shouldUseOutsets(attrs, fl); 4085 if (useOutsets) { 4086 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 4087 if (outset > 0) { 4088 if (displayRotation == Surface.ROTATION_0) { 4089 outOutsets.bottom += outset; 4090 } else if (displayRotation == Surface.ROTATION_90) { 4091 outOutsets.right += outset; 4092 } else if (displayRotation == Surface.ROTATION_180) { 4093 outOutsets.top += outset; 4094 } else if (displayRotation == Surface.ROTATION_270) { 4095 outOutsets.left += outset; 4096 } 4097 } 4098 } 4099 4100 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 4101 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 4102 int availRight, availBottom; 4103 if (canHideNavigationBar() && 4104 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) { 4105 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4106 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4107 } else { 4108 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth; 4109 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight; 4110 } 4111 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 4112 if ((fl & FLAG_FULLSCREEN) != 0) { 4113 outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop, 4114 availRight - mStableFullscreenRight, 4115 availBottom - mStableFullscreenBottom); 4116 } else { 4117 outContentInsets.set(mStableLeft, mStableTop, 4118 availRight - mStableRight, availBottom - mStableBottom); 4119 } 4120 } else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) { 4121 outContentInsets.setEmpty(); 4122 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN 4123 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) { 4124 outContentInsets.set(mCurLeft, mCurTop, 4125 availRight - mCurRight, availBottom - mCurBottom); 4126 } else { 4127 outContentInsets.set(mCurLeft, mCurTop, 4128 availRight - mCurRight, availBottom - mCurBottom); 4129 } 4130 4131 outStableInsets.set(mStableLeft, mStableTop, 4132 availRight - mStableRight, availBottom - mStableBottom); 4133 if (taskBounds != null) { 4134 calculateRelevantTaskInsets(taskBounds, outContentInsets, 4135 displayWidth, displayHeight); 4136 calculateRelevantTaskInsets(taskBounds, outStableInsets, 4137 displayWidth, displayHeight); 4138 } 4139 return mForceShowSystemBars; 4140 } 4141 outContentInsets.setEmpty(); 4142 outStableInsets.setEmpty(); 4143 return mForceShowSystemBars; 4144 } 4145 4146 /** 4147 * For any given task bounds, the insets relevant for these bounds given the insets relevant 4148 * for the entire display. 4149 */ 4150 private void calculateRelevantTaskInsets(Rect taskBounds, Rect inOutInsets, int displayWidth, 4151 int displayHeight) { 4152 mTmpRect.set(0, 0, displayWidth, displayHeight); 4153 mTmpRect.inset(inOutInsets); 4154 mTmpRect.intersect(taskBounds); 4155 int leftInset = mTmpRect.left - taskBounds.left; 4156 int topInset = mTmpRect.top - taskBounds.top; 4157 int rightInset = taskBounds.right - mTmpRect.right; 4158 int bottomInset = taskBounds.bottom - mTmpRect.bottom; 4159 inOutInsets.set(leftInset, topInset, rightInset, bottomInset); 4160 } 4161 4162 private boolean shouldUseOutsets(WindowManager.LayoutParams attrs, int fl) { 4163 return attrs.type == TYPE_WALLPAPER || (fl & (WindowManager.LayoutParams.FLAG_FULLSCREEN 4164 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN)) != 0; 4165 } 4166 4167 /** {@inheritDoc} */ 4168 @Override 4169 public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight, 4170 int displayRotation, int uiMode) { 4171 mDisplayRotation = displayRotation; 4172 final int overscanLeft, overscanTop, overscanRight, overscanBottom; 4173 if (isDefaultDisplay) { 4174 switch (displayRotation) { 4175 case Surface.ROTATION_90: 4176 overscanLeft = mOverscanTop; 4177 overscanTop = mOverscanRight; 4178 overscanRight = mOverscanBottom; 4179 overscanBottom = mOverscanLeft; 4180 break; 4181 case Surface.ROTATION_180: 4182 overscanLeft = mOverscanRight; 4183 overscanTop = mOverscanBottom; 4184 overscanRight = mOverscanLeft; 4185 overscanBottom = mOverscanTop; 4186 break; 4187 case Surface.ROTATION_270: 4188 overscanLeft = mOverscanBottom; 4189 overscanTop = mOverscanLeft; 4190 overscanRight = mOverscanTop; 4191 overscanBottom = mOverscanRight; 4192 break; 4193 default: 4194 overscanLeft = mOverscanLeft; 4195 overscanTop = mOverscanTop; 4196 overscanRight = mOverscanRight; 4197 overscanBottom = mOverscanBottom; 4198 break; 4199 } 4200 } else { 4201 overscanLeft = 0; 4202 overscanTop = 0; 4203 overscanRight = 0; 4204 overscanBottom = 0; 4205 } 4206 mOverscanScreenLeft = mRestrictedOverscanScreenLeft = 0; 4207 mOverscanScreenTop = mRestrictedOverscanScreenTop = 0; 4208 mOverscanScreenWidth = mRestrictedOverscanScreenWidth = displayWidth; 4209 mOverscanScreenHeight = mRestrictedOverscanScreenHeight = displayHeight; 4210 mSystemLeft = 0; 4211 mSystemTop = 0; 4212 mSystemRight = displayWidth; 4213 mSystemBottom = displayHeight; 4214 mUnrestrictedScreenLeft = overscanLeft; 4215 mUnrestrictedScreenTop = overscanTop; 4216 mUnrestrictedScreenWidth = displayWidth - overscanLeft - overscanRight; 4217 mUnrestrictedScreenHeight = displayHeight - overscanTop - overscanBottom; 4218 mRestrictedScreenLeft = mUnrestrictedScreenLeft; 4219 mRestrictedScreenTop = mUnrestrictedScreenTop; 4220 mRestrictedScreenWidth = mSystemGestures.screenWidth = mUnrestrictedScreenWidth; 4221 mRestrictedScreenHeight = mSystemGestures.screenHeight = mUnrestrictedScreenHeight; 4222 mDockLeft = mContentLeft = mVoiceContentLeft = mStableLeft = mStableFullscreenLeft 4223 = mCurLeft = mUnrestrictedScreenLeft; 4224 mDockTop = mContentTop = mVoiceContentTop = mStableTop = mStableFullscreenTop 4225 = mCurTop = mUnrestrictedScreenTop; 4226 mDockRight = mContentRight = mVoiceContentRight = mStableRight = mStableFullscreenRight 4227 = mCurRight = displayWidth - overscanRight; 4228 mDockBottom = mContentBottom = mVoiceContentBottom = mStableBottom = mStableFullscreenBottom 4229 = mCurBottom = displayHeight - overscanBottom; 4230 mDockLayer = 0x10000000; 4231 mStatusBarLayer = -1; 4232 4233 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight) 4234 final Rect pf = mTmpParentFrame; 4235 final Rect df = mTmpDisplayFrame; 4236 final Rect of = mTmpOverscanFrame; 4237 final Rect vf = mTmpVisibleFrame; 4238 final Rect dcf = mTmpDecorFrame; 4239 pf.left = df.left = of.left = vf.left = mDockLeft; 4240 pf.top = df.top = of.top = vf.top = mDockTop; 4241 pf.right = df.right = of.right = vf.right = mDockRight; 4242 pf.bottom = df.bottom = of.bottom = vf.bottom = mDockBottom; 4243 dcf.setEmpty(); // Decor frame N/A for system bars. 4244 4245 if (isDefaultDisplay) { 4246 // For purposes of putting out fake window up to steal focus, we will 4247 // drive nav being hidden only by whether it is requested. 4248 final int sysui = mLastSystemUiFlags; 4249 boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; 4250 boolean navTranslucent = (sysui 4251 & (View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT)) != 0; 4252 boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 4253 boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 4254 boolean navAllowedHidden = immersive || immersiveSticky; 4255 navTranslucent &= !immersiveSticky; // transient trumps translucent 4256 boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded; 4257 if (!isKeyguardShowing) { 4258 navTranslucent &= areTranslucentBarsAllowed(); 4259 } 4260 boolean statusBarExpandedNotKeyguard = !isKeyguardShowing && mStatusBar != null 4261 && mStatusBar.getAttrs().height == MATCH_PARENT 4262 && mStatusBar.getAttrs().width == MATCH_PARENT; 4263 4264 // When the navigation bar isn't visible, we put up a fake 4265 // input window to catch all touch events. This way we can 4266 // detect when the user presses anywhere to bring back the nav 4267 // bar and ensure the application doesn't see the event. 4268 if (navVisible || navAllowedHidden) { 4269 if (mInputConsumer != null) { 4270 mHandler.sendMessage( 4271 mHandler.obtainMessage(MSG_DISPOSE_INPUT_CONSUMER, mInputConsumer)); 4272 mInputConsumer = null; 4273 } 4274 } else if (mInputConsumer == null) { 4275 mInputConsumer = mWindowManagerFuncs.createInputConsumer(mHandler.getLooper(), 4276 INPUT_CONSUMER_NAVIGATION, 4277 (channel, looper) -> new HideNavInputEventReceiver(channel, looper)); 4278 } 4279 4280 // For purposes of positioning and showing the nav bar, if we have 4281 // decided that it can't be hidden (because of the screen aspect ratio), 4282 // then take that into account. 4283 navVisible |= !canHideNavigationBar(); 4284 4285 boolean updateSysUiVisibility = layoutNavigationBar(displayWidth, displayHeight, 4286 displayRotation, uiMode, overscanLeft, overscanRight, overscanBottom, dcf, navVisible, navTranslucent, 4287 navAllowedHidden, statusBarExpandedNotKeyguard); 4288 if (DEBUG_LAYOUT) Slog.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)", 4289 mDockLeft, mDockTop, mDockRight, mDockBottom)); 4290 updateSysUiVisibility |= layoutStatusBar(pf, df, of, vf, dcf, sysui, isKeyguardShowing); 4291 if (updateSysUiVisibility) { 4292 updateSystemUiVisibilityLw(); 4293 } 4294 } 4295 } 4296 4297 private boolean layoutStatusBar(Rect pf, Rect df, Rect of, Rect vf, Rect dcf, int sysui, 4298 boolean isKeyguardShowing) { 4299 // decide where the status bar goes ahead of time 4300 if (mStatusBar != null) { 4301 // apply any navigation bar insets 4302 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4303 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4304 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; 4305 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight 4306 + mUnrestrictedScreenTop; 4307 vf.left = mStableLeft; 4308 vf.top = mStableTop; 4309 vf.right = mStableRight; 4310 vf.bottom = mStableBottom; 4311 4312 mStatusBarLayer = mStatusBar.getSurfaceLayer(); 4313 4314 // Let the status bar determine its size. 4315 mStatusBar.computeFrameLw(pf /* parentFrame */, df /* displayFrame */, 4316 vf /* overlayFrame */, vf /* contentFrame */, vf /* visibleFrame */, 4317 dcf /* decorFrame */, vf /* stableFrame */, vf /* outsetFrame */); 4318 4319 // For layout, the status bar is always at the top with our fixed height. 4320 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; 4321 4322 boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0; 4323 boolean statusBarTranslucent = (sysui 4324 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0; 4325 if (!isKeyguardShowing) { 4326 statusBarTranslucent &= areTranslucentBarsAllowed(); 4327 } 4328 4329 // If the status bar is hidden, we don't want to cause 4330 // windows behind it to scroll. 4331 if (mStatusBar.isVisibleLw() && !statusBarTransient) { 4332 // Status bar may go away, so the screen area it occupies 4333 // is available to apps but just covering them when the 4334 // status bar is visible. 4335 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight; 4336 4337 mContentTop = mVoiceContentTop = mCurTop = mDockTop; 4338 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; 4339 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; 4340 mContentRight = mVoiceContentRight = mCurRight = mDockRight; 4341 4342 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar: " + 4343 String.format( 4344 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]", 4345 mDockLeft, mDockTop, mDockRight, mDockBottom, 4346 mContentLeft, mContentTop, mContentRight, mContentBottom, 4347 mCurLeft, mCurTop, mCurRight, mCurBottom)); 4348 } 4349 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw() 4350 && !statusBarTransient && !statusBarTranslucent 4351 && !mStatusBarController.wasRecentlyTranslucent()) { 4352 // If the opaque status bar is currently requested to be visible, 4353 // and not in the process of animating on or off, then 4354 // we can tell the app that it is covered by it. 4355 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight; 4356 } 4357 if (mStatusBarController.checkHiddenLw()) { 4358 return true; 4359 } 4360 } 4361 return false; 4362 } 4363 4364 private boolean layoutNavigationBar(int displayWidth, int displayHeight, int displayRotation, 4365 int uiMode, int overscanLeft, int overscanRight, int overscanBottom, Rect dcf, 4366 boolean navVisible, boolean navTranslucent, boolean navAllowedHidden, 4367 boolean statusBarExpandedNotKeyguard) { 4368 if (mNavigationBar != null) { 4369 boolean transientNavBarShowing = mNavigationBarController.isTransientShowing(); 4370 // Force the navigation bar to its appropriate place and 4371 // size. We need to do this directly, instead of relying on 4372 // it to bubble up from the nav bar, because this needs to 4373 // change atomically with screen rotations. 4374 mNavigationBarPosition = navigationBarPosition(displayWidth, displayHeight, 4375 displayRotation); 4376 if (mNavigationBarPosition == NAV_BAR_BOTTOM) { 4377 // It's a system nav bar or a portrait screen; nav bar goes on bottom. 4378 int top = displayHeight - overscanBottom 4379 - getNavigationBarHeight(displayRotation, uiMode); 4380 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom); 4381 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top; 4382 if (transientNavBarShowing) { 4383 mNavigationBarController.setBarShowingLw(true); 4384 } else if (navVisible) { 4385 mNavigationBarController.setBarShowingLw(true); 4386 mDockBottom = mTmpNavigationFrame.top; 4387 mRestrictedScreenHeight = mDockBottom - mRestrictedScreenTop; 4388 mRestrictedOverscanScreenHeight = mDockBottom - mRestrictedOverscanScreenTop; 4389 } else { 4390 // We currently want to hide the navigation UI - unless we expanded the status 4391 // bar. 4392 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4393 } 4394 if (navVisible && !navTranslucent && !navAllowedHidden 4395 && !mNavigationBar.isAnimatingLw() 4396 && !mNavigationBarController.wasRecentlyTranslucent()) { 4397 // If the opaque nav bar is currently requested to be visible, 4398 // and not in the process of animating on or off, then 4399 // we can tell the app that it is covered by it. 4400 mSystemBottom = mTmpNavigationFrame.top; 4401 } 4402 } else if (mNavigationBarPosition == NAV_BAR_RIGHT) { 4403 // Landscape screen; nav bar goes to the right. 4404 int left = displayWidth - overscanRight 4405 - getNavigationBarWidth(displayRotation, uiMode); 4406 mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight); 4407 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left; 4408 if (transientNavBarShowing) { 4409 mNavigationBarController.setBarShowingLw(true); 4410 } else if (navVisible) { 4411 mNavigationBarController.setBarShowingLw(true); 4412 mDockRight = mTmpNavigationFrame.left; 4413 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; 4414 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; 4415 } else { 4416 // We currently want to hide the navigation UI - unless we expanded the status 4417 // bar. 4418 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4419 } 4420 if (navVisible && !navTranslucent && !navAllowedHidden 4421 && !mNavigationBar.isAnimatingLw() 4422 && !mNavigationBarController.wasRecentlyTranslucent()) { 4423 // If the nav bar is currently requested to be visible, 4424 // and not in the process of animating on or off, then 4425 // we can tell the app that it is covered by it. 4426 mSystemRight = mTmpNavigationFrame.left; 4427 } 4428 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 4429 // Seascape screen; nav bar goes to the left. 4430 int right = overscanLeft + getNavigationBarWidth(displayRotation, uiMode); 4431 mTmpNavigationFrame.set(overscanLeft, 0, right, displayHeight); 4432 mStableLeft = mStableFullscreenLeft = mTmpNavigationFrame.right; 4433 if (transientNavBarShowing) { 4434 mNavigationBarController.setBarShowingLw(true); 4435 } else if (navVisible) { 4436 mNavigationBarController.setBarShowingLw(true); 4437 mDockLeft = mTmpNavigationFrame.right; 4438 // TODO: not so sure about those: 4439 mRestrictedScreenLeft = mRestrictedOverscanScreenLeft = mDockLeft; 4440 mRestrictedScreenWidth = mDockRight - mRestrictedScreenLeft; 4441 mRestrictedOverscanScreenWidth = mDockRight - mRestrictedOverscanScreenLeft; 4442 } else { 4443 // We currently want to hide the navigation UI - unless we expanded the status 4444 // bar. 4445 mNavigationBarController.setBarShowingLw(statusBarExpandedNotKeyguard); 4446 } 4447 if (navVisible && !navTranslucent && !navAllowedHidden 4448 && !mNavigationBar.isAnimatingLw() 4449 && !mNavigationBarController.wasRecentlyTranslucent()) { 4450 // If the nav bar is currently requested to be visible, 4451 // and not in the process of animating on or off, then 4452 // we can tell the app that it is covered by it. 4453 mSystemLeft = mTmpNavigationFrame.right; 4454 } 4455 } 4456 // Make sure the content and current rectangles are updated to 4457 // account for the restrictions from the navigation bar. 4458 mContentTop = mVoiceContentTop = mCurTop = mDockTop; 4459 mContentBottom = mVoiceContentBottom = mCurBottom = mDockBottom; 4460 mContentLeft = mVoiceContentLeft = mCurLeft = mDockLeft; 4461 mContentRight = mVoiceContentRight = mCurRight = mDockRight; 4462 mStatusBarLayer = mNavigationBar.getSurfaceLayer(); 4463 // And compute the final frame. 4464 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, 4465 mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf, 4466 mTmpNavigationFrame, mTmpNavigationFrame); 4467 if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); 4468 if (mNavigationBarController.checkHiddenLw()) { 4469 return true; 4470 } 4471 } 4472 return false; 4473 } 4474 4475 private int navigationBarPosition(int displayWidth, int displayHeight, int displayRotation) { 4476 if (mNavigationBarCanMove && displayWidth > displayHeight) { 4477 if (displayRotation == Surface.ROTATION_270) { 4478 return NAV_BAR_LEFT; 4479 } else { 4480 return NAV_BAR_RIGHT; 4481 } 4482 } 4483 return NAV_BAR_BOTTOM; 4484 } 4485 4486 /** {@inheritDoc} */ 4487 @Override 4488 public int getSystemDecorLayerLw() { 4489 if (mStatusBar != null && mStatusBar.isVisibleLw()) { 4490 return mStatusBar.getSurfaceLayer(); 4491 } 4492 4493 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) { 4494 return mNavigationBar.getSurfaceLayer(); 4495 } 4496 4497 return 0; 4498 } 4499 4500 @Override 4501 public void getContentRectLw(Rect r) { 4502 r.set(mContentLeft, mContentTop, mContentRight, mContentBottom); 4503 } 4504 4505 void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached, 4506 boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) { 4507 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) { 4508 // Here's a special case: if this attached window is a panel that is 4509 // above the dock window, and the window it is attached to is below 4510 // the dock window, then the frames we computed for the window it is 4511 // attached to can not be used because the dock is effectively part 4512 // of the underlying window and the attached window is floating on top 4513 // of the whole thing. So, we ignore the attached window and explicitly 4514 // compute the frames that would be appropriate without the dock. 4515 df.left = of.left = cf.left = vf.left = mDockLeft; 4516 df.top = of.top = cf.top = vf.top = mDockTop; 4517 df.right = of.right = cf.right = vf.right = mDockRight; 4518 df.bottom = of.bottom = cf.bottom = vf.bottom = mDockBottom; 4519 } else { 4520 // The effective display frame of the attached window depends on 4521 // whether it is taking care of insetting its content. If not, 4522 // we need to use the parent's content frame so that the entire 4523 // window is positioned within that content. Otherwise we can use 4524 // the overscan frame and let the attached window take care of 4525 // positioning its content appropriately. 4526 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4527 // Set the content frame of the attached window to the parent's decor frame 4528 // (same as content frame when IME isn't present) if specifically requested by 4529 // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag. 4530 // Otherwise, use the overscan frame. 4531 cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0 4532 ? attached.getContentFrameLw() : attached.getOverscanFrameLw()); 4533 } else { 4534 // If the window is resizing, then we want to base the content 4535 // frame on our attached content frame to resize... however, 4536 // things can be tricky if the attached window is NOT in resize 4537 // mode, in which case its content frame will be larger. 4538 // Ungh. So to deal with that, make sure the content frame 4539 // we end up using is not covering the IM dock. 4540 cf.set(attached.getContentFrameLw()); 4541 if (attached.isVoiceInteraction()) { 4542 if (cf.left < mVoiceContentLeft) cf.left = mVoiceContentLeft; 4543 if (cf.top < mVoiceContentTop) cf.top = mVoiceContentTop; 4544 if (cf.right > mVoiceContentRight) cf.right = mVoiceContentRight; 4545 if (cf.bottom > mVoiceContentBottom) cf.bottom = mVoiceContentBottom; 4546 } else if (attached.getSurfaceLayer() < mDockLayer) { 4547 if (cf.left < mContentLeft) cf.left = mContentLeft; 4548 if (cf.top < mContentTop) cf.top = mContentTop; 4549 if (cf.right > mContentRight) cf.right = mContentRight; 4550 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom; 4551 } 4552 } 4553 df.set(insetDecors ? attached.getDisplayFrameLw() : cf); 4554 of.set(insetDecors ? attached.getOverscanFrameLw() : cf); 4555 vf.set(attached.getVisibleFrameLw()); 4556 } 4557 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached 4558 // window should be positioned relative to its parent or the entire 4559 // screen. 4560 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 4561 ? attached.getFrameLw() : df); 4562 } 4563 4564 private void applyStableConstraints(int sysui, int fl, Rect r) { 4565 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 4566 // If app is requesting a stable layout, don't let the 4567 // content insets go below the stable values. 4568 if ((fl & FLAG_FULLSCREEN) != 0) { 4569 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft; 4570 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop; 4571 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight; 4572 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom; 4573 } else { 4574 if (r.left < mStableLeft) r.left = mStableLeft; 4575 if (r.top < mStableTop) r.top = mStableTop; 4576 if (r.right > mStableRight) r.right = mStableRight; 4577 if (r.bottom > mStableBottom) r.bottom = mStableBottom; 4578 } 4579 } 4580 } 4581 4582 private boolean canReceiveInput(WindowState win) { 4583 boolean notFocusable = 4584 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0; 4585 boolean altFocusableIm = 4586 (win.getAttrs().flags & WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM) != 0; 4587 boolean notFocusableForIm = notFocusable ^ altFocusableIm; 4588 return !notFocusableForIm; 4589 } 4590 4591 /** {@inheritDoc} */ 4592 @Override 4593 public void layoutWindowLw(WindowState win, WindowState attached) { 4594 // We've already done the navigation bar and status bar. If the status bar can receive 4595 // input, we need to layout it again to accomodate for the IME window. 4596 if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) { 4597 return; 4598 } 4599 final WindowManager.LayoutParams attrs = win.getAttrs(); 4600 final boolean isDefaultDisplay = win.isDefaultDisplay(); 4601 final boolean needsToOffsetInputMethodTarget = isDefaultDisplay && 4602 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null); 4603 if (needsToOffsetInputMethodTarget) { 4604 if (DEBUG_LAYOUT) Slog.i(TAG, "Offset ime target window by the last ime window state"); 4605 offsetInputMethodWindowLw(mLastInputMethodWindow); 4606 } 4607 4608 final int fl = PolicyControl.getWindowFlags(win, attrs); 4609 final int pfl = attrs.privateFlags; 4610 final int sim = attrs.softInputMode; 4611 final int sysUiFl = PolicyControl.getSystemUiVisibility(win, null); 4612 4613 final Rect pf = mTmpParentFrame; 4614 final Rect df = mTmpDisplayFrame; 4615 final Rect of = mTmpOverscanFrame; 4616 final Rect cf = mTmpContentFrame; 4617 final Rect vf = mTmpVisibleFrame; 4618 final Rect dcf = mTmpDecorFrame; 4619 final Rect sf = mTmpStableFrame; 4620 Rect osf = null; 4621 dcf.setEmpty(); 4622 4623 final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar 4624 && mNavigationBar != null && mNavigationBar.isVisibleLw()); 4625 4626 final int adjust = sim & SOFT_INPUT_MASK_ADJUST; 4627 4628 if (isDefaultDisplay) { 4629 sf.set(mStableLeft, mStableTop, mStableRight, mStableBottom); 4630 } else { 4631 sf.set(mOverscanLeft, mOverscanTop, mOverscanRight, mOverscanBottom); 4632 } 4633 4634 if (!isDefaultDisplay) { 4635 if (attached != null) { 4636 // If this window is attached to another, our display 4637 // frame is the same as the one we are attached to. 4638 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); 4639 } else { 4640 // Give the window full screen. 4641 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4642 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4643 pf.right = df.right = of.right = cf.right 4644 = mOverscanScreenLeft + mOverscanScreenWidth; 4645 pf.bottom = df.bottom = of.bottom = cf.bottom 4646 = mOverscanScreenTop + mOverscanScreenHeight; 4647 } 4648 } else if (attrs.type == TYPE_INPUT_METHOD) { 4649 pf.left = df.left = of.left = cf.left = vf.left = mDockLeft; 4650 pf.top = df.top = of.top = cf.top = vf.top = mDockTop; 4651 pf.right = df.right = of.right = cf.right = vf.right = mDockRight; 4652 // IM dock windows layout below the nav bar... 4653 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4654 // ...with content insets above the nav bar 4655 cf.bottom = vf.bottom = mStableBottom; 4656 if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) { 4657 // The status bar forces the navigation bar while it's visible. Make sure the IME 4658 // avoids the navigation bar in that case. 4659 if (mNavigationBarPosition == NAV_BAR_RIGHT) { 4660 pf.right = df.right = of.right = cf.right = vf.right = mStableRight; 4661 } else if (mNavigationBarPosition == NAV_BAR_LEFT) { 4662 pf.left = df.left = of.left = cf.left = vf.left = mStableLeft; 4663 } 4664 } 4665 // IM dock windows always go to the bottom of the screen. 4666 attrs.gravity = Gravity.BOTTOM; 4667 mDockLayer = win.getSurfaceLayer(); 4668 } else if (attrs.type == TYPE_VOICE_INTERACTION) { 4669 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4670 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4671 pf.right = df.right = of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4672 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4673 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4674 cf.left = mDockLeft; 4675 cf.top = mDockTop; 4676 cf.right = mDockRight; 4677 cf.bottom = mDockBottom; 4678 } else { 4679 cf.left = mContentLeft; 4680 cf.top = mContentTop; 4681 cf.right = mContentRight; 4682 cf.bottom = mContentBottom; 4683 } 4684 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4685 vf.left = mCurLeft; 4686 vf.top = mCurTop; 4687 vf.right = mCurRight; 4688 vf.bottom = mCurBottom; 4689 } else { 4690 vf.set(cf); 4691 } 4692 } else if (attrs.type == TYPE_WALLPAPER) { 4693 layoutWallpaper(win, pf, df, of, cf); 4694 } else if (win == mStatusBar) { 4695 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4696 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4697 pf.right = df.right = of.right = mUnrestrictedScreenWidth + mUnrestrictedScreenLeft; 4698 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenHeight + mUnrestrictedScreenTop; 4699 cf.left = vf.left = mStableLeft; 4700 cf.top = vf.top = mStableTop; 4701 cf.right = vf.right = mStableRight; 4702 vf.bottom = mStableBottom; 4703 4704 if (adjust == SOFT_INPUT_ADJUST_RESIZE) { 4705 cf.bottom = mContentBottom; 4706 } else { 4707 cf.bottom = mDockBottom; 4708 vf.bottom = mContentBottom; 4709 } 4710 } else { 4711 4712 // Default policy decor for the default display 4713 dcf.left = mSystemLeft; 4714 dcf.top = mSystemTop; 4715 dcf.right = mSystemRight; 4716 dcf.bottom = mSystemBottom; 4717 final boolean inheritTranslucentDecor = (attrs.privateFlags 4718 & WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR) != 0; 4719 final boolean isAppWindow = 4720 attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW && 4721 attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 4722 final boolean topAtRest = 4723 win == mTopFullscreenOpaqueWindowState && !win.isAnimatingLw(); 4724 if (isAppWindow && !inheritTranslucentDecor && !topAtRest) { 4725 if ((sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0 4726 && (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) == 0 4727 && (fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS) == 0 4728 && (fl & WindowManager.LayoutParams. 4729 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0 4730 && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) { 4731 // Ensure policy decor includes status bar 4732 dcf.top = mStableTop; 4733 } 4734 if ((fl & WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION) == 0 4735 && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0 4736 && (fl & WindowManager.LayoutParams. 4737 FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) { 4738 // Ensure policy decor includes navigation bar 4739 dcf.bottom = mStableBottom; 4740 dcf.right = mStableRight; 4741 } 4742 } 4743 4744 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 4745 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 4746 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() 4747 + "): IN_SCREEN, INSET_DECOR"); 4748 // This is the case for a normal activity window: we want it 4749 // to cover all of the screen space, and it can take care of 4750 // moving its contents to account for screen decorations that 4751 // intrude into that space. 4752 if (attached != null) { 4753 // If this window is attached to another, our display 4754 // frame is the same as the one we are attached to. 4755 setAttachedWindowFrames(win, fl, adjust, attached, true, pf, df, of, cf, vf); 4756 } else { 4757 if (attrs.type == TYPE_STATUS_BAR_PANEL 4758 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { 4759 // Status bar panels are the only windows who can go on top of 4760 // the status bar. They are protected by the STATUS_BAR_SERVICE 4761 // permission, so they have the same privileges as the status 4762 // bar itself. 4763 // 4764 // However, they should still dodge the navigation bar if it exists. 4765 4766 pf.left = df.left = of.left = hasNavBar 4767 ? mDockLeft : mUnrestrictedScreenLeft; 4768 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4769 pf.right = df.right = of.right = hasNavBar 4770 ? mRestrictedScreenLeft+mRestrictedScreenWidth 4771 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4772 pf.bottom = df.bottom = of.bottom = hasNavBar 4773 ? mRestrictedScreenTop+mRestrictedScreenHeight 4774 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4775 4776 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4777 "Laying out status bar window: (%d,%d - %d,%d)", 4778 pf.left, pf.top, pf.right, pf.bottom)); 4779 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 4780 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4781 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4782 // Asking to layout into the overscan region, so give it that pure 4783 // unrestricted area. 4784 pf.left = df.left = of.left = mOverscanScreenLeft; 4785 pf.top = df.top = of.top = mOverscanScreenTop; 4786 pf.right = df.right = of.right = mOverscanScreenLeft + mOverscanScreenWidth; 4787 pf.bottom = df.bottom = of.bottom = mOverscanScreenTop 4788 + mOverscanScreenHeight; 4789 } else if (canHideNavigationBar() 4790 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 4791 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4792 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4793 // Asking for layout as if the nav bar is hidden, lets the 4794 // application extend into the unrestricted overscan screen area. We 4795 // only do this for application windows to ensure no window that 4796 // can be above the nav bar can do this. 4797 pf.left = df.left = mOverscanScreenLeft; 4798 pf.top = df.top = mOverscanScreenTop; 4799 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 4800 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 4801 // We need to tell the app about where the frame inside the overscan 4802 // is, so it can inset its content by that amount -- it didn't ask 4803 // to actually extend itself into the overscan region. 4804 of.left = mUnrestrictedScreenLeft; 4805 of.top = mUnrestrictedScreenTop; 4806 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4807 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4808 } else { 4809 pf.left = df.left = mRestrictedOverscanScreenLeft; 4810 pf.top = df.top = mRestrictedOverscanScreenTop; 4811 pf.right = df.right = mRestrictedOverscanScreenLeft 4812 + mRestrictedOverscanScreenWidth; 4813 pf.bottom = df.bottom = mRestrictedOverscanScreenTop 4814 + mRestrictedOverscanScreenHeight; 4815 // We need to tell the app about where the frame inside the overscan 4816 // is, so it can inset its content by that amount -- it didn't ask 4817 // to actually extend itself into the overscan region. 4818 of.left = mUnrestrictedScreenLeft; 4819 of.top = mUnrestrictedScreenTop; 4820 of.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4821 of.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4822 } 4823 4824 if ((fl & FLAG_FULLSCREEN) == 0) { 4825 if (win.isVoiceInteraction()) { 4826 cf.left = mVoiceContentLeft; 4827 cf.top = mVoiceContentTop; 4828 cf.right = mVoiceContentRight; 4829 cf.bottom = mVoiceContentBottom; 4830 } else { 4831 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4832 cf.left = mDockLeft; 4833 cf.top = mDockTop; 4834 cf.right = mDockRight; 4835 cf.bottom = mDockBottom; 4836 } else { 4837 cf.left = mContentLeft; 4838 cf.top = mContentTop; 4839 cf.right = mContentRight; 4840 cf.bottom = mContentBottom; 4841 } 4842 } 4843 } else { 4844 // Full screen windows are always given a layout that is as if the 4845 // status bar and other transient decors are gone. This is to avoid 4846 // bad states when moving from a window that is not hding the 4847 // status bar to one that is. 4848 cf.left = mRestrictedScreenLeft; 4849 cf.top = mRestrictedScreenTop; 4850 cf.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 4851 cf.bottom = mRestrictedScreenTop + mRestrictedScreenHeight; 4852 } 4853 applyStableConstraints(sysUiFl, fl, cf); 4854 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4855 vf.left = mCurLeft; 4856 vf.top = mCurTop; 4857 vf.right = mCurRight; 4858 vf.bottom = mCurBottom; 4859 } else { 4860 vf.set(cf); 4861 } 4862 } 4863 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl 4864 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 4865 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) { 4866 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4867 "): IN_SCREEN"); 4868 // A window that has requested to fill the entire screen just 4869 // gets everything, period. 4870 if (attrs.type == TYPE_STATUS_BAR_PANEL 4871 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL 4872 || attrs.type == TYPE_VOLUME_OVERLAY) { 4873 pf.left = df.left = of.left = cf.left = hasNavBar 4874 ? mDockLeft : mUnrestrictedScreenLeft; 4875 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 4876 pf.right = df.right = of.right = cf.right = hasNavBar 4877 ? mRestrictedScreenLeft+mRestrictedScreenWidth 4878 : mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 4879 pf.bottom = df.bottom = of.bottom = cf.bottom = hasNavBar 4880 ? mRestrictedScreenTop+mRestrictedScreenHeight 4881 : mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 4882 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4883 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)", 4884 pf.left, pf.top, pf.right, pf.bottom)); 4885 } else if (attrs.type == TYPE_NAVIGATION_BAR 4886 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) { 4887 // The navigation bar has Real Ultimate Power. 4888 pf.left = df.left = of.left = mUnrestrictedScreenLeft; 4889 pf.top = df.top = of.top = mUnrestrictedScreenTop; 4890 pf.right = df.right = of.right = mUnrestrictedScreenLeft 4891 + mUnrestrictedScreenWidth; 4892 pf.bottom = df.bottom = of.bottom = mUnrestrictedScreenTop 4893 + mUnrestrictedScreenHeight; 4894 if (DEBUG_LAYOUT) Slog.v(TAG, String.format( 4895 "Laying out navigation bar window: (%d,%d - %d,%d)", 4896 pf.left, pf.top, pf.right, pf.bottom)); 4897 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY 4898 || attrs.type == TYPE_BOOT_PROGRESS 4899 || attrs.type == TYPE_SCREENSHOT) 4900 && ((fl & FLAG_FULLSCREEN) != 0)) { 4901 // Fullscreen secure system overlays get what they ask for. Screenshot region 4902 // selection overlay should also expand to full screen. 4903 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4904 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4905 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 4906 + mOverscanScreenWidth; 4907 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 4908 + mOverscanScreenHeight; 4909 } else if (attrs.type == TYPE_BOOT_PROGRESS) { 4910 // Boot progress screen always covers entire display. 4911 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4912 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4913 pf.right = df.right = of.right = cf.right = mOverscanScreenLeft 4914 + mOverscanScreenWidth; 4915 pf.bottom = df.bottom = of.bottom = cf.bottom = mOverscanScreenTop 4916 + mOverscanScreenHeight; 4917 } else if ((fl & FLAG_LAYOUT_IN_OVERSCAN) != 0 4918 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4919 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 4920 // Asking to layout into the overscan region, so give it that pure 4921 // unrestricted area. 4922 pf.left = df.left = of.left = cf.left = mOverscanScreenLeft; 4923 pf.top = df.top = of.top = cf.top = mOverscanScreenTop; 4924 pf.right = df.right = of.right = cf.right 4925 = mOverscanScreenLeft + mOverscanScreenWidth; 4926 pf.bottom = df.bottom = of.bottom = cf.bottom 4927 = mOverscanScreenTop + mOverscanScreenHeight; 4928 } else if (canHideNavigationBar() 4929 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 4930 && (attrs.type == TYPE_STATUS_BAR 4931 || attrs.type == TYPE_TOAST 4932 || attrs.type == TYPE_DOCK_DIVIDER 4933 || attrs.type == TYPE_VOICE_INTERACTION_STARTING 4934 || (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 4935 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) { 4936 // Asking for layout as if the nav bar is hidden, lets the 4937 // application extend into the unrestricted screen area. We 4938 // only do this for application windows (or toasts) to ensure no window that 4939 // can be above the nav bar can do this. 4940 // XXX This assumes that an app asking for this will also 4941 // ask for layout in only content. We can't currently figure out 4942 // what the screen would be if only laying out to hide the nav bar. 4943 pf.left = df.left = of.left = cf.left = mUnrestrictedScreenLeft; 4944 pf.top = df.top = of.top = cf.top = mUnrestrictedScreenTop; 4945 pf.right = df.right = of.right = cf.right = mUnrestrictedScreenLeft 4946 + mUnrestrictedScreenWidth; 4947 pf.bottom = df.bottom = of.bottom = cf.bottom = mUnrestrictedScreenTop 4948 + mUnrestrictedScreenHeight; 4949 } else if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0) { 4950 pf.left = df.left = of.left = mRestrictedScreenLeft; 4951 pf.top = df.top = of.top = mRestrictedScreenTop; 4952 pf.right = df.right = of.right = mRestrictedScreenLeft + mRestrictedScreenWidth; 4953 pf.bottom = df.bottom = of.bottom = mRestrictedScreenTop 4954 + mRestrictedScreenHeight; 4955 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 4956 cf.left = mDockLeft; 4957 cf.top = mDockTop; 4958 cf.right = mDockRight; 4959 cf.bottom = mDockBottom; 4960 } else { 4961 cf.left = mContentLeft; 4962 cf.top = mContentTop; 4963 cf.right = mContentRight; 4964 cf.bottom = mContentBottom; 4965 } 4966 } else { 4967 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 4968 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 4969 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 4970 + mRestrictedScreenWidth; 4971 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 4972 + mRestrictedScreenHeight; 4973 } 4974 4975 applyStableConstraints(sysUiFl, fl, cf); 4976 4977 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 4978 vf.left = mCurLeft; 4979 vf.top = mCurTop; 4980 vf.right = mCurRight; 4981 vf.bottom = mCurBottom; 4982 } else { 4983 vf.set(cf); 4984 } 4985 } else if (attached != null) { 4986 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4987 "): attached to " + attached); 4988 // A child window should be placed inside of the same visible 4989 // frame that its parent had. 4990 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, of, cf, vf); 4991 } else { 4992 if (DEBUG_LAYOUT) Slog.v(TAG, "layoutWindowLw(" + attrs.getTitle() + 4993 "): normal window"); 4994 // Otherwise, a normal window must be placed inside the content 4995 // of all screen decorations. 4996 if (attrs.type == TYPE_STATUS_BAR_PANEL || attrs.type == TYPE_VOLUME_OVERLAY) { 4997 // Status bar panels and the volume dialog are the only windows who can go on 4998 // top of the status bar. They are protected by the STATUS_BAR_SERVICE 4999 // permission, so they have the same privileges as the status 5000 // bar itself. 5001 pf.left = df.left = of.left = cf.left = mRestrictedScreenLeft; 5002 pf.top = df.top = of.top = cf.top = mRestrictedScreenTop; 5003 pf.right = df.right = of.right = cf.right = mRestrictedScreenLeft 5004 + mRestrictedScreenWidth; 5005 pf.bottom = df.bottom = of.bottom = cf.bottom = mRestrictedScreenTop 5006 + mRestrictedScreenHeight; 5007 } else if (attrs.type == TYPE_TOAST || attrs.type == TYPE_SYSTEM_ALERT) { 5008 // These dialogs are stable to interim decor changes. 5009 pf.left = df.left = of.left = cf.left = mStableLeft; 5010 pf.top = df.top = of.top = cf.top = mStableTop; 5011 pf.right = df.right = of.right = cf.right = mStableRight; 5012 pf.bottom = df.bottom = of.bottom = cf.bottom = mStableBottom; 5013 } else { 5014 pf.left = mContentLeft; 5015 pf.top = mContentTop; 5016 pf.right = mContentRight; 5017 pf.bottom = mContentBottom; 5018 if (win.isVoiceInteraction()) { 5019 df.left = of.left = cf.left = mVoiceContentLeft; 5020 df.top = of.top = cf.top = mVoiceContentTop; 5021 df.right = of.right = cf.right = mVoiceContentRight; 5022 df.bottom = of.bottom = cf.bottom = mVoiceContentBottom; 5023 } else if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 5024 df.left = of.left = cf.left = mDockLeft; 5025 df.top = of.top = cf.top = mDockTop; 5026 df.right = of.right = cf.right = mDockRight; 5027 df.bottom = of.bottom = cf.bottom = mDockBottom; 5028 } else { 5029 df.left = of.left = cf.left = mContentLeft; 5030 df.top = of.top = cf.top = mContentTop; 5031 df.right = of.right = cf.right = mContentRight; 5032 df.bottom = of.bottom = cf.bottom = mContentBottom; 5033 } 5034 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 5035 vf.left = mCurLeft; 5036 vf.top = mCurTop; 5037 vf.right = mCurRight; 5038 vf.bottom = mCurBottom; 5039 } else { 5040 vf.set(cf); 5041 } 5042 } 5043 } 5044 } 5045 5046 // TYPE_SYSTEM_ERROR is above the NavigationBar so it can't be allowed to extend over it. 5047 // Also, we don't allow windows in multi-window mode to extend out of the screen. 5048 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0 && attrs.type != TYPE_SYSTEM_ERROR 5049 && !win.isInMultiWindowMode()) { 5050 df.left = df.top = -10000; 5051 df.right = df.bottom = 10000; 5052 if (attrs.type != TYPE_WALLPAPER) { 5053 of.left = of.top = cf.left = cf.top = vf.left = vf.top = -10000; 5054 of.right = of.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000; 5055 } 5056 } 5057 5058 // If the device has a chin (e.g. some watches), a dead area at the bottom of the screen we 5059 // need to provide information to the clients that want to pretend that you can draw there. 5060 // We only want to apply outsets to certain types of windows. For example, we never want to 5061 // apply the outsets to floating dialogs, because they wouldn't make sense there. 5062 final boolean useOutsets = shouldUseOutsets(attrs, fl); 5063 if (isDefaultDisplay && useOutsets) { 5064 osf = mTmpOutsetFrame; 5065 osf.set(cf.left, cf.top, cf.right, cf.bottom); 5066 int outset = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources()); 5067 if (outset > 0) { 5068 int rotation = mDisplayRotation; 5069 if (rotation == Surface.ROTATION_0) { 5070 osf.bottom += outset; 5071 } else if (rotation == Surface.ROTATION_90) { 5072 osf.right += outset; 5073 } else if (rotation == Surface.ROTATION_180) { 5074 osf.top -= outset; 5075 } else if (rotation == Surface.ROTATION_270) { 5076 osf.left -= outset; 5077 } 5078 if (DEBUG_LAYOUT) Slog.v(TAG, "applying bottom outset of " + outset 5079 + " with rotation " + rotation + ", result: " + osf); 5080 } 5081 } 5082 5083 if (DEBUG_LAYOUT) Slog.v(TAG, "Compute frame " + attrs.getTitle() 5084 + ": sim=#" + Integer.toHexString(sim) 5085 + " attach=" + attached + " type=" + attrs.type 5086 + String.format(" flags=0x%08x", fl) 5087 + " pf=" + pf.toShortString() + " df=" + df.toShortString() 5088 + " of=" + of.toShortString() 5089 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString() 5090 + " dcf=" + dcf.toShortString() 5091 + " sf=" + sf.toShortString() 5092 + " osf=" + (osf == null ? "null" : osf.toShortString())); 5093 5094 win.computeFrameLw(pf, df, of, cf, vf, dcf, sf, osf); 5095 5096 // Dock windows carve out the bottom of the screen, so normal windows 5097 // can't appear underneath them. 5098 if (attrs.type == TYPE_INPUT_METHOD && win.isVisibleLw() 5099 && !win.getGivenInsetsPendingLw()) { 5100 setLastInputMethodWindowLw(null, null); 5101 offsetInputMethodWindowLw(win); 5102 } 5103 if (attrs.type == TYPE_VOICE_INTERACTION && win.isVisibleLw() 5104 && !win.getGivenInsetsPendingLw()) { 5105 offsetVoiceInputWindowLw(win); 5106 } 5107 } 5108 5109 private void layoutWallpaper(WindowState win, Rect pf, Rect df, Rect of, Rect cf) { 5110 5111 // The wallpaper also has Real Ultimate Power, but we want to tell 5112 // it about the overscan area. 5113 pf.left = df.left = mOverscanScreenLeft; 5114 pf.top = df.top = mOverscanScreenTop; 5115 pf.right = df.right = mOverscanScreenLeft + mOverscanScreenWidth; 5116 pf.bottom = df.bottom = mOverscanScreenTop + mOverscanScreenHeight; 5117 of.left = cf.left = mUnrestrictedScreenLeft; 5118 of.top = cf.top = mUnrestrictedScreenTop; 5119 of.right = cf.right = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 5120 of.bottom = cf.bottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 5121 } 5122 5123 private void offsetInputMethodWindowLw(WindowState win) { 5124 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 5125 top += win.getGivenContentInsetsLw().top; 5126 if (mContentBottom > top) { 5127 mContentBottom = top; 5128 } 5129 if (mVoiceContentBottom > top) { 5130 mVoiceContentBottom = top; 5131 } 5132 top = win.getVisibleFrameLw().top; 5133 top += win.getGivenVisibleInsetsLw().top; 5134 if (mCurBottom > top) { 5135 mCurBottom = top; 5136 } 5137 if (DEBUG_LAYOUT) Slog.v(TAG, "Input method: mDockBottom=" 5138 + mDockBottom + " mContentBottom=" 5139 + mContentBottom + " mCurBottom=" + mCurBottom); 5140 } 5141 5142 private void offsetVoiceInputWindowLw(WindowState win) { 5143 int top = Math.max(win.getDisplayFrameLw().top, win.getContentFrameLw().top); 5144 top += win.getGivenContentInsetsLw().top; 5145 if (mVoiceContentBottom > top) { 5146 mVoiceContentBottom = top; 5147 } 5148 } 5149 5150 /** {@inheritDoc} */ 5151 @Override 5152 public void finishLayoutLw() { 5153 return; 5154 } 5155 5156 /** {@inheritDoc} */ 5157 @Override 5158 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) { 5159 mTopFullscreenOpaqueWindowState = null; 5160 mTopFullscreenOpaqueOrDimmingWindowState = null; 5161 mTopDockedOpaqueWindowState = null; 5162 mTopDockedOpaqueOrDimmingWindowState = null; 5163 mForceStatusBar = false; 5164 mForceStatusBarFromKeyguard = false; 5165 mForceStatusBarTransparent = false; 5166 mForcingShowNavBar = false; 5167 mForcingShowNavBarLayer = -1; 5168 5169 mAllowLockscreenWhenOn = false; 5170 mShowingDream = false; 5171 } 5172 5173 /** {@inheritDoc} */ 5174 @Override 5175 public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs, 5176 WindowState attached, WindowState imeTarget) { 5177 final boolean visible = !win.isGoneForLayoutLw(); 5178 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisible=" + visible); 5179 applyKeyguardPolicyLw(win, imeTarget); 5180 final int fl = PolicyControl.getWindowFlags(win, attrs); 5181 if (mTopFullscreenOpaqueWindowState == null && visible && attrs.type == TYPE_INPUT_METHOD) { 5182 mForcingShowNavBar = true; 5183 mForcingShowNavBarLayer = win.getSurfaceLayer(); 5184 } 5185 if (attrs.type == TYPE_STATUS_BAR) { 5186 if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { 5187 mForceStatusBarFromKeyguard = true; 5188 } 5189 if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { 5190 mForceStatusBarTransparent = true; 5191 } 5192 } 5193 5194 // Don't allow snapshots to influence SystemUI visibility flags. 5195 // TODO: Revisit this once SystemUI flags for snapshots are handled correctly 5196 boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW 5197 && attrs.type < FIRST_SYSTEM_WINDOW 5198 && (attrs.privateFlags & PRIVATE_FLAG_TASK_SNAPSHOT) == 0; 5199 final int stackId = win.getStackId(); 5200 if (mTopFullscreenOpaqueWindowState == null && visible) { 5201 if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) { 5202 mForceStatusBar = true; 5203 } 5204 if (attrs.type == TYPE_DREAM) { 5205 // If the lockscreen was showing when the dream started then wait 5206 // for the dream to draw before hiding the lockscreen. 5207 if (!mDreamingLockscreen 5208 || (win.isVisibleLw() && win.hasDrawnLw())) { 5209 mShowingDream = true; 5210 appWindow = true; 5211 } 5212 } 5213 5214 // For app windows that are not attached, we decide if all windows in the app they 5215 // represent should be hidden or if we should hide the lockscreen. For attached app 5216 // windows we defer the decision to the window it is attached to. 5217 if (appWindow && attached == null) { 5218 if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) { 5219 if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win); 5220 mTopFullscreenOpaqueWindowState = win; 5221 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5222 mTopFullscreenOpaqueOrDimmingWindowState = win; 5223 } 5224 if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { 5225 mAllowLockscreenWhenOn = true; 5226 } 5227 } 5228 } 5229 } 5230 5231 // Voice interaction overrides both top fullscreen and top docked. 5232 if (visible && win.getAttrs().type == TYPE_VOICE_INTERACTION) { 5233 if (mTopFullscreenOpaqueWindowState == null) { 5234 mTopFullscreenOpaqueWindowState = win; 5235 if (mTopFullscreenOpaqueOrDimmingWindowState == null) { 5236 mTopFullscreenOpaqueOrDimmingWindowState = win; 5237 } 5238 } 5239 if (mTopDockedOpaqueWindowState == null) { 5240 mTopDockedOpaqueWindowState = win; 5241 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5242 mTopDockedOpaqueOrDimmingWindowState = win; 5243 } 5244 } 5245 } 5246 5247 // Keep track of the window if it's dimming but not necessarily fullscreen. 5248 if (mTopFullscreenOpaqueOrDimmingWindowState == null && visible 5249 && win.isDimming() && StackId.normallyFullscreenWindows(stackId)) { 5250 mTopFullscreenOpaqueOrDimmingWindowState = win; 5251 } 5252 5253 // We need to keep track of the top "fullscreen" opaque window for the docked stack 5254 // separately, because both the "real fullscreen" opaque window and the one for the docked 5255 // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR. 5256 if (mTopDockedOpaqueWindowState == null && visible && appWindow && attached == null 5257 && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) { 5258 mTopDockedOpaqueWindowState = win; 5259 if (mTopDockedOpaqueOrDimmingWindowState == null) { 5260 mTopDockedOpaqueOrDimmingWindowState = win; 5261 } 5262 } 5263 5264 // Also keep track of any windows that are dimming but not necessarily fullscreen in the 5265 // docked stack. 5266 if (mTopDockedOpaqueOrDimmingWindowState == null && visible && win.isDimming() 5267 && stackId == DOCKED_STACK_ID) { 5268 mTopDockedOpaqueOrDimmingWindowState = win; 5269 } 5270 } 5271 5272 private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) { 5273 if (canBeHiddenByKeyguardLw(win)) { 5274 if (shouldBeHiddenByKeyguard(win, imeTarget)) { 5275 win.hideLw(false /* doAnimation */); 5276 } else { 5277 win.showLw(false /* doAnimation */); 5278 } 5279 } 5280 } 5281 5282 private boolean isFullscreen(WindowManager.LayoutParams attrs) { 5283 return attrs.x == 0 && attrs.y == 0 5284 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT 5285 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT; 5286 } 5287 5288 /** {@inheritDoc} */ 5289 @Override 5290 public int finishPostLayoutPolicyLw() { 5291 int changes = 0; 5292 boolean topIsFullscreen = false; 5293 5294 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) 5295 ? mTopFullscreenOpaqueWindowState.getAttrs() 5296 : null; 5297 5298 // If we are not currently showing a dream then remember the current 5299 // lockscreen state. We will use this to determine whether the dream 5300 // started while the lockscreen was showing and remember this state 5301 // while the dream is showing. 5302 if (!mShowingDream) { 5303 mDreamingLockscreen = isKeyguardShowingAndNotOccluded(); 5304 if (mDreamingSleepTokenNeeded) { 5305 mDreamingSleepTokenNeeded = false; 5306 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget(); 5307 } 5308 } else { 5309 if (!mDreamingSleepTokenNeeded) { 5310 mDreamingSleepTokenNeeded = true; 5311 mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 1, 1).sendToTarget(); 5312 } 5313 } 5314 5315 if (mStatusBar != null) { 5316 if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar 5317 + " forcefkg=" + mForceStatusBarFromKeyguard 5318 + " top=" + mTopFullscreenOpaqueWindowState); 5319 boolean shouldBeTransparent = mForceStatusBarTransparent 5320 && !mForceStatusBar 5321 && !mForceStatusBarFromKeyguard; 5322 if (!shouldBeTransparent) { 5323 mStatusBarController.setShowTransparent(false /* transparent */); 5324 } else if (!mStatusBar.isVisibleLw()) { 5325 mStatusBarController.setShowTransparent(true /* transparent */); 5326 } 5327 5328 WindowManager.LayoutParams statusBarAttrs = mStatusBar.getAttrs(); 5329 boolean statusBarExpanded = statusBarAttrs.height == MATCH_PARENT 5330 && statusBarAttrs.width == MATCH_PARENT; 5331 if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent 5332 || statusBarExpanded) { 5333 if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); 5334 if (mStatusBarController.setBarShowingLw(true)) { 5335 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5336 } 5337 // Maintain fullscreen layout until incoming animation is complete. 5338 topIsFullscreen = mTopIsFullscreen && mStatusBar.isAnimatingLw(); 5339 // Transient status bar on the lockscreen is not allowed 5340 if (mForceStatusBarFromKeyguard && mStatusBarController.isTransientShowing()) { 5341 mStatusBarController.updateVisibilityLw(false /*transientAllowed*/, 5342 mLastSystemUiFlags, mLastSystemUiFlags); 5343 } 5344 if (statusBarExpanded && mNavigationBar != null) { 5345 if (mNavigationBarController.setBarShowingLw(true)) { 5346 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5347 } 5348 } 5349 } else if (mTopFullscreenOpaqueWindowState != null) { 5350 final int fl = PolicyControl.getWindowFlags(null, lp); 5351 if (localLOGV) { 5352 Slog.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() 5353 + " shown position: " 5354 + mTopFullscreenOpaqueWindowState.getShownPositionLw()); 5355 Slog.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() 5356 + " lp.flags=0x" + Integer.toHexString(fl)); 5357 } 5358 topIsFullscreen = (fl & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 5359 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 5360 // The subtle difference between the window for mTopFullscreenOpaqueWindowState 5361 // and mTopIsFullscreen is that mTopIsFullscreen is set only if the window 5362 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the 5363 // case though. 5364 if (mStatusBarController.isTransientShowing()) { 5365 if (mStatusBarController.setBarShowingLw(true)) { 5366 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5367 } 5368 } else if (topIsFullscreen 5369 && !mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID) 5370 && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID)) { 5371 if (DEBUG_LAYOUT) Slog.v(TAG, "** HIDING status bar"); 5372 if (mStatusBarController.setBarShowingLw(false)) { 5373 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5374 } else { 5375 if (DEBUG_LAYOUT) Slog.v(TAG, "Status bar already hiding"); 5376 } 5377 } else { 5378 if (DEBUG_LAYOUT) Slog.v(TAG, "** SHOWING status bar: top is not fullscreen"); 5379 if (mStatusBarController.setBarShowingLw(true)) { 5380 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5381 } 5382 } 5383 } 5384 } 5385 5386 if (mTopIsFullscreen != topIsFullscreen) { 5387 if (!topIsFullscreen) { 5388 // Force another layout when status bar becomes fully shown. 5389 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5390 } 5391 mTopIsFullscreen = topIsFullscreen; 5392 } 5393 5394 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5395 // If the navigation bar has been hidden or shown, we need to do another 5396 // layout pass to update that window. 5397 changes |= FINISH_LAYOUT_REDO_LAYOUT; 5398 } 5399 5400 if (mShowingDream != mLastShowingDream) { 5401 mLastShowingDream = mShowingDream; 5402 mWindowManagerFuncs.notifyShowingDreamChanged(); 5403 } 5404 5405 // update since mAllowLockscreenWhenOn might have changed 5406 updateLockScreenTimeout(); 5407 return changes; 5408 } 5409 5410 /** 5411 * Updates the occluded state of the Keyguard. 5412 * 5413 * @return Whether the flags have changed and we have to redo the layout. 5414 */ 5415 private boolean setKeyguardOccludedLw(boolean isOccluded) { 5416 if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded); 5417 boolean wasOccluded = mKeyguardOccluded; 5418 boolean showing = mKeyguardDelegate.isShowing(); 5419 if (wasOccluded && !isOccluded && showing) { 5420 mKeyguardOccluded = false; 5421 mKeyguardDelegate.setOccluded(false, true /* animate */); 5422 mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD; 5423 if (!mKeyguardDelegate.hasLockscreenWallpaper()) { 5424 mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER; 5425 } 5426 return true; 5427 } else if (!wasOccluded && isOccluded && showing) { 5428 mKeyguardOccluded = true; 5429 mKeyguardDelegate.setOccluded(true, false /* animate */); 5430 mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD; 5431 mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER; 5432 return true; 5433 } else if (wasOccluded != isOccluded) { 5434 mKeyguardOccluded = isOccluded; 5435 mKeyguardDelegate.setOccluded(isOccluded, false /* animate */); 5436 return false; 5437 } else { 5438 return false; 5439 } 5440 } 5441 5442 private boolean isStatusBarKeyguard() { 5443 return mStatusBar != null 5444 && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0; 5445 } 5446 5447 @Override 5448 public boolean allowAppAnimationsLw() { 5449 if (mShowingDream) { 5450 // If keyguard or dreams is currently visible, no reason to animate behind it. 5451 return false; 5452 } 5453 return true; 5454 } 5455 5456 @Override 5457 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 5458 mFocusedWindow = newFocus; 5459 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 5460 // If the navigation bar has been hidden or shown, we need to do another 5461 // layout pass to update that window. 5462 return FINISH_LAYOUT_REDO_LAYOUT; 5463 } 5464 return 0; 5465 } 5466 5467 /** {@inheritDoc} */ 5468 @Override 5469 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 5470 // lid changed state 5471 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 5472 if (newLidState == mLidState) { 5473 return; 5474 } 5475 5476 mLidState = newLidState; 5477 applyLidSwitchState(); 5478 updateRotation(true); 5479 5480 if (lidOpen) { 5481 wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch, 5482 "android.policy:LID"); 5483 } else if (!mLidControlsSleep) { 5484 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 5485 } 5486 } 5487 5488 @Override 5489 public void notifyCameraLensCoverSwitchChanged(long whenNanos, boolean lensCovered) { 5490 int lensCoverState = lensCovered ? CAMERA_LENS_COVERED : CAMERA_LENS_UNCOVERED; 5491 if (mCameraLensCoverState == lensCoverState) { 5492 return; 5493 } 5494 if (mCameraLensCoverState == CAMERA_LENS_COVERED && 5495 lensCoverState == CAMERA_LENS_UNCOVERED) { 5496 Intent intent; 5497 final boolean keyguardActive = mKeyguardDelegate == null ? false : 5498 mKeyguardDelegate.isShowing(); 5499 if (keyguardActive) { 5500 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE); 5501 } else { 5502 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA); 5503 } 5504 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens, 5505 "android.policy:CAMERA_COVER"); 5506 startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF); 5507 } 5508 mCameraLensCoverState = lensCoverState; 5509 } 5510 5511 void setHdmiPlugged(boolean plugged) { 5512 if (mHdmiPlugged != plugged) { 5513 mHdmiPlugged = plugged; 5514 updateRotation(true, true); 5515 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 5516 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 5517 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 5518 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); 5519 } 5520 } 5521 5522 void initializeHdmiState() { 5523 boolean plugged = false; 5524 // watch for HDMI plug messages if the hdmi switch exists 5525 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 5526 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 5527 5528 final String filename = "/sys/class/switch/hdmi/state"; 5529 FileReader reader = null; 5530 try { 5531 reader = new FileReader(filename); 5532 char[] buf = new char[15]; 5533 int n = reader.read(buf); 5534 if (n > 1) { 5535 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 5536 } 5537 } catch (IOException ex) { 5538 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5539 } catch (NumberFormatException ex) { 5540 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 5541 } finally { 5542 if (reader != null) { 5543 try { 5544 reader.close(); 5545 } catch (IOException ex) { 5546 } 5547 } 5548 } 5549 } 5550 // This dance forces the code in setHdmiPlugged to run. 5551 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 5552 mHdmiPlugged = !plugged; 5553 setHdmiPlugged(!mHdmiPlugged); 5554 } 5555 5556 final Object mScreenshotLock = new Object(); 5557 ServiceConnection mScreenshotConnection = null; 5558 5559 final Runnable mScreenshotTimeout = new Runnable() { 5560 @Override public void run() { 5561 synchronized (mScreenshotLock) { 5562 if (mScreenshotConnection != null) { 5563 mContext.unbindService(mScreenshotConnection); 5564 mScreenshotConnection = null; 5565 notifyScreenshotError(); 5566 } 5567 } 5568 } 5569 }; 5570 5571 // Assume this is called from the Handler thread. 5572 private void takeScreenshot(final int screenshotType) { 5573 synchronized (mScreenshotLock) { 5574 if (mScreenshotConnection != null) { 5575 return; 5576 } 5577 final ComponentName serviceComponent = new ComponentName(SYSUI_PACKAGE, 5578 SYSUI_SCREENSHOT_SERVICE); 5579 final Intent serviceIntent = new Intent(); 5580 serviceIntent.setComponent(serviceComponent); 5581 ServiceConnection conn = new ServiceConnection() { 5582 @Override 5583 public void onServiceConnected(ComponentName name, IBinder service) { 5584 synchronized (mScreenshotLock) { 5585 if (mScreenshotConnection != this) { 5586 return; 5587 } 5588 Messenger messenger = new Messenger(service); 5589 Message msg = Message.obtain(null, screenshotType); 5590 final ServiceConnection myConn = this; 5591 Handler h = new Handler(mHandler.getLooper()) { 5592 @Override 5593 public void handleMessage(Message msg) { 5594 synchronized (mScreenshotLock) { 5595 if (mScreenshotConnection == myConn) { 5596 mContext.unbindService(mScreenshotConnection); 5597 mScreenshotConnection = null; 5598 mHandler.removeCallbacks(mScreenshotTimeout); 5599 } 5600 } 5601 } 5602 }; 5603 msg.replyTo = new Messenger(h); 5604 msg.arg1 = msg.arg2 = 0; 5605 if (mStatusBar != null && mStatusBar.isVisibleLw()) 5606 msg.arg1 = 1; 5607 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 5608 msg.arg2 = 1; 5609 try { 5610 messenger.send(msg); 5611 } catch (RemoteException e) { 5612 } 5613 } 5614 } 5615 5616 @Override 5617 public void onServiceDisconnected(ComponentName name) { 5618 synchronized (mScreenshotLock) { 5619 if (mScreenshotConnection != null) { 5620 mContext.unbindService(mScreenshotConnection); 5621 mScreenshotConnection = null; 5622 mHandler.removeCallbacks(mScreenshotTimeout); 5623 notifyScreenshotError(); 5624 } 5625 } 5626 } 5627 }; 5628 if (mContext.bindServiceAsUser(serviceIntent, conn, 5629 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, 5630 UserHandle.CURRENT)) { 5631 mScreenshotConnection = conn; 5632 mHandler.postDelayed(mScreenshotTimeout, 10000); 5633 } 5634 } 5635 } 5636 5637 /** 5638 * Notifies the screenshot service to show an error. 5639 */ 5640 private void notifyScreenshotError() { 5641 // If the service process is killed, then ask it to clean up after itself 5642 final ComponentName errorComponent = new ComponentName(SYSUI_PACKAGE, 5643 SYSUI_SCREENSHOT_ERROR_RECEIVER); 5644 Intent errorIntent = new Intent(Intent.ACTION_USER_PRESENT); 5645 errorIntent.setComponent(errorComponent); 5646 errorIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT | 5647 Intent.FLAG_RECEIVER_FOREGROUND); 5648 mContext.sendBroadcastAsUser(errorIntent, UserHandle.CURRENT); 5649 } 5650 5651 /** {@inheritDoc} */ 5652 @Override 5653 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { 5654 if (!mSystemBooted) { 5655 // If we have not yet booted, don't let key events do anything. 5656 return 0; 5657 } 5658 5659 final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0; 5660 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 5661 final boolean canceled = event.isCanceled(); 5662 final int keyCode = event.getKeyCode(); 5663 5664 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 5665 5666 // If screen is off then we treat the case where the keyguard is open but hidden 5667 // the same as if it were open and in front. 5668 // This will prevent any keys other than the power button from waking the screen 5669 // when the keyguard is hidden by another activity. 5670 final boolean keyguardActive = (mKeyguardDelegate == null ? false : 5671 (interactive ? 5672 isKeyguardShowingAndNotOccluded() : 5673 mKeyguardDelegate.isShowing())); 5674 5675 if (DEBUG_INPUT) { 5676 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 5677 + " interactive=" + interactive + " keyguardActive=" + keyguardActive 5678 + " policyFlags=" + Integer.toHexString(policyFlags)); 5679 } 5680 5681 // Basic policy based on interactive state. 5682 int result; 5683 boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0 5684 || event.isWakeKey(); 5685 if (interactive || (isInjected && !isWakeKey)) { 5686 // When the device is interactive or the key is injected pass the 5687 // key to the application. 5688 result = ACTION_PASS_TO_USER; 5689 isWakeKey = false; 5690 5691 if (interactive) { 5692 // If the screen is awake, but the button pressed was the one that woke the device 5693 // then don't pass it to the application 5694 if (keyCode == mPendingWakeKey && !down) { 5695 result = 0; 5696 } 5697 // Reset the pending key 5698 mPendingWakeKey = PENDING_KEY_NULL; 5699 } 5700 } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) { 5701 // If we're currently dozing with the screen on and the keyguard showing, pass the key 5702 // to the application but preserve its wake key status to make sure we still move 5703 // from dozing to fully interactive if we would normally go from off to fully 5704 // interactive. 5705 result = ACTION_PASS_TO_USER; 5706 // Since we're dispatching the input, reset the pending key 5707 mPendingWakeKey = PENDING_KEY_NULL; 5708 } else { 5709 // When the screen is off and the key is not injected, determine whether 5710 // to wake the device but don't pass the key to the application. 5711 result = 0; 5712 if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) { 5713 isWakeKey = false; 5714 } 5715 // Cache the wake key on down event so we can also avoid sending the up event to the app 5716 if (isWakeKey && down) { 5717 mPendingWakeKey = keyCode; 5718 } 5719 } 5720 5721 // If the key would be handled globally, just return the result, don't worry about special 5722 // key processing. 5723 if (isValidGlobalKey(keyCode) 5724 && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { 5725 if (isWakeKey) { 5726 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 5727 } 5728 return result; 5729 } 5730 5731 boolean useHapticFeedback = down 5732 && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 5733 && event.getRepeatCount() == 0; 5734 5735 // Handle special keys. 5736 switch (keyCode) { 5737 case KeyEvent.KEYCODE_BACK: { 5738 if (down) { 5739 interceptBackKeyDown(); 5740 } else { 5741 boolean handled = interceptBackKeyUp(event); 5742 5743 // Don't pass back press to app if we've already handled it via long press 5744 if (handled) { 5745 result &= ~ACTION_PASS_TO_USER; 5746 } 5747 } 5748 break; 5749 } 5750 5751 case KeyEvent.KEYCODE_VOLUME_DOWN: 5752 case KeyEvent.KEYCODE_VOLUME_UP: 5753 case KeyEvent.KEYCODE_VOLUME_MUTE: { 5754 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 5755 if (down) { 5756 if (interactive && !mScreenshotChordVolumeDownKeyTriggered 5757 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5758 mScreenshotChordVolumeDownKeyTriggered = true; 5759 mScreenshotChordVolumeDownKeyTime = event.getDownTime(); 5760 mScreenshotChordVolumeDownKeyConsumed = false; 5761 cancelPendingPowerKeyAction(); 5762 interceptScreenshotChord(); 5763 } 5764 } else { 5765 mScreenshotChordVolumeDownKeyTriggered = false; 5766 cancelPendingScreenshotChordAction(); 5767 } 5768 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 5769 if (down) { 5770 if (interactive && !mScreenshotChordVolumeUpKeyTriggered 5771 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 5772 mScreenshotChordVolumeUpKeyTriggered = true; 5773 cancelPendingPowerKeyAction(); 5774 cancelPendingScreenshotChordAction(); 5775 } 5776 } else { 5777 mScreenshotChordVolumeUpKeyTriggered = false; 5778 cancelPendingScreenshotChordAction(); 5779 } 5780 } 5781 if (down) { 5782 TelecomManager telecomManager = getTelecommService(); 5783 if (telecomManager != null) { 5784 if (telecomManager.isRinging()) { 5785 // If an incoming call is ringing, either VOLUME key means 5786 // "silence ringer". We handle these keys here, rather than 5787 // in the InCallScreen, to make sure we'll respond to them 5788 // even if the InCallScreen hasn't come to the foreground yet. 5789 // Look for the DOWN event here, to agree with the "fallback" 5790 // behavior in the InCallScreen. 5791 Log.i(TAG, "interceptKeyBeforeQueueing:" 5792 + " VOLUME key-down while ringing: Silence ringer!"); 5793 5794 // Silence the ringer. (It's safe to call this 5795 // even if the ringer has already been silenced.) 5796 telecomManager.silenceRinger(); 5797 5798 // And *don't* pass this key thru to the current activity 5799 // (which is probably the InCallScreen.) 5800 result &= ~ACTION_PASS_TO_USER; 5801 break; 5802 } 5803 if (telecomManager.isInCall() 5804 && (result & ACTION_PASS_TO_USER) == 0) { 5805 // If we are in call but we decided not to pass the key to 5806 // the application, just pass it to the session service. 5807 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent( 5808 event, AudioManager.USE_DEFAULT_STREAM_TYPE, false); 5809 break; 5810 } 5811 } 5812 } 5813 if (mUseTvRouting) { 5814 // On TVs, defer special key handlings to 5815 // {@link interceptKeyBeforeDispatching()}. 5816 result |= ACTION_PASS_TO_USER; 5817 } else if ((result & ACTION_PASS_TO_USER) == 0) { 5818 // If we aren't passing to the user and no one else 5819 // handled it send it to the session manager to 5820 // figure out. 5821 MediaSessionLegacyHelper.getHelper(mContext).sendVolumeKeyEvent( 5822 event, AudioManager.USE_DEFAULT_STREAM_TYPE, false); 5823 } 5824 break; 5825 } 5826 5827 case KeyEvent.KEYCODE_ENDCALL: { 5828 result &= ~ACTION_PASS_TO_USER; 5829 if (down) { 5830 TelecomManager telecomManager = getTelecommService(); 5831 boolean hungUp = false; 5832 if (telecomManager != null) { 5833 hungUp = telecomManager.endCall(); 5834 } 5835 if (interactive && !hungUp) { 5836 mEndCallKeyHandled = false; 5837 mHandler.postDelayed(mEndCallLongPress, 5838 ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 5839 } else { 5840 mEndCallKeyHandled = true; 5841 } 5842 } else { 5843 if (!mEndCallKeyHandled) { 5844 mHandler.removeCallbacks(mEndCallLongPress); 5845 if (!canceled) { 5846 if ((mEndcallBehavior 5847 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 5848 if (goHome()) { 5849 break; 5850 } 5851 } 5852 if ((mEndcallBehavior 5853 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 5854 mPowerManager.goToSleep(event.getEventTime(), 5855 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0); 5856 isWakeKey = false; 5857 } 5858 } 5859 } 5860 } 5861 break; 5862 } 5863 5864 case KeyEvent.KEYCODE_POWER: { 5865 result &= ~ACTION_PASS_TO_USER; 5866 isWakeKey = false; // wake-up will be handled separately 5867 if (down) { 5868 interceptPowerKeyDown(event, interactive); 5869 } else { 5870 interceptPowerKeyUp(event, interactive, canceled); 5871 } 5872 break; 5873 } 5874 5875 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 5876 // fall through 5877 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 5878 // fall through 5879 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 5880 // fall through 5881 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: { 5882 result &= ~ACTION_PASS_TO_USER; 5883 interceptSystemNavigationKey(event); 5884 break; 5885 } 5886 5887 case KeyEvent.KEYCODE_SLEEP: { 5888 result &= ~ACTION_PASS_TO_USER; 5889 isWakeKey = false; 5890 if (!mPowerManager.isInteractive()) { 5891 useHapticFeedback = false; // suppress feedback if already non-interactive 5892 } 5893 if (down) { 5894 sleepPress(event.getEventTime()); 5895 } else { 5896 sleepRelease(event.getEventTime()); 5897 } 5898 break; 5899 } 5900 5901 case KeyEvent.KEYCODE_SOFT_SLEEP: { 5902 result &= ~ACTION_PASS_TO_USER; 5903 isWakeKey = false; 5904 if (!down) { 5905 mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); 5906 } 5907 break; 5908 } 5909 5910 case KeyEvent.KEYCODE_WAKEUP: { 5911 result &= ~ACTION_PASS_TO_USER; 5912 isWakeKey = true; 5913 break; 5914 } 5915 5916 case KeyEvent.KEYCODE_MEDIA_PLAY: 5917 case KeyEvent.KEYCODE_MEDIA_PAUSE: 5918 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 5919 case KeyEvent.KEYCODE_HEADSETHOOK: 5920 case KeyEvent.KEYCODE_MUTE: 5921 case KeyEvent.KEYCODE_MEDIA_STOP: 5922 case KeyEvent.KEYCODE_MEDIA_NEXT: 5923 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 5924 case KeyEvent.KEYCODE_MEDIA_REWIND: 5925 case KeyEvent.KEYCODE_MEDIA_RECORD: 5926 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 5927 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: { 5928 if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) { 5929 // If the global session is active pass all media keys to it 5930 // instead of the active window. 5931 result &= ~ACTION_PASS_TO_USER; 5932 } 5933 if ((result & ACTION_PASS_TO_USER) == 0) { 5934 // Only do this if we would otherwise not pass it to the user. In that 5935 // case, the PhoneWindow class will do the same thing, except it will 5936 // only do it if the showing app doesn't process the key on its own. 5937 // Note that we need to make a copy of the key event here because the 5938 // original key event will be recycled when we return. 5939 mBroadcastWakeLock.acquire(); 5940 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 5941 new KeyEvent(event)); 5942 msg.setAsynchronous(true); 5943 msg.sendToTarget(); 5944 } 5945 break; 5946 } 5947 5948 case KeyEvent.KEYCODE_CALL: { 5949 if (down) { 5950 TelecomManager telecomManager = getTelecommService(); 5951 if (telecomManager != null) { 5952 if (telecomManager.isRinging()) { 5953 Log.i(TAG, "interceptKeyBeforeQueueing:" 5954 + " CALL key-down while ringing: Answer the call!"); 5955 telecomManager.acceptRingingCall(); 5956 5957 // And *don't* pass this key thru to the current activity 5958 // (which is presumably the InCallScreen.) 5959 result &= ~ACTION_PASS_TO_USER; 5960 } 5961 } 5962 } 5963 break; 5964 } 5965 case KeyEvent.KEYCODE_VOICE_ASSIST: { 5966 // Only do this if we would otherwise not pass it to the user. In that case, 5967 // interceptKeyBeforeDispatching would apply a similar but different policy in 5968 // order to invoke voice assist actions. Note that we need to make a copy of the 5969 // key event here because the original key event will be recycled when we return. 5970 if ((result & ACTION_PASS_TO_USER) == 0 && !down) { 5971 mBroadcastWakeLock.acquire(); 5972 Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK, 5973 keyguardActive ? 1 : 0, 0); 5974 msg.setAsynchronous(true); 5975 msg.sendToTarget(); 5976 } 5977 break; 5978 } 5979 case KeyEvent.KEYCODE_WINDOW: { 5980 if (mShortPressWindowBehavior == SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE) { 5981 if (mTvPictureInPictureVisible) { 5982 // Consumes the key only if picture-in-picture is visible 5983 // to show picture-in-picture control menu. 5984 // This gives a chance to the foreground activity 5985 // to customize PIP key behavior. 5986 if (!down) { 5987 showTvPictureInPictureMenu(event); 5988 } 5989 result &= ~ACTION_PASS_TO_USER; 5990 } 5991 } 5992 break; 5993 } 5994 } 5995 5996 if (useHapticFeedback) { 5997 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 5998 } 5999 6000 if (isWakeKey) { 6001 wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); 6002 } 6003 6004 return result; 6005 } 6006 6007 /** 6008 * Handle statusbar expansion events. 6009 * @param event 6010 */ 6011 private void interceptSystemNavigationKey(KeyEvent event) { 6012 if (event.getAction() == KeyEvent.ACTION_UP && areSystemNavigationKeysEnabled()) { 6013 IStatusBarService sbar = getStatusBarService(); 6014 if (sbar != null) { 6015 try { 6016 sbar.handleSystemNavigationKey(event.getKeyCode()); 6017 } catch (RemoteException e1) { 6018 // oops, no statusbar. Ignore event. 6019 } 6020 } 6021 } 6022 } 6023 6024 /** 6025 * Returns true if the key can have global actions attached to it. 6026 * We reserve all power management keys for the system since they require 6027 * very careful handling. 6028 */ 6029 private static boolean isValidGlobalKey(int keyCode) { 6030 switch (keyCode) { 6031 case KeyEvent.KEYCODE_POWER: 6032 case KeyEvent.KEYCODE_WAKEUP: 6033 case KeyEvent.KEYCODE_SLEEP: 6034 return false; 6035 default: 6036 return true; 6037 } 6038 } 6039 6040 /** 6041 * When the screen is off we ignore some keys that might otherwise typically 6042 * be considered wake keys. We filter them out here. 6043 * 6044 * {@link KeyEvent#KEYCODE_POWER} is notably absent from this list because it 6045 * is always considered a wake key. 6046 */ 6047 private boolean isWakeKeyWhenScreenOff(int keyCode) { 6048 switch (keyCode) { 6049 // ignore volume keys unless docked 6050 case KeyEvent.KEYCODE_VOLUME_UP: 6051 case KeyEvent.KEYCODE_VOLUME_DOWN: 6052 case KeyEvent.KEYCODE_VOLUME_MUTE: 6053 return mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED; 6054 6055 // ignore media and camera keys 6056 case KeyEvent.KEYCODE_MUTE: 6057 case KeyEvent.KEYCODE_HEADSETHOOK: 6058 case KeyEvent.KEYCODE_MEDIA_PLAY: 6059 case KeyEvent.KEYCODE_MEDIA_PAUSE: 6060 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 6061 case KeyEvent.KEYCODE_MEDIA_STOP: 6062 case KeyEvent.KEYCODE_MEDIA_NEXT: 6063 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 6064 case KeyEvent.KEYCODE_MEDIA_REWIND: 6065 case KeyEvent.KEYCODE_MEDIA_RECORD: 6066 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: 6067 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: 6068 case KeyEvent.KEYCODE_CAMERA: 6069 return false; 6070 } 6071 return true; 6072 } 6073 6074 6075 /** {@inheritDoc} */ 6076 @Override 6077 public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) { 6078 if ((policyFlags & FLAG_WAKE) != 0) { 6079 if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion, 6080 "android.policy:MOTION")) { 6081 return 0; 6082 } 6083 } 6084 6085 if (shouldDispatchInputWhenNonInteractive(null)) { 6086 return ACTION_PASS_TO_USER; 6087 } 6088 6089 // If we have not passed the action up and we are in theater mode without dreaming, 6090 // there will be no dream to intercept the touch and wake into ambient. The device should 6091 // wake up in this case. 6092 if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) { 6093 wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming, 6094 "android.policy:MOTION"); 6095 } 6096 6097 return 0; 6098 } 6099 6100 private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) { 6101 final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF); 6102 6103 if (displayOff && !mHasFeatureWatch) { 6104 return false; 6105 } 6106 6107 // Send events to keyguard while the screen is on and it's showing. 6108 if (isKeyguardShowingAndNotOccluded() && !displayOff) { 6109 return true; 6110 } 6111 6112 // Watches handle BACK specially 6113 if (mHasFeatureWatch 6114 && event != null 6115 && (event.getKeyCode() == KeyEvent.KEYCODE_BACK 6116 || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) { 6117 return false; 6118 } 6119 6120 // Send events to a dozing dream even if the screen is off since the dream 6121 // is in control of the state of the screen. 6122 IDreamManager dreamManager = getDreamManager(); 6123 6124 try { 6125 if (dreamManager != null && dreamManager.isDreaming()) { 6126 return true; 6127 } 6128 } catch (RemoteException e) { 6129 Slog.e(TAG, "RemoteException when checking if dreaming", e); 6130 } 6131 6132 // Otherwise, consume events since the user can't see what is being 6133 // interacted with. 6134 return false; 6135 } 6136 6137 private void dispatchDirectAudioEvent(KeyEvent event) { 6138 if (event.getAction() != KeyEvent.ACTION_DOWN) { 6139 return; 6140 } 6141 int keyCode = event.getKeyCode(); 6142 int flags = AudioManager.FLAG_SHOW_UI | AudioManager.FLAG_PLAY_SOUND 6143 | AudioManager.FLAG_FROM_KEY; 6144 String pkgName = mContext.getOpPackageName(); 6145 switch (keyCode) { 6146 case KeyEvent.KEYCODE_VOLUME_UP: 6147 try { 6148 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, 6149 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6150 } catch (RemoteException e) { 6151 Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); 6152 } 6153 break; 6154 case KeyEvent.KEYCODE_VOLUME_DOWN: 6155 try { 6156 getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, 6157 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6158 } catch (RemoteException e) { 6159 Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); 6160 } 6161 break; 6162 case KeyEvent.KEYCODE_VOLUME_MUTE: 6163 try { 6164 if (event.getRepeatCount() == 0) { 6165 getAudioService().adjustSuggestedStreamVolume( 6166 AudioManager.ADJUST_TOGGLE_MUTE, 6167 AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName, TAG); 6168 } 6169 } catch (RemoteException e) { 6170 Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); 6171 } 6172 break; 6173 } 6174 } 6175 6176 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 6177 if (DEBUG_INPUT) { 6178 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 6179 } 6180 6181 if (mHavePendingMediaKeyRepeatWithWakeLock) { 6182 if (DEBUG_INPUT) { 6183 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 6184 } 6185 6186 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 6187 mHavePendingMediaKeyRepeatWithWakeLock = false; 6188 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 6189 } 6190 6191 dispatchMediaKeyWithWakeLockToAudioService(event); 6192 6193 if (event.getAction() == KeyEvent.ACTION_DOWN 6194 && event.getRepeatCount() == 0) { 6195 mHavePendingMediaKeyRepeatWithWakeLock = true; 6196 6197 Message msg = mHandler.obtainMessage( 6198 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 6199 msg.setAsynchronous(true); 6200 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 6201 } else { 6202 mBroadcastWakeLock.release(); 6203 } 6204 } 6205 6206 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 6207 mHavePendingMediaKeyRepeatWithWakeLock = false; 6208 6209 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 6210 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 6211 if (DEBUG_INPUT) { 6212 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 6213 } 6214 6215 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 6216 mBroadcastWakeLock.release(); 6217 } 6218 6219 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 6220 if (mActivityManagerInternal.isSystemReady()) { 6221 MediaSessionLegacyHelper.getHelper(mContext).sendMediaButtonEvent(event, true); 6222 } 6223 } 6224 6225 void launchVoiceAssistWithWakeLock(boolean keyguardActive) { 6226 IDeviceIdleController dic = IDeviceIdleController.Stub.asInterface( 6227 ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); 6228 if (dic != null) { 6229 try { 6230 dic.exitIdle("voice-search"); 6231 } catch (RemoteException e) { 6232 } 6233 } 6234 Intent voiceIntent = 6235 new Intent(RecognizerIntent.ACTION_VOICE_SEARCH_HANDS_FREE); 6236 voiceIntent.putExtra(RecognizerIntent.EXTRA_SECURE, keyguardActive); 6237 startActivityAsUser(voiceIntent, UserHandle.CURRENT_OR_SELF); 6238 mBroadcastWakeLock.release(); 6239 } 6240 6241 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 6242 @Override 6243 public void onReceive(Context context, Intent intent) { 6244 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 6245 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 6246 Intent.EXTRA_DOCK_STATE_UNDOCKED); 6247 } else { 6248 try { 6249 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 6250 ServiceManager.getService(Context.UI_MODE_SERVICE)); 6251 mUiMode = uiModeService.getCurrentModeType(); 6252 } catch (RemoteException e) { 6253 } 6254 } 6255 updateRotation(true); 6256 synchronized (mLock) { 6257 updateOrientationListenerLp(); 6258 } 6259 } 6260 }; 6261 6262 BroadcastReceiver mDreamReceiver = new BroadcastReceiver() { 6263 @Override 6264 public void onReceive(Context context, Intent intent) { 6265 if (Intent.ACTION_DREAMING_STARTED.equals(intent.getAction())) { 6266 if (mKeyguardDelegate != null) { 6267 mKeyguardDelegate.onDreamingStarted(); 6268 } 6269 } else if (Intent.ACTION_DREAMING_STOPPED.equals(intent.getAction())) { 6270 if (mKeyguardDelegate != null) { 6271 mKeyguardDelegate.onDreamingStopped(); 6272 } 6273 } 6274 } 6275 }; 6276 6277 BroadcastReceiver mMultiuserReceiver = new BroadcastReceiver() { 6278 @Override 6279 public void onReceive(Context context, Intent intent) { 6280 if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) { 6281 // tickle the settings observer: this first ensures that we're 6282 // observing the relevant settings for the newly-active user, 6283 // and then updates our own bookkeeping based on the now- 6284 // current user. 6285 mSettingsObserver.onChange(false); 6286 6287 // force a re-application of focused window sysui visibility. 6288 // the window may never have been shown for this user 6289 // e.g. the keyguard when going through the new-user setup flow 6290 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6291 mLastSystemUiFlags = 0; 6292 updateSystemUiVisibilityLw(); 6293 } 6294 } 6295 } 6296 }; 6297 6298 private final Runnable mHiddenNavPanic = new Runnable() { 6299 @Override 6300 public void run() { 6301 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6302 if (!isUserSetupComplete()) { 6303 // Swipe-up for navigation bar is disabled during setup 6304 return; 6305 } 6306 mPendingPanicGestureUptime = SystemClock.uptimeMillis(); 6307 if (!isNavBarEmpty(mLastSystemUiFlags)) { 6308 mNavigationBarController.showTransient(); 6309 } 6310 } 6311 } 6312 }; 6313 6314 private void requestTransientBars(WindowState swipeTarget) { 6315 synchronized (mWindowManagerFuncs.getWindowManagerLock()) { 6316 if (!isUserSetupComplete()) { 6317 // Swipe-up for navigation bar is disabled during setup 6318 return; 6319 } 6320 boolean sb = mStatusBarController.checkShowTransientBarLw(); 6321 boolean nb = mNavigationBarController.checkShowTransientBarLw() 6322 && !isNavBarEmpty(mLastSystemUiFlags); 6323 if (sb || nb) { 6324 // Don't show status bar when swiping on already visible navigation bar 6325 if (!nb && swipeTarget == mNavigationBar) { 6326 if (DEBUG) Slog.d(TAG, "Not showing transient bar, wrong swipe target"); 6327 return; 6328 } 6329 if (sb) mStatusBarController.showTransient(); 6330 if (nb) mNavigationBarController.showTransient(); 6331 mImmersiveModeConfirmation.confirmCurrentPrompt(); 6332 updateSystemUiVisibilityLw(); 6333 } 6334 } 6335 } 6336 6337 // Called on the PowerManager's Notifier thread. 6338 @Override 6339 public void startedGoingToSleep(int why) { 6340 if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")"); 6341 mCameraGestureTriggeredDuringGoingToSleep = false; 6342 mGoingToSleep = true; 6343 if (mKeyguardDelegate != null) { 6344 mKeyguardDelegate.onStartedGoingToSleep(why); 6345 } 6346 } 6347 6348 // Called on the PowerManager's Notifier thread. 6349 @Override 6350 public void finishedGoingToSleep(int why) { 6351 EventLog.writeEvent(70000, 0); 6352 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished going to sleep... (why=" + why + ")"); 6353 MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); 6354 6355 mGoingToSleep = false; 6356 6357 // We must get this work done here because the power manager will drop 6358 // the wake lock and let the system suspend once this function returns. 6359 synchronized (mLock) { 6360 mAwake = false; 6361 updateWakeGestureListenerLp(); 6362 updateOrientationListenerLp(); 6363 updateLockScreenTimeout(); 6364 } 6365 if (mKeyguardDelegate != null) { 6366 mKeyguardDelegate.onFinishedGoingToSleep(why, 6367 mCameraGestureTriggeredDuringGoingToSleep); 6368 } 6369 mCameraGestureTriggeredDuringGoingToSleep = false; 6370 } 6371 6372 // Called on the PowerManager's Notifier thread. 6373 @Override 6374 public void startedWakingUp() { 6375 EventLog.writeEvent(70000, 1); 6376 if (DEBUG_WAKEUP) Slog.i(TAG, "Started waking up..."); 6377 6378 // Since goToSleep performs these functions synchronously, we must 6379 // do the same here. We cannot post this work to a handler because 6380 // that might cause it to become reordered with respect to what 6381 // may happen in a future call to goToSleep. 6382 synchronized (mLock) { 6383 mAwake = true; 6384 6385 updateWakeGestureListenerLp(); 6386 updateOrientationListenerLp(); 6387 updateLockScreenTimeout(); 6388 } 6389 6390 if (mKeyguardDelegate != null) { 6391 mKeyguardDelegate.onStartedWakingUp(); 6392 } 6393 } 6394 6395 // Called on the PowerManager's Notifier thread. 6396 @Override 6397 public void finishedWakingUp() { 6398 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up..."); 6399 } 6400 6401 private void wakeUpFromPowerKey(long eventTime) { 6402 wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); 6403 } 6404 6405 private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { 6406 final boolean theaterModeEnabled = isTheaterModeEnabled(); 6407 if (!wakeInTheaterMode && theaterModeEnabled) { 6408 return false; 6409 } 6410 6411 if (theaterModeEnabled) { 6412 Settings.Global.putInt(mContext.getContentResolver(), 6413 Settings.Global.THEATER_MODE_ON, 0); 6414 } 6415 6416 mPowerManager.wakeUp(wakeTime, reason); 6417 return true; 6418 } 6419 6420 private void finishKeyguardDrawn() { 6421 synchronized (mLock) { 6422 if (!mScreenOnEarly || mKeyguardDrawComplete) { 6423 return; // We are not awake yet or we have already informed of this event. 6424 } 6425 6426 mKeyguardDrawComplete = true; 6427 if (mKeyguardDelegate != null) { 6428 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6429 } 6430 mWindowManagerDrawComplete = false; 6431 } 6432 6433 // ... eventually calls finishWindowsDrawn which will finalize our screen turn on 6434 // as well as enabling the orientation change logic/sensor. 6435 mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 6436 WAITING_FOR_DRAWN_TIMEOUT); 6437 } 6438 6439 // Called on the DisplayManager's DisplayPowerController thread. 6440 @Override 6441 public void screenTurnedOff() { 6442 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turned off..."); 6443 6444 updateScreenOffSleepToken(true); 6445 synchronized (mLock) { 6446 mScreenOnEarly = false; 6447 mScreenOnFully = false; 6448 mKeyguardDrawComplete = false; 6449 mWindowManagerDrawComplete = false; 6450 mScreenOnListener = null; 6451 updateOrientationListenerLp(); 6452 6453 if (mKeyguardDelegate != null) { 6454 mKeyguardDelegate.onScreenTurnedOff(); 6455 } 6456 } 6457 reportScreenStateToVrManager(false); 6458 } 6459 6460 // Called on the DisplayManager's DisplayPowerController thread. 6461 @Override 6462 public void screenTurningOn(final ScreenOnListener screenOnListener) { 6463 if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on..."); 6464 6465 updateScreenOffSleepToken(false); 6466 synchronized (mLock) { 6467 mScreenOnEarly = true; 6468 mScreenOnFully = false; 6469 mKeyguardDrawComplete = false; 6470 mWindowManagerDrawComplete = false; 6471 mScreenOnListener = screenOnListener; 6472 6473 if (mKeyguardDelegate != null) { 6474 mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT); 6475 mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000); 6476 mKeyguardDelegate.onScreenTurningOn(mKeyguardDrawnCallback); 6477 } else { 6478 if (DEBUG_WAKEUP) Slog.d(TAG, 6479 "null mKeyguardDelegate: setting mKeyguardDrawComplete."); 6480 finishKeyguardDrawn(); 6481 } 6482 } 6483 } 6484 6485 // Called on the DisplayManager's DisplayPowerController thread. 6486 @Override 6487 public void screenTurnedOn() { 6488 synchronized (mLock) { 6489 if (mKeyguardDelegate != null) { 6490 mKeyguardDelegate.onScreenTurnedOn(); 6491 } 6492 } 6493 reportScreenStateToVrManager(true); 6494 } 6495 6496 private void reportScreenStateToVrManager(boolean isScreenOn) { 6497 VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class); 6498 if (vrService == null) { 6499 return; 6500 } 6501 vrService.onScreenStateChanged(isScreenOn); 6502 } 6503 6504 private void finishWindowsDrawn() { 6505 synchronized (mLock) { 6506 if (!mScreenOnEarly || mWindowManagerDrawComplete) { 6507 return; // Screen is not turned on or we did already handle this case earlier. 6508 } 6509 6510 mWindowManagerDrawComplete = true; 6511 } 6512 6513 finishScreenTurningOn(); 6514 } 6515 6516 private void finishScreenTurningOn() { 6517 synchronized (mLock) { 6518 // We have just finished drawing screen content. Since the orientation listener 6519 // gets only installed when all windows are drawn, we try to install it again. 6520 updateOrientationListenerLp(); 6521 } 6522 final ScreenOnListener listener; 6523 final boolean enableScreen; 6524 synchronized (mLock) { 6525 if (DEBUG_WAKEUP) Slog.d(TAG, 6526 "finishScreenTurningOn: mAwake=" + mAwake 6527 + ", mScreenOnEarly=" + mScreenOnEarly 6528 + ", mScreenOnFully=" + mScreenOnFully 6529 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete 6530 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete); 6531 6532 if (mScreenOnFully || !mScreenOnEarly || !mWindowManagerDrawComplete 6533 || (mAwake && !mKeyguardDrawComplete)) { 6534 return; // spurious or not ready yet 6535 } 6536 6537 if (DEBUG_WAKEUP) Slog.i(TAG, "Finished screen turning on..."); 6538 listener = mScreenOnListener; 6539 mScreenOnListener = null; 6540 mScreenOnFully = true; 6541 6542 // Remember the first time we draw the keyguard so we know when we're done with 6543 // the main part of booting and can enable the screen and hide boot messages. 6544 if (!mKeyguardDrawnOnce && mAwake) { 6545 mKeyguardDrawnOnce = true; 6546 enableScreen = true; 6547 if (mBootMessageNeedsHiding) { 6548 mBootMessageNeedsHiding = false; 6549 hideBootMessages(); 6550 } 6551 } else { 6552 enableScreen = false; 6553 } 6554 } 6555 6556 if (listener != null) { 6557 listener.onScreenOn(); 6558 } 6559 6560 if (enableScreen) { 6561 try { 6562 mWindowManager.enableScreenIfNeeded(); 6563 } catch (RemoteException unhandled) { 6564 } 6565 } 6566 } 6567 6568 private void handleHideBootMessage() { 6569 synchronized (mLock) { 6570 if (!mKeyguardDrawnOnce) { 6571 mBootMessageNeedsHiding = true; 6572 return; // keyguard hasn't drawn the first time yet, not done booting 6573 } 6574 } 6575 6576 if (mBootMsgDialog != null) { 6577 if (DEBUG_WAKEUP) Slog.d(TAG, "handleHideBootMessage: dismissing"); 6578 mBootMsgDialog.dismiss(); 6579 mBootMsgDialog = null; 6580 } 6581 } 6582 6583 @Override 6584 public boolean isScreenOn() { 6585 return mScreenOnFully; 6586 } 6587 6588 /** {@inheritDoc} */ 6589 @Override 6590 public void enableKeyguard(boolean enabled) { 6591 if (mKeyguardDelegate != null) { 6592 mKeyguardDelegate.setKeyguardEnabled(enabled); 6593 } 6594 } 6595 6596 /** {@inheritDoc} */ 6597 @Override 6598 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 6599 if (mKeyguardDelegate != null) { 6600 mKeyguardDelegate.verifyUnlock(callback); 6601 } 6602 } 6603 6604 @Override 6605 public boolean isKeyguardShowingAndNotOccluded() { 6606 if (mKeyguardDelegate == null) return false; 6607 return mKeyguardDelegate.isShowing() && !mKeyguardOccluded; 6608 } 6609 6610 @Override 6611 public boolean isKeyguardTrustedLw() { 6612 if (mKeyguardDelegate == null) return false; 6613 return mKeyguardDelegate.isTrusted(); 6614 } 6615 6616 /** {@inheritDoc} */ 6617 @Override 6618 public boolean isKeyguardLocked() { 6619 return keyguardOn(); 6620 } 6621 6622 /** {@inheritDoc} */ 6623 @Override 6624 public boolean isKeyguardSecure(int userId) { 6625 if (mKeyguardDelegate == null) return false; 6626 return mKeyguardDelegate.isSecure(userId); 6627 } 6628 6629 /** {@inheritDoc} */ 6630 @Override 6631 public boolean isKeyguardOccluded() { 6632 if (mKeyguardDelegate == null) return false; 6633 return mKeyguardOccluded; 6634 } 6635 6636 /** {@inheritDoc} */ 6637 @Override 6638 public boolean inKeyguardRestrictedKeyInputMode() { 6639 if (mKeyguardDelegate == null) return false; 6640 return mKeyguardDelegate.isInputRestricted(); 6641 } 6642 6643 @Override 6644 public void dismissKeyguardLw(IKeyguardDismissCallback callback) { 6645 if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) { 6646 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw"); 6647 6648 // ask the keyguard to prompt the user to authenticate if necessary 6649 mKeyguardDelegate.dismiss(callback); 6650 } else if (callback != null) { 6651 try { 6652 callback.onDismissError(); 6653 } catch (RemoteException e) { 6654 Slog.w(TAG, "Failed to call callback", e); 6655 } 6656 } 6657 } 6658 6659 @Override 6660 public boolean isKeyguardDrawnLw() { 6661 synchronized (mLock) { 6662 return mKeyguardDrawnOnce; 6663 } 6664 } 6665 6666 @Override 6667 public boolean isShowingDreamLw() { 6668 return mShowingDream; 6669 } 6670 6671 @Override 6672 public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) { 6673 if (mKeyguardDelegate != null) { 6674 if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation"); 6675 mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration); 6676 } 6677 } 6678 6679 @Override 6680 public void getStableInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6681 Rect outInsets) { 6682 outInsets.setEmpty(); 6683 6684 // Navigation bar and status bar. 6685 getNonDecorInsetsLw(displayRotation, displayWidth, displayHeight, outInsets); 6686 outInsets.top = mStatusBarHeight; 6687 } 6688 6689 @Override 6690 public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight, 6691 Rect outInsets) { 6692 outInsets.setEmpty(); 6693 6694 // Only navigation bar 6695 if (mHasNavigationBar) { 6696 int position = navigationBarPosition(displayWidth, displayHeight, displayRotation); 6697 if (position == NAV_BAR_BOTTOM) { 6698 outInsets.bottom = getNavigationBarHeight(displayRotation, mUiMode); 6699 } else if (position == NAV_BAR_RIGHT) { 6700 outInsets.right = getNavigationBarWidth(displayRotation, mUiMode); 6701 } else if (position == NAV_BAR_LEFT) { 6702 outInsets.left = getNavigationBarWidth(displayRotation, mUiMode); 6703 } 6704 } 6705 } 6706 6707 @Override 6708 public boolean isNavBarForcedShownLw(WindowState windowState) { 6709 return mForceShowSystemBars; 6710 } 6711 6712 @Override 6713 public boolean isDockSideAllowed(int dockSide) { 6714 6715 // We do not allow all dock sides at which the navigation bar touches the docked stack. 6716 if (!mNavigationBarCanMove) { 6717 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT; 6718 } else { 6719 return dockSide == DOCKED_TOP || dockSide == DOCKED_LEFT; 6720 } 6721 } 6722 6723 void sendCloseSystemWindows() { 6724 PhoneWindow.sendCloseSystemWindows(mContext, null); 6725 } 6726 6727 void sendCloseSystemWindows(String reason) { 6728 PhoneWindow.sendCloseSystemWindows(mContext, reason); 6729 } 6730 6731 @Override 6732 public int rotationForOrientationLw(int orientation, int lastRotation) { 6733 if (false) { 6734 Slog.v(TAG, "rotationForOrientationLw(orient=" 6735 + orientation + ", last=" + lastRotation 6736 + "); user=" + mUserRotation + " " 6737 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 6738 ? "USER_ROTATION_LOCKED" : "") 6739 ); 6740 } 6741 6742 if (mForceDefaultOrientation) { 6743 return Surface.ROTATION_0; 6744 } 6745 6746 synchronized (mLock) { 6747 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 6748 if (sensorRotation < 0) { 6749 sensorRotation = lastRotation; 6750 } 6751 6752 final int preferredRotation; 6753 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 6754 // Ignore sensor when lid switch is open and rotation is forced. 6755 preferredRotation = mLidOpenRotation; 6756 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 6757 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 6758 // Ignore sensor when in car dock unless explicitly enabled. 6759 // This case can override the behavior of NOSENSOR, and can also 6760 // enable 180 degree rotation while docked. 6761 preferredRotation = mCarDockEnablesAccelerometer 6762 ? sensorRotation : mCarDockRotation; 6763 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 6764 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 6765 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 6766 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 6767 // Ignore sensor when in desk dock unless explicitly enabled. 6768 // This case can override the behavior of NOSENSOR, and can also 6769 // enable 180 degree rotation while docked. 6770 preferredRotation = mDeskDockEnablesAccelerometer 6771 ? sensorRotation : mDeskDockRotation; 6772 } else if (mHdmiPlugged && mDemoHdmiRotationLock) { 6773 // Ignore sensor when plugged into HDMI when demo HDMI rotation lock enabled. 6774 // Note that the dock orientation overrides the HDMI orientation. 6775 preferredRotation = mDemoHdmiRotation; 6776 } else if (mHdmiPlugged && mDockMode == Intent.EXTRA_DOCK_STATE_UNDOCKED 6777 && mUndockedHdmiRotation >= 0) { 6778 // Ignore sensor when plugged into HDMI and an undocked orientation has 6779 // been specified in the configuration (only for legacy devices without 6780 // full multi-display support). 6781 // Note that the dock orientation overrides the HDMI orientation. 6782 preferredRotation = mUndockedHdmiRotation; 6783 } else if (mDemoRotationLock) { 6784 // Ignore sensor when demo rotation lock is enabled. 6785 // Note that the dock orientation and HDMI rotation lock override this. 6786 preferredRotation = mDemoRotation; 6787 } else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 6788 // Application just wants to remain locked in the last rotation. 6789 preferredRotation = lastRotation; 6790 } else if (!mSupportAutoRotation) { 6791 // If we don't support auto-rotation then bail out here and ignore 6792 // the sensor and any rotation lock settings. 6793 preferredRotation = -1; 6794 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 6795 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 6796 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED 6797 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE 6798 || orientation == ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT 6799 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER)) 6800 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 6801 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6802 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 6803 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 6804 // Otherwise, use sensor only if requested by the application or enabled 6805 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 6806 if (mAllowAllRotations < 0) { 6807 // Can't read this during init() because the context doesn't 6808 // have display metrics at that time so we cannot determine 6809 // tablet vs. phone then. 6810 mAllowAllRotations = mContext.getResources().getBoolean( 6811 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 6812 } 6813 if (sensorRotation != Surface.ROTATION_180 6814 || mAllowAllRotations == 1 6815 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 6816 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) { 6817 preferredRotation = sensorRotation; 6818 } else { 6819 preferredRotation = lastRotation; 6820 } 6821 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 6822 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 6823 // Apply rotation lock. Does not apply to NOSENSOR. 6824 // The idea is that the user rotation expresses a weak preference for the direction 6825 // of gravity and as NOSENSOR is never affected by gravity, then neither should 6826 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 6827 preferredRotation = mUserRotation; 6828 } else { 6829 // No overriding preference. 6830 // We will do exactly what the application asked us to do. 6831 preferredRotation = -1; 6832 } 6833 6834 switch (orientation) { 6835 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6836 // Return portrait unless overridden. 6837 if (isAnyPortrait(preferredRotation)) { 6838 return preferredRotation; 6839 } 6840 return mPortraitRotation; 6841 6842 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6843 // Return landscape unless overridden. 6844 if (isLandscapeOrSeascape(preferredRotation)) { 6845 return preferredRotation; 6846 } 6847 return mLandscapeRotation; 6848 6849 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6850 // Return reverse portrait unless overridden. 6851 if (isAnyPortrait(preferredRotation)) { 6852 return preferredRotation; 6853 } 6854 return mUpsideDownRotation; 6855 6856 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6857 // Return seascape unless overridden. 6858 if (isLandscapeOrSeascape(preferredRotation)) { 6859 return preferredRotation; 6860 } 6861 return mSeascapeRotation; 6862 6863 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6864 case ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE: 6865 // Return either landscape rotation. 6866 if (isLandscapeOrSeascape(preferredRotation)) { 6867 return preferredRotation; 6868 } 6869 if (isLandscapeOrSeascape(lastRotation)) { 6870 return lastRotation; 6871 } 6872 return mLandscapeRotation; 6873 6874 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6875 case ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT: 6876 // Return either portrait rotation. 6877 if (isAnyPortrait(preferredRotation)) { 6878 return preferredRotation; 6879 } 6880 if (isAnyPortrait(lastRotation)) { 6881 return lastRotation; 6882 } 6883 return mPortraitRotation; 6884 6885 default: 6886 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 6887 // just return the preferred orientation we already calculated. 6888 if (preferredRotation >= 0) { 6889 return preferredRotation; 6890 } 6891 return Surface.ROTATION_0; 6892 } 6893 } 6894 } 6895 6896 @Override 6897 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 6898 switch (orientation) { 6899 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 6900 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 6901 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 6902 return isAnyPortrait(rotation); 6903 6904 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 6905 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 6906 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 6907 return isLandscapeOrSeascape(rotation); 6908 6909 default: 6910 return true; 6911 } 6912 } 6913 6914 @Override 6915 public void setRotationLw(int rotation) { 6916 mOrientationListener.setCurrentRotation(rotation); 6917 } 6918 6919 private boolean isLandscapeOrSeascape(int rotation) { 6920 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 6921 } 6922 6923 private boolean isAnyPortrait(int rotation) { 6924 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 6925 } 6926 6927 @Override 6928 public int getUserRotationMode() { 6929 return Settings.System.getIntForUser(mContext.getContentResolver(), 6930 Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT) != 0 ? 6931 WindowManagerPolicy.USER_ROTATION_FREE : 6932 WindowManagerPolicy.USER_ROTATION_LOCKED; 6933 } 6934 6935 // User rotation: to be used when all else fails in assigning an orientation to the device 6936 @Override 6937 public void setUserRotationMode(int mode, int rot) { 6938 ContentResolver res = mContext.getContentResolver(); 6939 6940 // mUserRotationMode and mUserRotation will be assigned by the content observer 6941 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 6942 Settings.System.putIntForUser(res, 6943 Settings.System.USER_ROTATION, 6944 rot, 6945 UserHandle.USER_CURRENT); 6946 Settings.System.putIntForUser(res, 6947 Settings.System.ACCELEROMETER_ROTATION, 6948 0, 6949 UserHandle.USER_CURRENT); 6950 } else { 6951 Settings.System.putIntForUser(res, 6952 Settings.System.ACCELEROMETER_ROTATION, 6953 1, 6954 UserHandle.USER_CURRENT); 6955 } 6956 } 6957 6958 @Override 6959 public void setSafeMode(boolean safeMode) { 6960 mSafeMode = safeMode; 6961 performHapticFeedbackLw(null, safeMode 6962 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 6963 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 6964 } 6965 6966 static long[] getLongIntArray(Resources r, int resid) { 6967 int[] ar = r.getIntArray(resid); 6968 if (ar == null) { 6969 return null; 6970 } 6971 long[] out = new long[ar.length]; 6972 for (int i=0; i<ar.length; i++) { 6973 out[i] = ar[i]; 6974 } 6975 return out; 6976 } 6977 6978 /** {@inheritDoc} */ 6979 @Override 6980 public void systemReady() { 6981 mKeyguardDelegate = new KeyguardServiceDelegate(mContext, 6982 new StateCallback() { 6983 @Override 6984 public void onTrustedChanged() { 6985 mWindowManagerFuncs.notifyKeyguardTrustedChanged(); 6986 } 6987 }); 6988 mKeyguardDelegate.onSystemReady(); 6989 6990 readCameraLensCoverState(); 6991 updateUiMode(); 6992 boolean bindKeyguardNow; 6993 synchronized (mLock) { 6994 updateOrientationListenerLp(); 6995 mSystemReady = true; 6996 mHandler.post(new Runnable() { 6997 @Override 6998 public void run() { 6999 updateSettings(); 7000 } 7001 }); 7002 7003 bindKeyguardNow = mDeferBindKeyguard; 7004 if (bindKeyguardNow) { 7005 // systemBooted ran but wasn't able to bind to the Keyguard, we'll do it now. 7006 mDeferBindKeyguard = false; 7007 } 7008 } 7009 7010 if (bindKeyguardNow) { 7011 mKeyguardDelegate.bindService(mContext); 7012 mKeyguardDelegate.onBootCompleted(); 7013 } 7014 mSystemGestures.systemReady(); 7015 mImmersiveModeConfirmation.systemReady(); 7016 } 7017 7018 /** {@inheritDoc} */ 7019 @Override 7020 public void systemBooted() { 7021 boolean bindKeyguardNow = false; 7022 synchronized (mLock) { 7023 // Time to bind Keyguard; take care to only bind it once, either here if ready or 7024 // in systemReady if not. 7025 if (mKeyguardDelegate != null) { 7026 bindKeyguardNow = true; 7027 } else { 7028 // Because mKeyguardDelegate is null, we know that the synchronized block in 7029 // systemReady didn't run yet and setting this will actually have an effect. 7030 mDeferBindKeyguard = true; 7031 } 7032 } 7033 if (bindKeyguardNow) { 7034 mKeyguardDelegate.bindService(mContext); 7035 mKeyguardDelegate.onBootCompleted(); 7036 } 7037 synchronized (mLock) { 7038 mSystemBooted = true; 7039 } 7040 startedWakingUp(); 7041 screenTurningOn(null); 7042 screenTurnedOn(); 7043 } 7044 7045 ProgressDialog mBootMsgDialog = null; 7046 7047 /** {@inheritDoc} */ 7048 @Override 7049 public void showBootMessage(final CharSequence msg, final boolean always) { 7050 mHandler.post(new Runnable() { 7051 @Override public void run() { 7052 if (mBootMsgDialog == null) { 7053 int theme; 7054 if (mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION)) { 7055 theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; 7056 } else { 7057 theme = 0; 7058 } 7059 7060 mBootMsgDialog = new ProgressDialog(mContext, theme) { 7061 // This dialog will consume all events coming in to 7062 // it, to avoid it trying to do things too early in boot. 7063 @Override public boolean dispatchKeyEvent(KeyEvent event) { 7064 return true; 7065 } 7066 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 7067 return true; 7068 } 7069 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 7070 return true; 7071 } 7072 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 7073 return true; 7074 } 7075 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 7076 return true; 7077 } 7078 @Override public boolean dispatchPopulateAccessibilityEvent( 7079 AccessibilityEvent event) { 7080 return true; 7081 } 7082 }; 7083 if (mContext.getPackageManager().isUpgrade()) { 7084 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 7085 } else { 7086 mBootMsgDialog.setTitle(R.string.android_start_title); 7087 } 7088 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 7089 mBootMsgDialog.setIndeterminate(true); 7090 mBootMsgDialog.getWindow().setType( 7091 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 7092 mBootMsgDialog.getWindow().addFlags( 7093 WindowManager.LayoutParams.FLAG_DIM_BEHIND 7094 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 7095 mBootMsgDialog.getWindow().setDimAmount(1); 7096 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 7097 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 7098 mBootMsgDialog.getWindow().setAttributes(lp); 7099 mBootMsgDialog.setCancelable(false); 7100 mBootMsgDialog.show(); 7101 } 7102 mBootMsgDialog.setMessage(msg); 7103 } 7104 }); 7105 } 7106 7107 /** {@inheritDoc} */ 7108 @Override 7109 public void hideBootMessages() { 7110 mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE); 7111 } 7112 7113 /** {@inheritDoc} */ 7114 @Override 7115 public void userActivity() { 7116 // *************************************** 7117 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 7118 // *************************************** 7119 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 7120 // WITH ITS LOCKS HELD. 7121 // 7122 // This code must be VERY careful about the locks 7123 // it acquires. 7124 // In fact, the current code acquires way too many, 7125 // and probably has lurking deadlocks. 7126 7127 synchronized (mScreenLockTimeout) { 7128 if (mLockScreenTimerActive) { 7129 // reset the timer 7130 mHandler.removeCallbacks(mScreenLockTimeout); 7131 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7132 } 7133 } 7134 } 7135 7136 class ScreenLockTimeout implements Runnable { 7137 Bundle options; 7138 7139 @Override 7140 public void run() { 7141 synchronized (this) { 7142 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 7143 if (mKeyguardDelegate != null) { 7144 mKeyguardDelegate.doKeyguardTimeout(options); 7145 } 7146 mLockScreenTimerActive = false; 7147 options = null; 7148 } 7149 } 7150 7151 public void setLockOptions(Bundle options) { 7152 this.options = options; 7153 } 7154 } 7155 7156 ScreenLockTimeout mScreenLockTimeout = new ScreenLockTimeout(); 7157 7158 @Override 7159 public void lockNow(Bundle options) { 7160 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 7161 mHandler.removeCallbacks(mScreenLockTimeout); 7162 if (options != null) { 7163 // In case multiple calls are made to lockNow, we don't wipe out the options 7164 // until the runnable actually executes. 7165 mScreenLockTimeout.setLockOptions(options); 7166 } 7167 mHandler.post(mScreenLockTimeout); 7168 } 7169 7170 private void updateLockScreenTimeout() { 7171 synchronized (mScreenLockTimeout) { 7172 boolean enable = (mAllowLockscreenWhenOn && mAwake && 7173 mKeyguardDelegate != null && mKeyguardDelegate.isSecure(mCurrentUserId)); 7174 if (mLockScreenTimerActive != enable) { 7175 if (enable) { 7176 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 7177 mHandler.removeCallbacks(mScreenLockTimeout); // remove any pending requests 7178 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 7179 } else { 7180 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 7181 mHandler.removeCallbacks(mScreenLockTimeout); 7182 } 7183 mLockScreenTimerActive = enable; 7184 } 7185 } 7186 } 7187 7188 private void updateDreamingSleepToken(boolean acquire) { 7189 if (acquire) { 7190 if (mDreamingSleepToken == null) { 7191 mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken("Dream"); 7192 } 7193 } else { 7194 if (mDreamingSleepToken != null) { 7195 mDreamingSleepToken.release(); 7196 mDreamingSleepToken = null; 7197 } 7198 } 7199 } 7200 7201 private void updateScreenOffSleepToken(boolean acquire) { 7202 if (acquire) { 7203 if (mScreenOffSleepToken == null) { 7204 mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken("ScreenOff"); 7205 } 7206 } else { 7207 if (mScreenOffSleepToken != null) { 7208 mScreenOffSleepToken.release(); 7209 mScreenOffSleepToken = null; 7210 } 7211 } 7212 } 7213 7214 /** {@inheritDoc} */ 7215 @Override 7216 public void enableScreenAfterBoot() { 7217 readLidState(); 7218 applyLidSwitchState(); 7219 updateRotation(true); 7220 } 7221 7222 private void applyLidSwitchState() { 7223 if (mLidState == LID_CLOSED && mLidControlsSleep) { 7224 mPowerManager.goToSleep(SystemClock.uptimeMillis(), 7225 PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH, 7226 PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE); 7227 } else if (mLidState == LID_CLOSED && mLidControlsScreenLock) { 7228 mWindowManagerFuncs.lockDeviceNow(); 7229 } 7230 7231 synchronized (mLock) { 7232 updateWakeGestureListenerLp(); 7233 } 7234 } 7235 7236 void updateUiMode() { 7237 if (mUiModeManager == null) { 7238 mUiModeManager = IUiModeManager.Stub.asInterface( 7239 ServiceManager.getService(Context.UI_MODE_SERVICE)); 7240 } 7241 try { 7242 mUiMode = mUiModeManager.getCurrentModeType(); 7243 } catch (RemoteException e) { 7244 } 7245 } 7246 7247 void updateRotation(boolean alwaysSendConfiguration) { 7248 try { 7249 //set orientation on WindowManager 7250 mWindowManager.updateRotation(alwaysSendConfiguration, false); 7251 } catch (RemoteException e) { 7252 // Ignore 7253 } 7254 } 7255 7256 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 7257 try { 7258 //set orientation on WindowManager 7259 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 7260 } catch (RemoteException e) { 7261 // Ignore 7262 } 7263 } 7264 7265 /** 7266 * Return an Intent to launch the currently active dock app as home. Returns 7267 * null if the standard home should be launched, which is the case if any of the following is 7268 * true: 7269 * <ul> 7270 * <li>The device is not in either car mode or desk mode 7271 * <li>The device is in car mode but mEnableCarDockHomeCapture is false 7272 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 7273 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 7274 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 7275 * </ul> 7276 * @return A dock intent. 7277 */ 7278 Intent createHomeDockIntent() { 7279 Intent intent = null; 7280 7281 // What home does is based on the mode, not the dock state. That 7282 // is, when in car mode you should be taken to car home regardless 7283 // of whether we are actually in a car dock. 7284 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 7285 if (mEnableCarDockHomeCapture) { 7286 intent = mCarDockIntent; 7287 } 7288 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 7289 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 7290 intent = mDeskDockIntent; 7291 } 7292 } else if (mUiMode == Configuration.UI_MODE_TYPE_WATCH 7293 && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 7294 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK 7295 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK)) { 7296 // Always launch dock home from home when watch is docked, if it exists. 7297 intent = mDeskDockIntent; 7298 } 7299 7300 if (intent == null) { 7301 return null; 7302 } 7303 7304 ActivityInfo ai = null; 7305 ResolveInfo info = mContext.getPackageManager().resolveActivityAsUser( 7306 intent, 7307 PackageManager.MATCH_DEFAULT_ONLY | PackageManager.GET_META_DATA, 7308 mCurrentUserId); 7309 if (info != null) { 7310 ai = info.activityInfo; 7311 } 7312 if (ai != null 7313 && ai.metaData != null 7314 && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 7315 intent = new Intent(intent); 7316 intent.setClassName(ai.packageName, ai.name); 7317 return intent; 7318 } 7319 7320 return null; 7321 } 7322 7323 void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) { 7324 if (awakenFromDreams) { 7325 awakenDreams(); 7326 } 7327 7328 Intent dock = createHomeDockIntent(); 7329 if (dock != null) { 7330 try { 7331 if (fromHomeKey) { 7332 dock.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7333 } 7334 startActivityAsUser(dock, UserHandle.CURRENT); 7335 return; 7336 } catch (ActivityNotFoundException e) { 7337 } 7338 } 7339 7340 Intent intent; 7341 7342 if (fromHomeKey) { 7343 intent = new Intent(mHomeIntent); 7344 intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey); 7345 } else { 7346 intent = mHomeIntent; 7347 } 7348 7349 startActivityAsUser(intent, UserHandle.CURRENT); 7350 } 7351 7352 /** 7353 * goes to the home screen 7354 * @return whether it did anything 7355 */ 7356 boolean goHome() { 7357 if (!isUserSetupComplete()) { 7358 Slog.i(TAG, "Not going home because user setup is in progress."); 7359 return false; 7360 } 7361 if (false) { 7362 // This code always brings home to the front. 7363 try { 7364 ActivityManager.getService().stopAppSwitches(); 7365 } catch (RemoteException e) { 7366 } 7367 sendCloseSystemWindows(); 7368 startDockOrHome(false /*fromHomeKey*/, true /* awakenFromDreams */); 7369 } else { 7370 // This code brings home to the front or, if it is already 7371 // at the front, puts the device to sleep. 7372 try { 7373 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 7374 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 7375 Log.d(TAG, "UTS-TEST-MODE"); 7376 } else { 7377 ActivityManager.getService().stopAppSwitches(); 7378 sendCloseSystemWindows(); 7379 Intent dock = createHomeDockIntent(); 7380 if (dock != null) { 7381 int result = ActivityManager.getService() 7382 .startActivityAsUser(null, null, dock, 7383 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 7384 null, null, 0, 7385 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7386 null, null, UserHandle.USER_CURRENT); 7387 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7388 return false; 7389 } 7390 } 7391 } 7392 int result = ActivityManager.getService() 7393 .startActivityAsUser(null, null, mHomeIntent, 7394 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 7395 null, null, 0, 7396 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 7397 null, null, UserHandle.USER_CURRENT); 7398 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 7399 return false; 7400 } 7401 } catch (RemoteException ex) { 7402 // bummer, the activity manager, which is in this process, is dead 7403 } 7404 } 7405 return true; 7406 } 7407 7408 @Override 7409 public void setCurrentOrientationLw(int newOrientation) { 7410 synchronized (mLock) { 7411 if (newOrientation != mCurrentAppOrientation) { 7412 mCurrentAppOrientation = newOrientation; 7413 updateOrientationListenerLp(); 7414 } 7415 } 7416 } 7417 7418 private void performAuditoryFeedbackForAccessibilityIfNeed() { 7419 if (!isGlobalAccessibilityGestureEnabled()) { 7420 return; 7421 } 7422 AudioManager audioManager = (AudioManager) mContext.getSystemService( 7423 Context.AUDIO_SERVICE); 7424 if (audioManager.isSilentMode()) { 7425 return; 7426 } 7427 Ringtone ringTone = RingtoneManager.getRingtone(mContext, 7428 Settings.System.DEFAULT_NOTIFICATION_URI); 7429 ringTone.setStreamType(AudioManager.STREAM_MUSIC); 7430 ringTone.play(); 7431 } 7432 7433 private boolean isTheaterModeEnabled() { 7434 return Settings.Global.getInt(mContext.getContentResolver(), 7435 Settings.Global.THEATER_MODE_ON, 0) == 1; 7436 } 7437 7438 private boolean isGlobalAccessibilityGestureEnabled() { 7439 return Settings.Global.getInt(mContext.getContentResolver(), 7440 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1; 7441 } 7442 7443 private boolean areSystemNavigationKeysEnabled() { 7444 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 7445 Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; 7446 } 7447 7448 @Override 7449 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 7450 if (!mVibrator.hasVibrator()) { 7451 return false; 7452 } 7453 final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), 7454 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; 7455 if (hapticsDisabled && !always) { 7456 return false; 7457 } 7458 long[] pattern = null; 7459 switch (effectId) { 7460 case HapticFeedbackConstants.LONG_PRESS: 7461 pattern = mLongPressVibePattern; 7462 break; 7463 case HapticFeedbackConstants.VIRTUAL_KEY: 7464 pattern = mVirtualKeyVibePattern; 7465 break; 7466 case HapticFeedbackConstants.KEYBOARD_TAP: 7467 pattern = mKeyboardTapVibePattern; 7468 break; 7469 case HapticFeedbackConstants.CLOCK_TICK: 7470 pattern = mClockTickVibePattern; 7471 break; 7472 case HapticFeedbackConstants.CALENDAR_DATE: 7473 pattern = mCalendarDateVibePattern; 7474 break; 7475 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 7476 pattern = mSafeModeDisabledVibePattern; 7477 break; 7478 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 7479 pattern = mSafeModeEnabledVibePattern; 7480 break; 7481 case HapticFeedbackConstants.CONTEXT_CLICK: 7482 pattern = mContextClickVibePattern; 7483 break; 7484 default: 7485 return false; 7486 } 7487 int owningUid; 7488 String owningPackage; 7489 if (win != null) { 7490 owningUid = win.getOwningUid(); 7491 owningPackage = win.getOwningPackage(); 7492 } else { 7493 owningUid = android.os.Process.myUid(); 7494 owningPackage = mContext.getOpPackageName(); 7495 } 7496 if (pattern.length == 1) { 7497 // One-shot vibration 7498 mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES); 7499 } else { 7500 // Pattern vibration 7501 mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES); 7502 } 7503 return true; 7504 } 7505 7506 @Override 7507 public void keepScreenOnStartedLw() { 7508 } 7509 7510 @Override 7511 public void keepScreenOnStoppedLw() { 7512 if (isKeyguardShowingAndNotOccluded()) { 7513 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 7514 } 7515 } 7516 7517 private int updateSystemUiVisibilityLw() { 7518 // If there is no window focused, there will be nobody to handle the events 7519 // anyway, so just hang on in whatever state we're in until things settle down. 7520 WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow 7521 : mTopFullscreenOpaqueWindowState; 7522 if (winCandidate == null) { 7523 return 0; 7524 } 7525 if (winCandidate.getAttrs().token == mImmersiveModeConfirmation.getWindowToken()) { 7526 // The immersive mode confirmation should never affect the system bar visibility, 7527 // otherwise it will unhide the navigation bar and hide itself. 7528 winCandidate = isStatusBarKeyguard() ? mStatusBar : mTopFullscreenOpaqueWindowState; 7529 if (winCandidate == null) { 7530 return 0; 7531 } 7532 } 7533 final WindowState win = winCandidate; 7534 if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) { 7535 // We are updating at a point where the keyguard has gotten 7536 // focus, but we were last in a state where the top window is 7537 // hiding it. This is probably because the keyguard as been 7538 // shown while the top window was displayed, so we want to ignore 7539 // it here because this is just a very transient change and it 7540 // will quickly lose focus once it correctly gets hidden. 7541 return 0; 7542 } 7543 7544 int tmpVisibility = PolicyControl.getSystemUiVisibility(win, null) 7545 & ~mResettingSystemUiFlags 7546 & ~mForceClearedSystemUiFlags; 7547 if (mForcingShowNavBar && win.getSurfaceLayer() < mForcingShowNavBarLayer) { 7548 tmpVisibility &= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS); 7549 } 7550 7551 final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */, 7552 mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState); 7553 final int dockedVisibility = updateLightStatusBarLw(0 /* vis */, 7554 mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState); 7555 mWindowManagerFuncs.getStackBounds(HOME_STACK_ID, mNonDockedStackBounds); 7556 mWindowManagerFuncs.getStackBounds(DOCKED_STACK_ID, mDockedStackBounds); 7557 final int visibility = updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility); 7558 final int diff = visibility ^ mLastSystemUiFlags; 7559 final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags; 7560 final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags; 7561 final boolean needsMenu = win.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 7562 if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0 && mLastFocusNeedsMenu == needsMenu 7563 && mFocusedApp == win.getAppToken() 7564 && mLastNonDockedStackBounds.equals(mNonDockedStackBounds) 7565 && mLastDockedStackBounds.equals(mDockedStackBounds)) { 7566 return 0; 7567 } 7568 mLastSystemUiFlags = visibility; 7569 mLastFullscreenStackSysUiFlags = fullscreenVisibility; 7570 mLastDockedStackSysUiFlags = dockedVisibility; 7571 mLastFocusNeedsMenu = needsMenu; 7572 mFocusedApp = win.getAppToken(); 7573 final Rect fullscreenStackBounds = new Rect(mNonDockedStackBounds); 7574 final Rect dockedStackBounds = new Rect(mDockedStackBounds); 7575 mHandler.post(new Runnable() { 7576 @Override 7577 public void run() { 7578 StatusBarManagerInternal statusbar = getStatusBarManagerInternal(); 7579 if (statusbar != null) { 7580 statusbar.setSystemUiVisibility(visibility, fullscreenVisibility, 7581 dockedVisibility, 0xffffffff, fullscreenStackBounds, 7582 dockedStackBounds, win.toString()); 7583 statusbar.topAppWindowChanged(needsMenu); 7584 } 7585 } 7586 }); 7587 return diff; 7588 } 7589 7590 private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) { 7591 WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded 7592 ? mStatusBar 7593 : opaqueOrDimming; 7594 7595 if (statusColorWin != null) { 7596 if (statusColorWin == opaque) { 7597 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7598 // its light flag. 7599 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7600 vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null) 7601 & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7602 } else if (statusColorWin != null && statusColorWin.isDimming()) { 7603 // Otherwise if it's dimming, clear the light flag. 7604 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7605 } 7606 } 7607 return vis; 7608 } 7609 7610 private int updateLightNavigationBarLw(int vis, WindowState opaque, 7611 WindowState opaqueOrDimming) { 7612 final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw(); 7613 7614 final WindowState navColorWin; 7615 if (imeWin != null && imeWin.isVisibleLw()) { 7616 navColorWin = imeWin; 7617 } else { 7618 navColorWin = opaqueOrDimming; 7619 } 7620 7621 if (navColorWin != null) { 7622 if (navColorWin == opaque) { 7623 // If the top fullscreen-or-dimming window is also the top fullscreen, respect 7624 // its light flag. 7625 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7626 vis |= PolicyControl.getSystemUiVisibility(navColorWin, null) 7627 & View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7628 } else if (navColorWin.isDimming() || navColorWin == imeWin) { 7629 // Otherwise if it's dimming or it's the IME window, clear the light flag. 7630 vis &= ~View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR; 7631 } 7632 } 7633 return vis; 7634 } 7635 7636 private boolean drawsSystemBarBackground(WindowState win) { 7637 return win == null || (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0; 7638 } 7639 7640 private boolean forcesDrawStatusBarBackground(WindowState win) { 7641 return win == null || (win.getAttrs().privateFlags 7642 & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0; 7643 } 7644 7645 private int updateSystemBarsLw(WindowState win, int oldVis, int vis) { 7646 final boolean dockedStackVisible = mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID); 7647 final boolean freeformStackVisible = 7648 mWindowManagerInternal.isStackVisible(FREEFORM_WORKSPACE_STACK_ID); 7649 final boolean resizing = mWindowManagerInternal.isDockedDividerResizing(); 7650 7651 // We need to force system bars when the docked stack is visible, when the freeform stack 7652 // is visible but also when we are resizing for the transitions when docked stack 7653 // visibility changes. 7654 mForceShowSystemBars = dockedStackVisible || freeformStackVisible || resizing; 7655 final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard; 7656 7657 // apply translucent bar vis flags 7658 WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded 7659 ? mStatusBar 7660 : mTopFullscreenOpaqueWindowState; 7661 vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7662 vis = mNavigationBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis); 7663 final int dockedVis = mStatusBarController.applyTranslucentFlagLw( 7664 mTopDockedOpaqueWindowState, 0, 0); 7665 7666 final boolean fullscreenDrawsStatusBarBackground = 7667 (drawsSystemBarBackground(mTopFullscreenOpaqueWindowState) 7668 && (vis & View.STATUS_BAR_TRANSLUCENT) == 0) 7669 || forcesDrawStatusBarBackground(mTopFullscreenOpaqueWindowState); 7670 final boolean dockedDrawsStatusBarBackground = 7671 (drawsSystemBarBackground(mTopDockedOpaqueWindowState) 7672 && (dockedVis & View.STATUS_BAR_TRANSLUCENT) == 0) 7673 || forcesDrawStatusBarBackground(mTopDockedOpaqueWindowState); 7674 7675 // prevent status bar interaction from clearing certain flags 7676 int type = win.getAttrs().type; 7677 boolean statusBarHasFocus = type == TYPE_STATUS_BAR; 7678 if (statusBarHasFocus && !isStatusBarKeyguard()) { 7679 int flags = View.SYSTEM_UI_FLAG_FULLSCREEN 7680 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION 7681 | View.SYSTEM_UI_FLAG_IMMERSIVE 7682 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY 7683 | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; 7684 if (mKeyguardOccluded) { 7685 flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT; 7686 } 7687 vis = (vis & ~flags) | (oldVis & flags); 7688 } 7689 7690 if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) { 7691 vis |= View.STATUS_BAR_TRANSPARENT; 7692 vis &= ~View.STATUS_BAR_TRANSLUCENT; 7693 } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar) 7694 || forceOpaqueStatusBar) { 7695 vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT); 7696 } 7697 7698 vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing); 7699 7700 // update status bar 7701 boolean immersiveSticky = 7702 (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7703 final boolean hideStatusBarWM = 7704 mTopFullscreenOpaqueWindowState != null 7705 && (PolicyControl.getWindowFlags(mTopFullscreenOpaqueWindowState, null) 7706 & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; 7707 final boolean hideStatusBarSysui = 7708 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 7709 final boolean hideNavBarSysui = 7710 (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0; 7711 7712 final boolean transientStatusBarAllowed = mStatusBar != null 7713 && (statusBarHasFocus || (!mForceShowSystemBars 7714 && (hideStatusBarWM || (hideStatusBarSysui && immersiveSticky)))); 7715 7716 final boolean transientNavBarAllowed = mNavigationBar != null 7717 && !mForceShowSystemBars && hideNavBarSysui && immersiveSticky; 7718 7719 final long now = SystemClock.uptimeMillis(); 7720 final boolean pendingPanic = mPendingPanicGestureUptime != 0 7721 && now - mPendingPanicGestureUptime <= PANIC_GESTURE_EXPIRATION; 7722 if (pendingPanic && hideNavBarSysui && !isStatusBarKeyguard() && mKeyguardDrawComplete) { 7723 // The user performed the panic gesture recently, we're about to hide the bars, 7724 // we're no longer on the Keyguard and the screen is ready. We can now request the bars. 7725 mPendingPanicGestureUptime = 0; 7726 mStatusBarController.showTransient(); 7727 if (!isNavBarEmpty(vis)) { 7728 mNavigationBarController.showTransient(); 7729 } 7730 } 7731 7732 final boolean denyTransientStatus = mStatusBarController.isTransientShowRequested() 7733 && !transientStatusBarAllowed && hideStatusBarSysui; 7734 final boolean denyTransientNav = mNavigationBarController.isTransientShowRequested() 7735 && !transientNavBarAllowed; 7736 if (denyTransientStatus || denyTransientNav || mForceShowSystemBars) { 7737 // clear the clearable flags instead 7738 clearClearableFlagsLw(); 7739 vis &= ~View.SYSTEM_UI_CLEARABLE_FLAGS; 7740 } 7741 7742 final boolean immersive = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0; 7743 immersiveSticky = (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0; 7744 final boolean navAllowedHidden = immersive || immersiveSticky; 7745 7746 if (hideNavBarSysui && !navAllowedHidden && windowTypeToLayerLw(win.getBaseType()) 7747 > windowTypeToLayerLw(TYPE_INPUT_CONSUMER)) { 7748 // We can't hide the navbar from this window otherwise the input consumer would not get 7749 // the input events. 7750 vis = (vis & ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); 7751 } 7752 7753 vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis); 7754 7755 // update navigation bar 7756 boolean oldImmersiveMode = isImmersiveMode(oldVis); 7757 boolean newImmersiveMode = isImmersiveMode(vis); 7758 if (win != null && oldImmersiveMode != newImmersiveMode) { 7759 final String pkg = win.getOwningPackage(); 7760 mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode, 7761 isUserSetupComplete(), isNavBarEmpty(win.getSystemUiVisibility())); 7762 } 7763 7764 vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis); 7765 7766 vis = updateLightNavigationBarLw(vis, mTopFullscreenOpaqueWindowState, 7767 mTopFullscreenOpaqueOrDimmingWindowState); 7768 7769 return vis; 7770 } 7771 7772 /** 7773 * @return the current visibility flags with the nav-bar opacity related flags toggled based 7774 * on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}. 7775 */ 7776 private int configureNavBarOpacity(int visibility, boolean dockedStackVisible, 7777 boolean freeformStackVisible, boolean isDockedDividerResizing) { 7778 if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) { 7779 if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) { 7780 visibility = setNavBarOpaqueFlag(visibility); 7781 } 7782 } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) { 7783 if (isDockedDividerResizing) { 7784 visibility = setNavBarOpaqueFlag(visibility); 7785 } else if (freeformStackVisible) { 7786 visibility = setNavBarTranslucentFlag(visibility); 7787 } else { 7788 visibility = setNavBarOpaqueFlag(visibility); 7789 } 7790 } 7791 7792 if (!areTranslucentBarsAllowed()) { 7793 visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT; 7794 } 7795 return visibility; 7796 } 7797 7798 private int setNavBarOpaqueFlag(int visibility) { 7799 return visibility &= ~(View.NAVIGATION_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSPARENT); 7800 } 7801 7802 private int setNavBarTranslucentFlag(int visibility) { 7803 visibility &= ~View.NAVIGATION_BAR_TRANSPARENT; 7804 return visibility |= View.NAVIGATION_BAR_TRANSLUCENT; 7805 } 7806 7807 private void clearClearableFlagsLw() { 7808 int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS; 7809 if (newVal != mResettingSystemUiFlags) { 7810 mResettingSystemUiFlags = newVal; 7811 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 7812 } 7813 } 7814 7815 private boolean isImmersiveMode(int vis) { 7816 final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; 7817 return mNavigationBar != null 7818 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 7819 && (vis & flags) != 0 7820 && canHideNavigationBar(); 7821 } 7822 7823 private static boolean isNavBarEmpty(int systemUiFlags) { 7824 final int disableNavigationBar = (View.STATUS_BAR_DISABLE_HOME 7825 | View.STATUS_BAR_DISABLE_BACK 7826 | View.STATUS_BAR_DISABLE_RECENT); 7827 7828 return (systemUiFlags & disableNavigationBar) == disableNavigationBar; 7829 } 7830 7831 /** 7832 * @return whether the navigation or status bar can be made translucent 7833 * 7834 * This should return true unless touch exploration is not enabled or 7835 * R.boolean.config_enableTranslucentDecor is false. 7836 */ 7837 private boolean areTranslucentBarsAllowed() { 7838 return mTranslucentDecorEnabled; 7839 } 7840 7841 // Use this instead of checking config_showNavigationBar so that it can be consistently 7842 // overridden by qemu.hw.mainkeys in the emulator. 7843 @Override 7844 public boolean hasNavigationBar() { 7845 return mHasNavigationBar; 7846 } 7847 7848 @Override 7849 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 7850 mLastInputMethodWindow = ime; 7851 mLastInputMethodTargetWindow = target; 7852 } 7853 7854 @Override 7855 public int getInputMethodWindowVisibleHeightLw() { 7856 return mDockBottom - mCurBottom; 7857 } 7858 7859 @Override 7860 public void setCurrentUserLw(int newUserId) { 7861 mCurrentUserId = newUserId; 7862 if (mKeyguardDelegate != null) { 7863 mKeyguardDelegate.setCurrentUser(newUserId); 7864 } 7865 StatusBarManagerInternal statusBar = getStatusBarManagerInternal(); 7866 if (statusBar != null) { 7867 statusBar.setCurrentUser(newUserId); 7868 } 7869 setLastInputMethodWindowLw(null, null); 7870 } 7871 7872 @Override 7873 public void setSwitchingUser(boolean switching) { 7874 mKeyguardDelegate.setSwitchingUser(switching); 7875 } 7876 7877 @Override 7878 public boolean canMagnifyWindow(int windowType) { 7879 switch (windowType) { 7880 case WindowManager.LayoutParams.TYPE_INPUT_METHOD: 7881 case WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG: 7882 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR: 7883 case WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY: { 7884 return false; 7885 } 7886 } 7887 return true; 7888 } 7889 7890 @Override 7891 public boolean isTopLevelWindow(int windowType) { 7892 if (windowType >= WindowManager.LayoutParams.FIRST_SUB_WINDOW 7893 && windowType <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 7894 return (windowType == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG); 7895 } 7896 return true; 7897 } 7898 7899 @Override 7900 public boolean shouldRotateSeamlessly(int oldRotation, int newRotation) { 7901 // For the upside down rotation we don't rotate seamlessly as the navigation 7902 // bar moves position. 7903 // Note most apps (using orientation:sensor or user as opposed to fullSensor) 7904 // will not enter the reverse portrait orientation, so actually the 7905 // orientation won't change at all. 7906 if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) { 7907 return false; 7908 } 7909 // If the navigation bar can't change sides, then it will 7910 // jump when we change orientations and we don't rotate 7911 // seamlessly. 7912 if (!mNavigationBarCanMove) { 7913 return false; 7914 } 7915 int delta = newRotation - oldRotation; 7916 if (delta < 0) delta += 4; 7917 // Likewise we don't rotate seamlessly for 180 degree rotations 7918 // in this case the surfaces never resize, and our logic to 7919 // revert the transformations on size change will fail. We could 7920 // fix this in the future with the "tagged" frames idea. 7921 if (delta == Surface.ROTATION_180) { 7922 return false; 7923 } 7924 7925 final WindowState w = mTopFullscreenOpaqueWindowState; 7926 if (w != mFocusedWindow) { 7927 return false; 7928 } 7929 7930 // We only enable seamless rotation if the top window has requested 7931 // it and is in the fullscreen opaque state. Seamless rotation 7932 // requires freezing various Surface states and won't work well 7933 // with animations, so we disable it in the animation case for now. 7934 if (w != null && !w.isAnimatingLw() && 7935 ((w.getAttrs().rotationAnimation == ROTATION_ANIMATION_JUMPCUT) || 7936 (w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS))) { 7937 return true; 7938 } 7939 return false; 7940 } 7941 7942 @Override 7943 public void dump(String prefix, PrintWriter pw, String[] args) { 7944 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 7945 pw.print(" mSystemReady="); pw.print(mSystemReady); 7946 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 7947 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 7948 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 7949 pw.print(" mCameraLensCoverState="); pw.print(mCameraLensCoverState); 7950 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 7951 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 7952 || mForceClearedSystemUiFlags != 0) { 7953 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 7954 pw.print(Integer.toHexString(mLastSystemUiFlags)); 7955 pw.print(" mResettingSystemUiFlags=0x"); 7956 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 7957 pw.print(" mForceClearedSystemUiFlags=0x"); 7958 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 7959 } 7960 if (mLastFocusNeedsMenu) { 7961 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 7962 pw.println(mLastFocusNeedsMenu); 7963 } 7964 pw.print(prefix); pw.print("mWakeGestureEnabledSetting="); 7965 pw.println(mWakeGestureEnabledSetting); 7966 7967 pw.print(prefix); pw.print("mSupportAutoRotation="); pw.println(mSupportAutoRotation); 7968 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 7969 pw.print(" mDockMode="); pw.print(mDockMode); 7970 pw.print(" mEnableCarDockHomeCapture="); pw.print(mEnableCarDockHomeCapture); 7971 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 7972 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 7973 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 7974 pw.print(" mUserRotation="); pw.print(mUserRotation); 7975 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 7976 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 7977 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 7978 pw.print(mCarDockEnablesAccelerometer); 7979 pw.print(" mDeskDockEnablesAccelerometer="); 7980 pw.println(mDeskDockEnablesAccelerometer); 7981 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 7982 pw.print(mLidKeyboardAccessibility); 7983 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 7984 pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock); 7985 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 7986 pw.print(prefix); 7987 pw.print(" mLongPressOnBackBehavior="); pw.println(mLongPressOnBackBehavior); 7988 pw.print(prefix); 7989 pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior); 7990 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior); 7991 pw.print(prefix); 7992 pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior); 7993 pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior); 7994 pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput); 7995 pw.print(prefix); pw.print("mAwake="); pw.println(mAwake); 7996 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 7997 pw.print(" mScreenOnFully="); pw.println(mScreenOnFully); 7998 pw.print(prefix); pw.print("mKeyguardDrawComplete="); pw.print(mKeyguardDrawComplete); 7999 pw.print(" mWindowManagerDrawComplete="); pw.println(mWindowManagerDrawComplete); 8000 pw.print(prefix); pw.print("mOrientationSensorEnabled="); 8001 pw.println(mOrientationSensorEnabled); 8002 pw.print(prefix); pw.print("mOverscanScreen=("); pw.print(mOverscanScreenLeft); 8003 pw.print(","); pw.print(mOverscanScreenTop); 8004 pw.print(") "); pw.print(mOverscanScreenWidth); 8005 pw.print("x"); pw.println(mOverscanScreenHeight); 8006 if (mOverscanLeft != 0 || mOverscanTop != 0 8007 || mOverscanRight != 0 || mOverscanBottom != 0) { 8008 pw.print(prefix); pw.print("mOverscan left="); pw.print(mOverscanLeft); 8009 pw.print(" top="); pw.print(mOverscanTop); 8010 pw.print(" right="); pw.print(mOverscanRight); 8011 pw.print(" bottom="); pw.println(mOverscanBottom); 8012 } 8013 pw.print(prefix); pw.print("mRestrictedOverscanScreen=("); 8014 pw.print(mRestrictedOverscanScreenLeft); 8015 pw.print(","); pw.print(mRestrictedOverscanScreenTop); 8016 pw.print(") "); pw.print(mRestrictedOverscanScreenWidth); 8017 pw.print("x"); pw.println(mRestrictedOverscanScreenHeight); 8018 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 8019 pw.print(","); pw.print(mUnrestrictedScreenTop); 8020 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 8021 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 8022 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 8023 pw.print(","); pw.print(mRestrictedScreenTop); 8024 pw.print(") "); pw.print(mRestrictedScreenWidth); 8025 pw.print("x"); pw.println(mRestrictedScreenHeight); 8026 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 8027 pw.print(","); pw.print(mStableFullscreenTop); 8028 pw.print(")-("); pw.print(mStableFullscreenRight); 8029 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 8030 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 8031 pw.print(","); pw.print(mStableTop); 8032 pw.print(")-("); pw.print(mStableRight); 8033 pw.print(","); pw.print(mStableBottom); pw.println(")"); 8034 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 8035 pw.print(","); pw.print(mSystemTop); 8036 pw.print(")-("); pw.print(mSystemRight); 8037 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 8038 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 8039 pw.print(","); pw.print(mCurTop); 8040 pw.print(")-("); pw.print(mCurRight); 8041 pw.print(","); pw.print(mCurBottom); pw.println(")"); 8042 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 8043 pw.print(","); pw.print(mContentTop); 8044 pw.print(")-("); pw.print(mContentRight); 8045 pw.print(","); pw.print(mContentBottom); pw.println(")"); 8046 pw.print(prefix); pw.print("mVoiceContent=("); pw.print(mVoiceContentLeft); 8047 pw.print(","); pw.print(mVoiceContentTop); 8048 pw.print(")-("); pw.print(mVoiceContentRight); 8049 pw.print(","); pw.print(mVoiceContentBottom); pw.println(")"); 8050 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 8051 pw.print(","); pw.print(mDockTop); 8052 pw.print(")-("); pw.print(mDockRight); 8053 pw.print(","); pw.print(mDockBottom); pw.println(")"); 8054 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 8055 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 8056 pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream); 8057 pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen); 8058 pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken); 8059 if (mLastInputMethodWindow != null) { 8060 pw.print(prefix); pw.print("mLastInputMethodWindow="); 8061 pw.println(mLastInputMethodWindow); 8062 } 8063 if (mLastInputMethodTargetWindow != null) { 8064 pw.print(prefix); pw.print("mLastInputMethodTargetWindow="); 8065 pw.println(mLastInputMethodTargetWindow); 8066 } 8067 if (mStatusBar != null) { 8068 pw.print(prefix); pw.print("mStatusBar="); 8069 pw.print(mStatusBar); pw.print(" isStatusBarKeyguard="); 8070 pw.println(isStatusBarKeyguard()); 8071 } 8072 if (mNavigationBar != null) { 8073 pw.print(prefix); pw.print("mNavigationBar="); 8074 pw.println(mNavigationBar); 8075 } 8076 if (mFocusedWindow != null) { 8077 pw.print(prefix); pw.print("mFocusedWindow="); 8078 pw.println(mFocusedWindow); 8079 } 8080 if (mFocusedApp != null) { 8081 pw.print(prefix); pw.print("mFocusedApp="); 8082 pw.println(mFocusedApp); 8083 } 8084 if (mTopFullscreenOpaqueWindowState != null) { 8085 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 8086 pw.println(mTopFullscreenOpaqueWindowState); 8087 } 8088 if (mTopFullscreenOpaqueOrDimmingWindowState != null) { 8089 pw.print(prefix); pw.print("mTopFullscreenOpaqueOrDimmingWindowState="); 8090 pw.println(mTopFullscreenOpaqueOrDimmingWindowState); 8091 } 8092 if (mForcingShowNavBar) { 8093 pw.print(prefix); pw.print("mForcingShowNavBar="); 8094 pw.println(mForcingShowNavBar); pw.print( "mForcingShowNavBarLayer="); 8095 pw.println(mForcingShowNavBarLayer); 8096 } 8097 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 8098 pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded); 8099 pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged); 8100 pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded); 8101 pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar); 8102 pw.print(" mForceStatusBarFromKeyguard="); 8103 pw.println(mForceStatusBarFromKeyguard); 8104 pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed); 8105 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 8106 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 8107 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 8108 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 8109 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 8110 pw.print(" mIncallBackBehavior="); pw.print(mIncallBackBehavior); 8111 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 8112 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 8113 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 8114 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 8115 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 8116 pw.print(prefix); pw.print("mDemoHdmiRotation="); pw.print(mDemoHdmiRotation); 8117 pw.print(" mDemoHdmiRotationLock="); pw.println(mDemoHdmiRotationLock); 8118 pw.print(prefix); pw.print("mUndockedHdmiRotation="); pw.println(mUndockedHdmiRotation); 8119 8120 mGlobalKeyManager.dump(prefix, pw); 8121 mStatusBarController.dump(pw, prefix); 8122 mNavigationBarController.dump(pw, prefix); 8123 PolicyControl.dump(prefix, pw); 8124 8125 if (mWakeGestureListener != null) { 8126 mWakeGestureListener.dump(pw, prefix); 8127 } 8128 if (mOrientationListener != null) { 8129 mOrientationListener.dump(pw, prefix); 8130 } 8131 if (mBurnInProtectionHelper != null) { 8132 mBurnInProtectionHelper.dump(prefix, pw); 8133 } 8134 if (mKeyguardDelegate != null) { 8135 mKeyguardDelegate.dump(prefix, pw); 8136 } 8137 } 8138} 8139