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