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