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