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