PhoneWindowManager.java revision 79af1dd54c16cde063152922b42c96d72ae9eca8
1/* 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16package com.android.internal.policy.impl; 17 18import android.app.ActivityManager; 19import android.app.ActivityManagerNative; 20import android.app.IUiModeManager; 21import android.app.ProgressDialog; 22import android.app.SearchManager; 23import android.app.UiModeManager; 24import android.content.ActivityNotFoundException; 25import android.content.BroadcastReceiver; 26import android.content.ComponentName; 27import android.content.ContentResolver; 28import android.content.Context; 29import android.content.Intent; 30import android.content.IntentFilter; 31import android.content.ServiceConnection; 32import android.content.pm.ActivityInfo; 33import android.content.pm.PackageManager; 34import android.content.res.CompatibilityInfo; 35import android.content.res.Configuration; 36import android.content.res.Resources; 37import android.content.res.TypedArray; 38import android.database.ContentObserver; 39import android.graphics.PixelFormat; 40import android.graphics.Rect; 41import android.media.AudioManager; 42import android.media.IAudioService; 43import android.os.BatteryManager; 44import android.os.Bundle; 45import android.os.Handler; 46import android.os.IBinder; 47import android.os.IRemoteCallback; 48import android.os.Looper; 49import android.os.Message; 50import android.os.Messenger; 51import android.os.PowerManager; 52import android.os.RemoteException; 53import android.os.ServiceManager; 54import android.os.SystemClock; 55import android.os.SystemProperties; 56import android.os.UEventObserver; 57import android.os.UserHandle; 58import android.os.Vibrator; 59import android.provider.Settings; 60 61import com.android.internal.R; 62import com.android.internal.policy.PolicyManager; 63import com.android.internal.statusbar.IStatusBarService; 64import com.android.internal.telephony.ITelephony; 65import com.android.internal.widget.PointerLocationView; 66 67import android.service.dreams.IDreamManager; 68import android.util.DisplayMetrics; 69import android.util.EventLog; 70import android.util.Log; 71import android.util.Slog; 72import android.util.SparseArray; 73import android.view.Display; 74import android.view.Gravity; 75import android.view.HapticFeedbackConstants; 76import android.view.IApplicationToken; 77import android.view.IWindowManager; 78import android.view.InputChannel; 79import android.view.InputDevice; 80import android.view.InputEvent; 81import android.view.InputEventReceiver; 82import android.view.KeyCharacterMap; 83import android.view.KeyEvent; 84import android.view.MotionEvent; 85import android.view.WindowOrientationListener; 86import android.view.Surface; 87import android.view.View; 88import android.view.ViewConfiguration; 89import android.view.Window; 90import android.view.WindowManager; 91import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; 92import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN; 93import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN; 94import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 95import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; 96import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; 97import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; 98import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; 99import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; 100import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST; 101import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; 102import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; 103import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; 104import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA; 105import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY; 106import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL; 107import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL; 108import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG; 109import static android.view.WindowManager.LayoutParams.TYPE_DRAG; 110import static android.view.WindowManager.LayoutParams.TYPE_DREAM; 111import static android.view.WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER; 112import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD; 113import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; 114import static android.view.WindowManager.LayoutParams.TYPE_PHONE; 115import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; 116import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR; 117import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; 118import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; 119import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL; 120import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL; 121import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; 122import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; 123import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; 124import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; 125import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; 126import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; 127import static android.view.WindowManager.LayoutParams.TYPE_TOAST; 128import static android.view.WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND; 129import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; 130import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; 131import static android.view.WindowManager.LayoutParams.TYPE_POINTER; 132import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; 133import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; 134import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS; 135import android.view.WindowManagerImpl; 136import android.view.WindowManagerPolicy; 137import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; 138import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN; 139import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; 140import android.view.KeyCharacterMap.FallbackAction; 141import android.view.accessibility.AccessibilityEvent; 142import android.view.animation.Animation; 143import android.view.animation.AnimationUtils; 144 145import java.io.File; 146import java.io.FileReader; 147import java.io.IOException; 148import java.io.PrintWriter; 149 150/** 151 * WindowManagerPolicy implementation for the Android phone UI. This 152 * introduces a new method suffix, Lp, for an internal lock of the 153 * PhoneWindowManager. This is used to protect some internal state, and 154 * can be acquired with either thw Lw and Li lock held, so has the restrictions 155 * of both of those when held. 156 */ 157public class PhoneWindowManager implements WindowManagerPolicy { 158 static final String TAG = "WindowManager"; 159 static final boolean DEBUG = false; 160 static final boolean localLOGV = false; 161 static final boolean DEBUG_LAYOUT = false; 162 static final boolean DEBUG_INPUT = false; 163 static final boolean DEBUG_STARTING_WINDOW = false; 164 static final boolean SHOW_STARTING_ANIMATIONS = true; 165 static final boolean SHOW_PROCESSES_ON_ALT_MENU = false; 166 167 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. 168 // No longer recommended for desk docks; still useful in car docks. 169 static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true; 170 static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false; 171 172 static final int LONG_PRESS_POWER_NOTHING = 0; 173 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; 174 static final int LONG_PRESS_POWER_SHUT_OFF = 2; 175 176 // These need to match the documentation/constant in 177 // core/res/res/values/config.xml 178 static final int LONG_PRESS_HOME_NOTHING = 0; 179 static final int LONG_PRESS_HOME_RECENT_DIALOG = 1; 180 static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 2; 181 182 // wallpaper is at the bottom, though the window manager may move it. 183 static final int UNIVERSE_BACKGROUND_LAYER = 1; 184 static final int WALLPAPER_LAYER = 2; 185 static final int APPLICATION_LAYER = 2; 186 static final int PHONE_LAYER = 3; 187 static final int SEARCH_BAR_LAYER = 4; 188 static final int SYSTEM_DIALOG_LAYER = 5; 189 // toasts and the plugged-in battery thing 190 static final int TOAST_LAYER = 6; 191 // SIM errors and unlock. Not sure if this really should be in a high layer. 192 static final int PRIORITY_PHONE_LAYER = 7; 193 // like the ANR / app crashed dialogs 194 static final int SYSTEM_ALERT_LAYER = 8; 195 // on-screen keyboards and other such input method user interfaces go here. 196 static final int INPUT_METHOD_LAYER = 9; 197 // on-screen keyboards and other such input method user interfaces go here. 198 static final int INPUT_METHOD_DIALOG_LAYER = 10; 199 // the keyguard; nothing on top of these can take focus, since they are 200 // responsible for power management when displayed. 201 static final int KEYGUARD_LAYER = 11; 202 static final int KEYGUARD_DIALOG_LAYER = 12; 203 // used for Dreams (screensavers with TYPE_DREAM windows) 204 static final int SCREENSAVER_LAYER = 13; 205 static final int STATUS_BAR_SUB_PANEL_LAYER = 14; 206 static final int STATUS_BAR_LAYER = 15; 207 static final int STATUS_BAR_PANEL_LAYER = 16; 208 // the on-screen volume indicator and controller shown when the user 209 // changes the device volume 210 static final int VOLUME_OVERLAY_LAYER = 17; 211 // things in here CAN NOT take focus, but are shown on top of everything else. 212 static final int SYSTEM_OVERLAY_LAYER = 18; 213 // the navigation bar, if available, shows atop most things 214 static final int NAVIGATION_BAR_LAYER = 19; 215 // some panels (e.g. search) need to show on top of the navigation bar 216 static final int NAVIGATION_BAR_PANEL_LAYER = 20; 217 // system-level error dialogs 218 static final int SYSTEM_ERROR_LAYER = 21; 219 // the drag layer: input for drag-and-drop is associated with this window, 220 // which sits above all other focusable windows 221 static final int DRAG_LAYER = 22; 222 static final int SECURE_SYSTEM_OVERLAY_LAYER = 23; 223 static final int BOOT_PROGRESS_LAYER = 24; 224 // the (mouse) pointer layer 225 static final int POINTER_LAYER = 25; 226 static final int HIDDEN_NAV_CONSUMER_LAYER = 26; 227 228 static final int APPLICATION_MEDIA_SUBLAYER = -2; 229 static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1; 230 static final int APPLICATION_PANEL_SUBLAYER = 1; 231 static final int APPLICATION_SUB_PANEL_SUBLAYER = 2; 232 233 static public final String SYSTEM_DIALOG_REASON_KEY = "reason"; 234 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions"; 235 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps"; 236 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey"; 237 static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist"; 238 239 /** 240 * These are the system UI flags that, when changing, can cause the layout 241 * of the screen to change. 242 */ 243 static final int SYSTEM_UI_CHANGING_LAYOUT = 244 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN; 245 246 /* Table of Application Launch keys. Maps from key codes to intent categories. 247 * 248 * These are special keys that are used to launch particular kinds of applications, 249 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C) 250 * usage page. We don't support quite that many yet... 251 */ 252 static SparseArray<String> sApplicationLaunchKeyCategories; 253 static { 254 sApplicationLaunchKeyCategories = new SparseArray<String>(); 255 sApplicationLaunchKeyCategories.append( 256 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER); 257 sApplicationLaunchKeyCategories.append( 258 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL); 259 sApplicationLaunchKeyCategories.append( 260 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS); 261 sApplicationLaunchKeyCategories.append( 262 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR); 263 sApplicationLaunchKeyCategories.append( 264 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC); 265 sApplicationLaunchKeyCategories.append( 266 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR); 267 } 268 269 /** 270 * Lock protecting internal state. Must not call out into window 271 * manager with lock held. (This lock will be acquired in places 272 * where the window manager is calling in with its own lock held.) 273 */ 274 final Object mLock = new Object(); 275 276 Context mContext; 277 IWindowManager mWindowManager; 278 WindowManagerFuncs mWindowManagerFuncs; 279 PowerManager mPowerManager; 280 IStatusBarService mStatusBarService; 281 final Object mServiceAquireLock = new Object(); 282 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes 283 SearchManager mSearchManager; 284 285 // Vibrator pattern for haptic feedback of a long press. 286 long[] mLongPressVibePattern; 287 288 // Vibrator pattern for haptic feedback of virtual key press. 289 long[] mVirtualKeyVibePattern; 290 291 // Vibrator pattern for a short vibration. 292 long[] mKeyboardTapVibePattern; 293 294 // Vibrator pattern for haptic feedback during boot when safe mode is disabled. 295 long[] mSafeModeDisabledVibePattern; 296 297 // Vibrator pattern for haptic feedback during boot when safe mode is enabled. 298 long[] mSafeModeEnabledVibePattern; 299 300 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */ 301 boolean mEnableShiftMenuBugReports = false; 302 303 boolean mHeadless; 304 boolean mSafeMode; 305 WindowState mStatusBar = null; 306 boolean mHasSystemNavBar; 307 int mStatusBarHeight; 308 WindowState mNavigationBar = null; 309 boolean mHasNavigationBar = false; 310 boolean mCanHideNavigationBar = false; 311 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side? 312 boolean mNavigationBarOnBottom = true; // is the navigation bar on the bottom *right now*? 313 int[] mNavigationBarHeightForRotation = new int[4]; 314 int[] mNavigationBarWidthForRotation = new int[4]; 315 316 WindowState mKeyguard = null; 317 KeyguardViewMediator mKeyguardMediator; 318 GlobalActions mGlobalActions; 319 volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread 320 boolean mPendingPowerKeyUpCanceled; 321 Handler mHandler; 322 WindowState mLastInputMethodWindow = null; 323 WindowState mLastInputMethodTargetWindow = null; 324 325 static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0; 326 static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1; 327 static final int RECENT_APPS_BEHAVIOR_DISMISS = 2; 328 static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 3; 329 330 RecentApplicationsDialog mRecentAppsDialog; 331 int mRecentAppsDialogHeldModifiers; 332 boolean mLanguageSwitchKeyPressed; 333 334 int mLidState = LID_ABSENT; 335 boolean mHaveBuiltInKeyboard; 336 337 boolean mSystemReady; 338 boolean mSystemBooted; 339 boolean mHdmiPlugged; 340 int mUiMode; 341 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED; 342 int mLidOpenRotation; 343 int mCarDockRotation; 344 int mDeskDockRotation; 345 int mHdmiRotation; 346 347 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE; 348 int mUserRotation = Surface.ROTATION_0; 349 boolean mAccelerometerDefault; 350 351 int mAllowAllRotations = -1; 352 boolean mCarDockEnablesAccelerometer; 353 boolean mDeskDockEnablesAccelerometer; 354 int mLidKeyboardAccessibility; 355 int mLidNavigationAccessibility; 356 boolean mLidControlsSleep; 357 int mLongPressOnPowerBehavior = -1; 358 boolean mScreenOnEarly = false; 359 boolean mScreenOnFully = false; 360 boolean mOrientationSensorEnabled = false; 361 int mLastSensorRotation = -1; 362 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 363 boolean mHasSoftInput = false; 364 365 int mPointerLocationMode = 0; // guarded by mLock 366 367 // The last window we were told about in focusChanged. 368 WindowState mFocusedWindow; 369 IApplicationToken mFocusedApp; 370 371 private static final class PointerLocationInputEventReceiver extends InputEventReceiver { 372 private final PointerLocationView mView; 373 374 public PointerLocationInputEventReceiver(InputChannel inputChannel, Looper looper, 375 PointerLocationView view) { 376 super(inputChannel, looper); 377 mView = view; 378 } 379 380 @Override 381 public void onInputEvent(InputEvent event) { 382 boolean handled = false; 383 try { 384 if (event instanceof MotionEvent 385 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 386 final MotionEvent motionEvent = (MotionEvent)event; 387 mView.addPointerEvent(motionEvent); 388 handled = true; 389 } 390 } finally { 391 finishInputEvent(event, handled); 392 } 393 } 394 } 395 396 // Pointer location view state, only modified on the mHandler Looper. 397 PointerLocationInputEventReceiver mPointerLocationInputEventReceiver; 398 PointerLocationView mPointerLocationView; 399 InputChannel mPointerLocationInputChannel; 400 401 // The current size of the screen; really; (ir)regardless of whether the status 402 // bar can be hidden or not 403 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop; 404 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight; 405 // The current size of the screen; these may be different than (0,0)-(dw,dh) 406 // if the status bar can't be hidden; in that case it effectively carves out 407 // that area of the display from all other windows. 408 int mRestrictedScreenLeft, mRestrictedScreenTop; 409 int mRestrictedScreenWidth, mRestrictedScreenHeight; 410 // During layout, the current screen borders accounting for any currently 411 // visible system UI elements. 412 int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom; 413 // For applications requesting stable content insets, these are them. 414 int mStableLeft, mStableTop, mStableRight, mStableBottom; 415 // For applications requesting stable content insets but have also set the 416 // fullscreen window flag, these are the stable dimensions without the status bar. 417 int mStableFullscreenLeft, mStableFullscreenTop; 418 int mStableFullscreenRight, mStableFullscreenBottom; 419 // During layout, the current screen borders with all outer decoration 420 // (status bar, input method dock) accounted for. 421 int mCurLeft, mCurTop, mCurRight, mCurBottom; 422 // During layout, the frame in which content should be displayed 423 // to the user, accounting for all screen decoration except for any 424 // space they deem as available for other content. This is usually 425 // the same as mCur*, but may be larger if the screen decor has supplied 426 // content insets. 427 int mContentLeft, mContentTop, mContentRight, mContentBottom; 428 // During layout, the current screen borders along which input method 429 // windows are placed. 430 int mDockLeft, mDockTop, mDockRight, mDockBottom; 431 // During layout, the layer at which the doc window is placed. 432 int mDockLayer; 433 // During layout, this is the layer of the status bar. 434 int mStatusBarLayer; 435 int mLastSystemUiFlags; 436 // Bits that we are in the process of clearing, so we want to prevent 437 // them from being set by applications until everything has been updated 438 // to have them clear. 439 int mResettingSystemUiFlags = 0; 440 // Bits that we are currently always keeping cleared. 441 int mForceClearedSystemUiFlags = 0; 442 // What we last reported to system UI about whether the compatibility 443 // menu needs to be displayed. 444 boolean mLastFocusNeedsMenu = false; 445 446 FakeWindow mHideNavFakeWindow = null; 447 448 static final Rect mTmpParentFrame = new Rect(); 449 static final Rect mTmpDisplayFrame = new Rect(); 450 static final Rect mTmpContentFrame = new Rect(); 451 static final Rect mTmpVisibleFrame = new Rect(); 452 static final Rect mTmpNavigationFrame = new Rect(); 453 454 WindowState mTopFullscreenOpaqueWindowState; 455 boolean mTopIsFullscreen; 456 boolean mForceStatusBar; 457 boolean mHideLockScreen; 458 boolean mDismissKeyguard; 459 boolean mHomePressed; 460 boolean mHomeLongPressed; 461 Intent mHomeIntent; 462 Intent mCarDockIntent; 463 Intent mDeskDockIntent; 464 boolean mSearchKeyShortcutPending; 465 boolean mConsumeSearchKeyUp; 466 boolean mAssistKeyLongPressed; 467 468 // support for activating the lock screen while the screen is on 469 boolean mAllowLockscreenWhenOn; 470 int mLockScreenTimeout; 471 boolean mLockScreenTimerActive; 472 473 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.) 474 int mEndcallBehavior; 475 476 // Behavior of POWER button while in-call and screen on. 477 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.) 478 int mIncallPowerBehavior; 479 480 Display mDisplay; 481 482 int mLandscapeRotation = 0; // default landscape rotation 483 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation 484 int mPortraitRotation = 0; // default portrait rotation 485 int mUpsideDownRotation = 0; // "other" portrait rotation 486 487 // What we do when the user long presses on home 488 private int mLongPressOnHomeBehavior = -1; 489 490 // Screenshot trigger states 491 // Time to volume and power must be pressed within this interval of each other. 492 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150; 493 private boolean mScreenshotChordEnabled; 494 private boolean mVolumeDownKeyTriggered; 495 private long mVolumeDownKeyTime; 496 private boolean mVolumeDownKeyConsumedByScreenshotChord; 497 private boolean mVolumeUpKeyTriggered; 498 private boolean mPowerKeyTriggered; 499 private long mPowerKeyTime; 500 501 ShortcutManager mShortcutManager; 502 PowerManager.WakeLock mBroadcastWakeLock; 503 boolean mHavePendingMediaKeyRepeatWithWakeLock; 504 505 // Fallback actions by key code. 506 private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions = 507 new SparseArray<KeyCharacterMap.FallbackAction>(); 508 509 private static final int MSG_ENABLE_POINTER_LOCATION = 1; 510 private static final int MSG_DISABLE_POINTER_LOCATION = 2; 511 private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; 512 private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4; 513 514 private class PolicyHandler extends Handler { 515 @Override 516 public void handleMessage(Message msg) { 517 switch (msg.what) { 518 case MSG_ENABLE_POINTER_LOCATION: 519 enablePointerLocation(); 520 break; 521 case MSG_DISABLE_POINTER_LOCATION: 522 disablePointerLocation(); 523 break; 524 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK: 525 dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj); 526 break; 527 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK: 528 dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj); 529 break; 530 } 531 } 532 } 533 534 private UEventObserver mHDMIObserver = new UEventObserver() { 535 @Override 536 public void onUEvent(UEventObserver.UEvent event) { 537 setHdmiPlugged("1".equals(event.get("SWITCH_STATE"))); 538 } 539 }; 540 541 class SettingsObserver extends ContentObserver { 542 SettingsObserver(Handler handler) { 543 super(handler); 544 } 545 546 void observe() { 547 ContentResolver resolver = mContext.getContentResolver(); 548 resolver.registerContentObserver(Settings.System.getUriFor( 549 Settings.System.END_BUTTON_BEHAVIOR), false, this); 550 resolver.registerContentObserver(Settings.Secure.getUriFor( 551 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this); 552 resolver.registerContentObserver(Settings.System.getUriFor( 553 Settings.System.ACCELEROMETER_ROTATION), false, this); 554 resolver.registerContentObserver(Settings.System.getUriFor( 555 Settings.System.USER_ROTATION), false, this); 556 resolver.registerContentObserver(Settings.System.getUriFor( 557 Settings.System.SCREEN_OFF_TIMEOUT), false, this); 558 resolver.registerContentObserver(Settings.System.getUriFor( 559 Settings.System.POINTER_LOCATION), false, this); 560 resolver.registerContentObserver(Settings.Secure.getUriFor( 561 Settings.Secure.DEFAULT_INPUT_METHOD), false, this); 562 resolver.registerContentObserver(Settings.System.getUriFor( 563 "fancy_rotation_anim"), false, this); 564 updateSettings(); 565 } 566 567 @Override public void onChange(boolean selfChange) { 568 updateSettings(); 569 updateRotation(false); 570 } 571 } 572 573 class MyOrientationListener extends WindowOrientationListener { 574 MyOrientationListener(Context context) { 575 super(context); 576 } 577 578 @Override 579 public void onProposedRotationChanged(int rotation) { 580 if (localLOGV) Log.v(TAG, "onProposedRotationChanged, rotation=" + rotation); 581 updateRotation(false); 582 } 583 } 584 MyOrientationListener mOrientationListener; 585 586 IStatusBarService getStatusBarService() { 587 synchronized (mServiceAquireLock) { 588 if (mStatusBarService == null) { 589 mStatusBarService = IStatusBarService.Stub.asInterface( 590 ServiceManager.getService("statusbar")); 591 } 592 return mStatusBarService; 593 } 594 } 595 596 /* 597 * We always let the sensor be switched on by default except when 598 * the user has explicitly disabled sensor based rotation or when the 599 * screen is switched off. 600 */ 601 boolean needSensorRunningLp() { 602 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 603 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 604 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT 605 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) { 606 // If the application has explicitly requested to follow the 607 // orientation, then we need to turn the sensor or. 608 return true; 609 } 610 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) || 611 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK 612 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 613 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) { 614 // enable accelerometer if we are docked in a dock that enables accelerometer 615 // orientation management, 616 return true; 617 } 618 if (mUserRotationMode == USER_ROTATION_LOCKED) { 619 // If the setting for using the sensor by default is enabled, then 620 // we will always leave it on. Note that the user could go to 621 // a window that forces an orientation that does not use the 622 // sensor and in theory we could turn it off... however, when next 623 // turning it on we won't have a good value for the current 624 // orientation for a little bit, which can cause orientation 625 // changes to lag, so we'd like to keep it always on. (It will 626 // still be turned off when the screen is off.) 627 return false; 628 } 629 return true; 630 } 631 632 /* 633 * Various use cases for invoking this function 634 * screen turning off, should always disable listeners if already enabled 635 * screen turned on and current app has sensor based orientation, enable listeners 636 * if not already enabled 637 * screen turned on and current app does not have sensor orientation, disable listeners if 638 * already enabled 639 * screen turning on and current app has sensor based orientation, enable listeners if needed 640 * screen turning on and current app has nosensor based orientation, do nothing 641 */ 642 void updateOrientationListenerLp() { 643 if (!mOrientationListener.canDetectOrientation()) { 644 // If sensor is turned off or nonexistent for some reason 645 return; 646 } 647 //Could have been invoked due to screen turning on or off or 648 //change of the currently visible window's orientation 649 if (localLOGV) Log.v(TAG, "Screen status="+mScreenOnEarly+ 650 ", current orientation="+mCurrentAppOrientation+ 651 ", SensorEnabled="+mOrientationSensorEnabled); 652 boolean disable = true; 653 if (mScreenOnEarly) { 654 if (needSensorRunningLp()) { 655 disable = false; 656 //enable listener if not already enabled 657 if (!mOrientationSensorEnabled) { 658 mOrientationListener.enable(); 659 if(localLOGV) Log.v(TAG, "Enabling listeners"); 660 mOrientationSensorEnabled = true; 661 } 662 } 663 } 664 //check if sensors need to be disabled 665 if (disable && mOrientationSensorEnabled) { 666 mOrientationListener.disable(); 667 if(localLOGV) Log.v(TAG, "Disabling listeners"); 668 mOrientationSensorEnabled = false; 669 } 670 } 671 672 private void interceptPowerKeyDown(boolean handled) { 673 mPowerKeyHandled = handled; 674 if (!handled) { 675 mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout()); 676 } 677 } 678 679 private boolean interceptPowerKeyUp(boolean canceled) { 680 if (!mPowerKeyHandled) { 681 mHandler.removeCallbacks(mPowerLongPress); 682 return !canceled; 683 } 684 return false; 685 } 686 687 private void cancelPendingPowerKeyAction() { 688 if (!mPowerKeyHandled) { 689 mHandler.removeCallbacks(mPowerLongPress); 690 } 691 if (mPowerKeyTriggered) { 692 mPendingPowerKeyUpCanceled = true; 693 } 694 } 695 696 private void interceptScreenshotChord() { 697 if (mScreenshotChordEnabled 698 && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) { 699 final long now = SystemClock.uptimeMillis(); 700 if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS 701 && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) { 702 mVolumeDownKeyConsumedByScreenshotChord = true; 703 cancelPendingPowerKeyAction(); 704 705 mHandler.postDelayed(mScreenshotChordLongPress, 706 ViewConfiguration.getGlobalActionKeyTimeout()); 707 } 708 } 709 } 710 711 private void cancelPendingScreenshotChordAction() { 712 mHandler.removeCallbacks(mScreenshotChordLongPress); 713 } 714 715 private final Runnable mPowerLongPress = new Runnable() { 716 public void run() { 717 // The context isn't read 718 if (mLongPressOnPowerBehavior < 0) { 719 mLongPressOnPowerBehavior = mContext.getResources().getInteger( 720 com.android.internal.R.integer.config_longPressOnPowerBehavior); 721 } 722 switch (mLongPressOnPowerBehavior) { 723 case LONG_PRESS_POWER_NOTHING: 724 break; 725 case LONG_PRESS_POWER_GLOBAL_ACTIONS: 726 mPowerKeyHandled = true; 727 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 728 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); 729 showGlobalActionsDialog(); 730 break; 731 case LONG_PRESS_POWER_SHUT_OFF: 732 mPowerKeyHandled = true; 733 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 734 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); 735 mWindowManagerFuncs.shutdown(); 736 break; 737 } 738 } 739 }; 740 741 private final Runnable mScreenshotChordLongPress = new Runnable() { 742 public void run() { 743 takeScreenshot(); 744 } 745 }; 746 747 void showGlobalActionsDialog() { 748 if (mGlobalActions == null) { 749 mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs); 750 } 751 final boolean keyguardShowing = keyguardIsShowingTq(); 752 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned()); 753 if (keyguardShowing) { 754 // since it took two seconds of long press to bring this up, 755 // poke the wake lock so they have some time to see the dialog. 756 mKeyguardMediator.pokeWakelock(); 757 } 758 } 759 760 boolean isDeviceProvisioned() { 761 return Settings.Secure.getInt( 762 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0; 763 } 764 765 private void handleLongPressOnHome() { 766 // We can't initialize this in init() since the configuration hasn't been loaded yet. 767 if (mLongPressOnHomeBehavior < 0) { 768 mLongPressOnHomeBehavior 769 = mContext.getResources().getInteger(R.integer.config_longPressOnHomeBehavior); 770 if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING || 771 mLongPressOnHomeBehavior > LONG_PRESS_HOME_RECENT_SYSTEM_UI) { 772 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING; 773 } 774 } 775 776 if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) { 777 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 778 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS); 779 780 // Eat the longpress so it won't dismiss the recent apps dialog when 781 // the user lets go of the home key 782 mHomeLongPressed = true; 783 } 784 785 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) { 786 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS); 787 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) { 788 try { 789 IStatusBarService statusbar = getStatusBarService(); 790 if (statusbar != null) { 791 statusbar.toggleRecentApps(); 792 } 793 } catch (RemoteException e) { 794 Slog.e(TAG, "RemoteException when showing recent apps", e); 795 // re-acquire status bar service next time it is needed. 796 mStatusBarService = null; 797 } 798 } 799 } 800 801 /** 802 * Create (if necessary) and show or dismiss the recent apps dialog according 803 * according to the requested behavior. 804 */ 805 void showOrHideRecentAppsDialog(final int behavior) { 806 mHandler.post(new Runnable() { 807 @Override 808 public void run() { 809 if (mRecentAppsDialog == null) { 810 mRecentAppsDialog = new RecentApplicationsDialog(mContext); 811 } 812 if (mRecentAppsDialog.isShowing()) { 813 switch (behavior) { 814 case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS: 815 case RECENT_APPS_BEHAVIOR_DISMISS: 816 mRecentAppsDialog.dismiss(); 817 break; 818 case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH: 819 mRecentAppsDialog.dismissAndSwitch(); 820 break; 821 case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW: 822 default: 823 break; 824 } 825 } else { 826 switch (behavior) { 827 case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS: 828 mRecentAppsDialog.show(); 829 break; 830 case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW: 831 try { 832 mWindowManager.setInTouchMode(false); 833 } catch (RemoteException e) { 834 } 835 mRecentAppsDialog.show(); 836 break; 837 case RECENT_APPS_BEHAVIOR_DISMISS: 838 case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH: 839 default: 840 break; 841 } 842 } 843 } 844 }); 845 } 846 847 /** {@inheritDoc} */ 848 public void init(Context context, IWindowManager windowManager, 849 WindowManagerFuncs windowManagerFuncs) { 850 mContext = context; 851 mWindowManager = windowManager; 852 mWindowManagerFuncs = windowManagerFuncs; 853 mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0")); 854 if (!mHeadless) { 855 // don't create KeyguardViewMediator if headless 856 mKeyguardMediator = new KeyguardViewMediator(context, this); 857 } 858 mHandler = new PolicyHandler(); 859 mOrientationListener = new MyOrientationListener(mContext); 860 try { 861 mOrientationListener.setCurrentRotation(windowManager.getRotation()); 862 } catch (RemoteException ex) { } 863 SettingsObserver settingsObserver = new SettingsObserver(mHandler); 864 settingsObserver.observe(); 865 mShortcutManager = new ShortcutManager(context, mHandler); 866 mShortcutManager.observe(); 867 mUiMode = context.getResources().getInteger( 868 com.android.internal.R.integer.config_defaultUiModeType); 869 mHomeIntent = new Intent(Intent.ACTION_MAIN, null); 870 mHomeIntent.addCategory(Intent.CATEGORY_HOME); 871 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 872 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 873 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null); 874 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK); 875 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 876 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 877 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null); 878 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK); 879 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 880 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 881 882 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 883 mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 884 "PhoneWindowManager.mBroadcastWakeLock"); 885 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable")); 886 mLidOpenRotation = readRotation( 887 com.android.internal.R.integer.config_lidOpenRotation); 888 mCarDockRotation = readRotation( 889 com.android.internal.R.integer.config_carDockRotation); 890 mDeskDockRotation = readRotation( 891 com.android.internal.R.integer.config_deskDockRotation); 892 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean( 893 com.android.internal.R.bool.config_carDockEnablesAccelerometer); 894 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean( 895 com.android.internal.R.bool.config_deskDockEnablesAccelerometer); 896 mLidKeyboardAccessibility = mContext.getResources().getInteger( 897 com.android.internal.R.integer.config_lidKeyboardAccessibility); 898 mLidNavigationAccessibility = mContext.getResources().getInteger( 899 com.android.internal.R.integer.config_lidNavigationAccessibility); 900 mLidControlsSleep = mContext.getResources().getBoolean( 901 com.android.internal.R.bool.config_lidControlsSleep); 902 // register for dock events 903 IntentFilter filter = new IntentFilter(); 904 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE); 905 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE); 906 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE); 907 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE); 908 filter.addAction(Intent.ACTION_DOCK_EVENT); 909 Intent intent = context.registerReceiver(mDockReceiver, filter); 910 if (intent != null) { 911 // Retrieve current sticky dock event broadcast. 912 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 913 Intent.EXTRA_DOCK_STATE_UNDOCKED); 914 } 915 916 mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE); 917 mLongPressVibePattern = getLongIntArray(mContext.getResources(), 918 com.android.internal.R.array.config_longPressVibePattern); 919 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(), 920 com.android.internal.R.array.config_virtualKeyVibePattern); 921 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(), 922 com.android.internal.R.array.config_keyboardTapVibePattern); 923 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(), 924 com.android.internal.R.array.config_safeModeDisabledVibePattern); 925 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(), 926 com.android.internal.R.array.config_safeModeEnabledVibePattern); 927 928 mScreenshotChordEnabled = mContext.getResources().getBoolean( 929 com.android.internal.R.bool.config_enableScreenshotChord); 930 931 // Controls rotation and the like. 932 initializeHdmiState(); 933 934 // Match current screen state. 935 if (mPowerManager.isScreenOn()) { 936 screenTurningOn(null); 937 } else { 938 screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER); 939 } 940 } 941 942 public void setInitialDisplaySize(Display display, int width, int height, int density) { 943 mDisplay = display; 944 945 int shortSize, longSize; 946 if (width > height) { 947 shortSize = height; 948 longSize = width; 949 mLandscapeRotation = Surface.ROTATION_0; 950 mSeascapeRotation = Surface.ROTATION_180; 951 if (mContext.getResources().getBoolean( 952 com.android.internal.R.bool.config_reverseDefaultRotation)) { 953 mPortraitRotation = Surface.ROTATION_90; 954 mUpsideDownRotation = Surface.ROTATION_270; 955 } else { 956 mPortraitRotation = Surface.ROTATION_270; 957 mUpsideDownRotation = Surface.ROTATION_90; 958 } 959 } else { 960 shortSize = width; 961 longSize = height; 962 mPortraitRotation = Surface.ROTATION_0; 963 mUpsideDownRotation = Surface.ROTATION_180; 964 if (mContext.getResources().getBoolean( 965 com.android.internal.R.bool.config_reverseDefaultRotation)) { 966 mLandscapeRotation = Surface.ROTATION_270; 967 mSeascapeRotation = Surface.ROTATION_90; 968 } else { 969 mLandscapeRotation = Surface.ROTATION_90; 970 mSeascapeRotation = Surface.ROTATION_270; 971 } 972 } 973 974 mStatusBarHeight = mContext.getResources().getDimensionPixelSize( 975 com.android.internal.R.dimen.status_bar_height); 976 977 // Height of the navigation bar when presented horizontally at bottom 978 mNavigationBarHeightForRotation[mPortraitRotation] = 979 mNavigationBarHeightForRotation[mUpsideDownRotation] = 980 mContext.getResources().getDimensionPixelSize( 981 com.android.internal.R.dimen.navigation_bar_height); 982 mNavigationBarHeightForRotation[mLandscapeRotation] = 983 mNavigationBarHeightForRotation[mSeascapeRotation] = 984 mContext.getResources().getDimensionPixelSize( 985 com.android.internal.R.dimen.navigation_bar_height_landscape); 986 987 // Width of the navigation bar when presented vertically along one side 988 mNavigationBarWidthForRotation[mPortraitRotation] = 989 mNavigationBarWidthForRotation[mUpsideDownRotation] = 990 mNavigationBarWidthForRotation[mLandscapeRotation] = 991 mNavigationBarWidthForRotation[mSeascapeRotation] = 992 mContext.getResources().getDimensionPixelSize( 993 com.android.internal.R.dimen.navigation_bar_width); 994 995 // SystemUI (status bar) layout policy 996 int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density; 997 998 if (shortSizeDp < 600) { 999 // 0-599dp: "phone" UI with a separate status & navigation bar 1000 mHasSystemNavBar = false; 1001 mNavigationBarCanMove = true; 1002 } else if (shortSizeDp < 720) { 1003 // 600+dp: "phone" UI with modifications for larger screens 1004 mHasSystemNavBar = false; 1005 mNavigationBarCanMove = false; 1006 } 1007 1008 if (!mHasSystemNavBar) { 1009 mHasNavigationBar = mContext.getResources().getBoolean( 1010 com.android.internal.R.bool.config_showNavigationBar); 1011 // Allow a system property to override this. Used by the emulator. 1012 // See also hasNavigationBar(). 1013 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); 1014 if (! "".equals(navBarOverride)) { 1015 if (navBarOverride.equals("1")) mHasNavigationBar = false; 1016 else if (navBarOverride.equals("0")) mHasNavigationBar = true; 1017 } 1018 } else { 1019 mHasNavigationBar = false; 1020 } 1021 1022 if (mHasSystemNavBar) { 1023 // The system bar is always at the bottom. If you are watching 1024 // a video in landscape, we don't need to hide it if we can still 1025 // show a 16:9 aspect ratio with it. 1026 int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density; 1027 int barHeightDp = mNavigationBarHeightForRotation[mLandscapeRotation] 1028 * DisplayMetrics.DENSITY_DEFAULT / density; 1029 int aspect = ((shortSizeDp-barHeightDp) * 16) / longSizeDp; 1030 // We have computed the aspect ratio with the bar height taken 1031 // out to be 16:aspect. If this is less than 9, then hiding 1032 // the navigation bar will provide more useful space for wide 1033 // screen movies. 1034 mCanHideNavigationBar = aspect < 9; 1035 } else if (mHasNavigationBar) { 1036 // The navigation bar is at the right in landscape; it seems always 1037 // useful to hide it for showing a video. 1038 mCanHideNavigationBar = true; 1039 } else { 1040 mCanHideNavigationBar = false; 1041 } 1042 1043 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) { 1044 mHdmiRotation = mPortraitRotation; 1045 } else { 1046 mHdmiRotation = mLandscapeRotation; 1047 } 1048 } 1049 1050 public void updateSettings() { 1051 ContentResolver resolver = mContext.getContentResolver(); 1052 boolean updateRotation = false; 1053 synchronized (mLock) { 1054 mEndcallBehavior = Settings.System.getInt(resolver, 1055 Settings.System.END_BUTTON_BEHAVIOR, 1056 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT); 1057 mIncallPowerBehavior = Settings.Secure.getInt(resolver, 1058 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, 1059 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT); 1060 1061 // Configure rotation lock. 1062 int userRotation = Settings.System.getInt(resolver, 1063 Settings.System.USER_ROTATION, Surface.ROTATION_0); 1064 if (mUserRotation != userRotation) { 1065 mUserRotation = userRotation; 1066 updateRotation = true; 1067 } 1068 int userRotationMode = Settings.System.getInt(resolver, 1069 Settings.System.ACCELEROMETER_ROTATION, 0) != 0 ? 1070 WindowManagerPolicy.USER_ROTATION_FREE : 1071 WindowManagerPolicy.USER_ROTATION_LOCKED; 1072 if (mUserRotationMode != userRotationMode) { 1073 mUserRotationMode = userRotationMode; 1074 updateRotation = true; 1075 updateOrientationListenerLp(); 1076 } 1077 1078 if (mSystemReady) { 1079 int pointerLocation = Settings.System.getInt(resolver, 1080 Settings.System.POINTER_LOCATION, 0); 1081 if (mPointerLocationMode != pointerLocation) { 1082 mPointerLocationMode = pointerLocation; 1083 mHandler.sendEmptyMessage(pointerLocation != 0 ? 1084 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION); 1085 } 1086 } 1087 // use screen off timeout setting as the timeout for the lockscreen 1088 mLockScreenTimeout = Settings.System.getInt(resolver, 1089 Settings.System.SCREEN_OFF_TIMEOUT, 0); 1090 String imId = Settings.Secure.getString(resolver, 1091 Settings.Secure.DEFAULT_INPUT_METHOD); 1092 boolean hasSoftInput = imId != null && imId.length() > 0; 1093 if (mHasSoftInput != hasSoftInput) { 1094 mHasSoftInput = hasSoftInput; 1095 updateRotation = true; 1096 } 1097 } 1098 if (updateRotation) { 1099 updateRotation(true); 1100 } 1101 } 1102 1103 private void enablePointerLocation() { 1104 if (mPointerLocationView == null) { 1105 mPointerLocationView = new PointerLocationView(mContext); 1106 mPointerLocationView.setPrintCoords(false); 1107 1108 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 1109 WindowManager.LayoutParams.MATCH_PARENT, 1110 WindowManager.LayoutParams.MATCH_PARENT); 1111 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY; 1112 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN 1113 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE 1114 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 1115 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 1116 lp.format = PixelFormat.TRANSLUCENT; 1117 lp.setTitle("PointerLocation"); 1118 WindowManager wm = (WindowManager) 1119 mContext.getSystemService(Context.WINDOW_SERVICE); 1120 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL; 1121 wm.addView(mPointerLocationView, lp); 1122 1123 mPointerLocationInputChannel = 1124 mWindowManagerFuncs.monitorInput("PointerLocationView"); 1125 mPointerLocationInputEventReceiver = 1126 new PointerLocationInputEventReceiver(mPointerLocationInputChannel, 1127 Looper.myLooper(), mPointerLocationView); 1128 } 1129 } 1130 1131 private void disablePointerLocation() { 1132 if (mPointerLocationInputEventReceiver != null) { 1133 mPointerLocationInputEventReceiver.dispose(); 1134 mPointerLocationInputEventReceiver = null; 1135 } 1136 1137 if (mPointerLocationInputChannel != null) { 1138 mPointerLocationInputChannel.dispose(); 1139 mPointerLocationInputChannel = null; 1140 } 1141 1142 if (mPointerLocationView != null) { 1143 WindowManager wm = (WindowManager) 1144 mContext.getSystemService(Context.WINDOW_SERVICE); 1145 wm.removeView(mPointerLocationView); 1146 mPointerLocationView = null; 1147 } 1148 } 1149 1150 private int readRotation(int resID) { 1151 try { 1152 int rotation = mContext.getResources().getInteger(resID); 1153 switch (rotation) { 1154 case 0: 1155 return Surface.ROTATION_0; 1156 case 90: 1157 return Surface.ROTATION_90; 1158 case 180: 1159 return Surface.ROTATION_180; 1160 case 270: 1161 return Surface.ROTATION_270; 1162 } 1163 } catch (Resources.NotFoundException e) { 1164 // fall through 1165 } 1166 return -1; 1167 } 1168 1169 /** {@inheritDoc} */ 1170 public int checkAddPermission(WindowManager.LayoutParams attrs) { 1171 int type = attrs.type; 1172 1173 if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW 1174 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) { 1175 return WindowManagerImpl.ADD_OKAY; 1176 } 1177 String permission = null; 1178 switch (type) { 1179 case TYPE_TOAST: 1180 // XXX right now the app process has complete control over 1181 // this... should introduce a token to let the system 1182 // monitor/control what they are doing. 1183 break; 1184 case TYPE_DREAM: 1185 case TYPE_INPUT_METHOD: 1186 case TYPE_WALLPAPER: 1187 // The window manager will check these. 1188 break; 1189 case TYPE_PHONE: 1190 case TYPE_PRIORITY_PHONE: 1191 case TYPE_SYSTEM_ALERT: 1192 case TYPE_SYSTEM_ERROR: 1193 case TYPE_SYSTEM_OVERLAY: 1194 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW; 1195 break; 1196 default: 1197 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; 1198 } 1199 if (permission != null) { 1200 if (mContext.checkCallingOrSelfPermission(permission) 1201 != PackageManager.PERMISSION_GRANTED) { 1202 return WindowManagerImpl.ADD_PERMISSION_DENIED; 1203 } 1204 } 1205 return WindowManagerImpl.ADD_OKAY; 1206 } 1207 1208 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) { 1209 switch (attrs.type) { 1210 case TYPE_SYSTEM_OVERLAY: 1211 case TYPE_SECURE_SYSTEM_OVERLAY: 1212 case TYPE_TOAST: 1213 // These types of windows can't receive input events. 1214 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 1215 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 1216 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; 1217 break; 1218 } 1219 } 1220 1221 void readLidState() { 1222 mLidState = mWindowManagerFuncs.getLidState(); 1223 } 1224 1225 private boolean isHidden(int accessibilityMode) { 1226 switch (accessibilityMode) { 1227 case 1: 1228 return mLidState == LID_CLOSED; 1229 case 2: 1230 return mLidState == LID_OPEN; 1231 default: 1232 return false; 1233 } 1234 } 1235 1236 private boolean isBuiltInKeyboardVisible() { 1237 return mHaveBuiltInKeyboard && !isHidden(mLidKeyboardAccessibility); 1238 } 1239 1240 /** {@inheritDoc} */ 1241 public void adjustConfigurationLw(Configuration config, int keyboardPresence, 1242 int navigationPresence) { 1243 mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0; 1244 1245 readLidState(); 1246 applyLidSwitchState(); 1247 1248 if (config.keyboard == Configuration.KEYBOARD_NOKEYS 1249 || (keyboardPresence == PRESENCE_INTERNAL 1250 && isHidden(mLidKeyboardAccessibility))) { 1251 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES; 1252 if (!mHasSoftInput) { 1253 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES; 1254 } 1255 } 1256 1257 if (config.navigation == Configuration.NAVIGATION_NONAV 1258 || (navigationPresence == PRESENCE_INTERNAL 1259 && isHidden(mLidNavigationAccessibility))) { 1260 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES; 1261 } 1262 } 1263 1264 /** {@inheritDoc} */ 1265 public int windowTypeToLayerLw(int type) { 1266 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { 1267 return APPLICATION_LAYER; 1268 } 1269 switch (type) { 1270 case TYPE_STATUS_BAR: 1271 return STATUS_BAR_LAYER; 1272 case TYPE_STATUS_BAR_PANEL: 1273 return STATUS_BAR_PANEL_LAYER; 1274 case TYPE_STATUS_BAR_SUB_PANEL: 1275 return STATUS_BAR_SUB_PANEL_LAYER; 1276 case TYPE_SYSTEM_DIALOG: 1277 return SYSTEM_DIALOG_LAYER; 1278 case TYPE_SEARCH_BAR: 1279 return SEARCH_BAR_LAYER; 1280 case TYPE_PHONE: 1281 return PHONE_LAYER; 1282 case TYPE_KEYGUARD: 1283 return KEYGUARD_LAYER; 1284 case TYPE_KEYGUARD_DIALOG: 1285 return KEYGUARD_DIALOG_LAYER; 1286 case TYPE_SYSTEM_ALERT: 1287 return SYSTEM_ALERT_LAYER; 1288 case TYPE_SYSTEM_ERROR: 1289 return SYSTEM_ERROR_LAYER; 1290 case TYPE_INPUT_METHOD: 1291 return INPUT_METHOD_LAYER; 1292 case TYPE_INPUT_METHOD_DIALOG: 1293 return INPUT_METHOD_DIALOG_LAYER; 1294 case TYPE_VOLUME_OVERLAY: 1295 return VOLUME_OVERLAY_LAYER; 1296 case TYPE_SYSTEM_OVERLAY: 1297 return SYSTEM_OVERLAY_LAYER; 1298 case TYPE_SECURE_SYSTEM_OVERLAY: 1299 return SECURE_SYSTEM_OVERLAY_LAYER; 1300 case TYPE_PRIORITY_PHONE: 1301 return PRIORITY_PHONE_LAYER; 1302 case TYPE_TOAST: 1303 return TOAST_LAYER; 1304 case TYPE_WALLPAPER: 1305 return WALLPAPER_LAYER; 1306 case TYPE_DRAG: 1307 return DRAG_LAYER; 1308 case TYPE_POINTER: 1309 return POINTER_LAYER; 1310 case TYPE_NAVIGATION_BAR: 1311 return NAVIGATION_BAR_LAYER; 1312 case TYPE_NAVIGATION_BAR_PANEL: 1313 return NAVIGATION_BAR_PANEL_LAYER; 1314 case TYPE_BOOT_PROGRESS: 1315 return BOOT_PROGRESS_LAYER; 1316 case TYPE_HIDDEN_NAV_CONSUMER: 1317 return HIDDEN_NAV_CONSUMER_LAYER; 1318 case TYPE_DREAM: 1319 return SCREENSAVER_LAYER; 1320 case TYPE_UNIVERSE_BACKGROUND: 1321 return UNIVERSE_BACKGROUND_LAYER; 1322 } 1323 Log.e(TAG, "Unknown window type: " + type); 1324 return APPLICATION_LAYER; 1325 } 1326 1327 /** {@inheritDoc} */ 1328 public int subWindowTypeToLayerLw(int type) { 1329 switch (type) { 1330 case TYPE_APPLICATION_PANEL: 1331 case TYPE_APPLICATION_ATTACHED_DIALOG: 1332 return APPLICATION_PANEL_SUBLAYER; 1333 case TYPE_APPLICATION_MEDIA: 1334 return APPLICATION_MEDIA_SUBLAYER; 1335 case TYPE_APPLICATION_MEDIA_OVERLAY: 1336 return APPLICATION_MEDIA_OVERLAY_SUBLAYER; 1337 case TYPE_APPLICATION_SUB_PANEL: 1338 return APPLICATION_SUB_PANEL_SUBLAYER; 1339 } 1340 Log.e(TAG, "Unknown sub-window type: " + type); 1341 return 0; 1342 } 1343 1344 public int getMaxWallpaperLayer() { 1345 return STATUS_BAR_LAYER; 1346 } 1347 1348 public int getAboveUniverseLayer() { 1349 return SYSTEM_ERROR_LAYER; 1350 } 1351 1352 public boolean hasSystemNavBar() { 1353 return mHasSystemNavBar; 1354 } 1355 1356 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) { 1357 if (mHasNavigationBar) { 1358 // For a basic navigation bar, when we are in landscape mode we place 1359 // the navigation bar to the side. 1360 if (mNavigationBarCanMove && fullWidth > fullHeight) { 1361 return fullWidth - mNavigationBarWidthForRotation[rotation]; 1362 } 1363 } 1364 return fullWidth; 1365 } 1366 1367 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) { 1368 if (mHasSystemNavBar) { 1369 // For the system navigation bar, we always place it at the bottom. 1370 return fullHeight - mNavigationBarHeightForRotation[rotation]; 1371 } 1372 if (mHasNavigationBar) { 1373 // For a basic navigation bar, when we are in portrait mode we place 1374 // the navigation bar to the bottom. 1375 if (!mNavigationBarCanMove || fullWidth < fullHeight) { 1376 return fullHeight - mNavigationBarHeightForRotation[rotation]; 1377 } 1378 } 1379 return fullHeight; 1380 } 1381 1382 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) { 1383 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation); 1384 } 1385 1386 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) { 1387 // If we don't have a system nav bar, then there is a separate status 1388 // bar at the top of the display. We don't count that as part of the 1389 // fixed decor, since it can hide; however, for purposes of configurations, 1390 // we do want to exclude it since applications can't generally use that part 1391 // of the screen. 1392 if (!mHasSystemNavBar) { 1393 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) - mStatusBarHeight; 1394 } 1395 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation); 1396 } 1397 1398 public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) { 1399 return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD; 1400 } 1401 1402 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) { 1403 return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR 1404 && attrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR 1405 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER 1406 && attrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND; 1407 } 1408 1409 /** {@inheritDoc} */ 1410 @Override 1411 public View addStartingWindow(IBinder appToken, String packageName, int theme, 1412 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, 1413 int icon, int windowFlags) { 1414 if (!SHOW_STARTING_ANIMATIONS) { 1415 return null; 1416 } 1417 if (packageName == null) { 1418 return null; 1419 } 1420 1421 try { 1422 Context context = mContext; 1423 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName 1424 + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme=" 1425 + Integer.toHexString(theme)); 1426 if (theme != context.getThemeResId() || labelRes != 0) { 1427 try { 1428 context = context.createPackageContext(packageName, 0); 1429 context.setTheme(theme); 1430 } catch (PackageManager.NameNotFoundException e) { 1431 // Ignore 1432 } 1433 } 1434 1435 Window win = PolicyManager.makeNewWindow(context); 1436 final TypedArray ta = win.getWindowStyle(); 1437 if (ta.getBoolean( 1438 com.android.internal.R.styleable.Window_windowDisablePreview, false) 1439 || ta.getBoolean( 1440 com.android.internal.R.styleable.Window_windowShowWallpaper,false)) { 1441 return null; 1442 } 1443 1444 Resources r = context.getResources(); 1445 win.setTitle(r.getText(labelRes, nonLocalizedLabel)); 1446 1447 win.setType( 1448 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING); 1449 // Force the window flags: this is a fake window, so it is not really 1450 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM 1451 // flag because we do know that the next window will take input 1452 // focus, so we want to get the IME window up on top of us right away. 1453 win.setFlags( 1454 windowFlags| 1455 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| 1456 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| 1457 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, 1458 windowFlags| 1459 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| 1460 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| 1461 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); 1462 1463 if (!compatInfo.supportsScreen()) { 1464 win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW); 1465 } 1466 1467 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT, 1468 WindowManager.LayoutParams.MATCH_PARENT); 1469 1470 final WindowManager.LayoutParams params = win.getAttributes(); 1471 params.token = appToken; 1472 params.packageName = packageName; 1473 params.windowAnimations = win.getWindowStyle().getResourceId( 1474 com.android.internal.R.styleable.Window_windowAnimationStyle, 0); 1475 params.privateFlags |= 1476 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED; 1477 params.setTitle("Starting " + packageName); 1478 1479 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); 1480 View view = win.getDecorView(); 1481 1482 if (win.isFloating()) { 1483 // Whoops, there is no way to display an animation/preview 1484 // of such a thing! After all that work... let's skip it. 1485 // (Note that we must do this here because it is in 1486 // getDecorView() where the theme is evaluated... maybe 1487 // we should peek the floating attribute from the theme 1488 // earlier.) 1489 return null; 1490 } 1491 1492 if (DEBUG_STARTING_WINDOW) Slog.d( 1493 TAG, "Adding starting window for " + packageName 1494 + " / " + appToken + ": " 1495 + (view.getParent() != null ? view : null)); 1496 1497 wm.addView(view, params); 1498 1499 // Only return the view if it was successfully added to the 1500 // window manager... which we can tell by it having a parent. 1501 return view.getParent() != null ? view : null; 1502 } catch (WindowManagerImpl.BadTokenException e) { 1503 // ignore 1504 Log.w(TAG, appToken + " already running, starting window not displayed"); 1505 } catch (RuntimeException e) { 1506 // don't crash if something else bad happens, for example a 1507 // failure loading resources because we are loading from an app 1508 // on external storage that has been unmounted. 1509 Log.w(TAG, appToken + " failed creating starting window", e); 1510 } 1511 1512 return null; 1513 } 1514 1515 /** {@inheritDoc} */ 1516 public void removeStartingWindow(IBinder appToken, View window) { 1517 if (DEBUG_STARTING_WINDOW) { 1518 RuntimeException e = new RuntimeException("here"); 1519 e.fillInStackTrace(); 1520 Log.v(TAG, "Removing starting window for " + appToken + ": " + window, e); 1521 } 1522 1523 if (window != null) { 1524 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 1525 wm.removeView(window); 1526 } 1527 } 1528 1529 /** 1530 * Preflight adding a window to the system. 1531 * 1532 * Currently enforces that three window types are singletons: 1533 * <ul> 1534 * <li>STATUS_BAR_TYPE</li> 1535 * <li>KEYGUARD_TYPE</li> 1536 * </ul> 1537 * 1538 * @param win The window to be added 1539 * @param attrs Information about the window to be added 1540 * 1541 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON 1542 */ 1543 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) { 1544 switch (attrs.type) { 1545 case TYPE_STATUS_BAR: 1546 mContext.enforceCallingOrSelfPermission( 1547 android.Manifest.permission.STATUS_BAR_SERVICE, 1548 "PhoneWindowManager"); 1549 if (mStatusBar != null) { 1550 if (mStatusBar.isAlive()) { 1551 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON; 1552 } 1553 } 1554 mStatusBar = win; 1555 break; 1556 case TYPE_NAVIGATION_BAR: 1557 mContext.enforceCallingOrSelfPermission( 1558 android.Manifest.permission.STATUS_BAR_SERVICE, 1559 "PhoneWindowManager"); 1560 if (mNavigationBar != null) { 1561 if (mNavigationBar.isAlive()) { 1562 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON; 1563 } 1564 } 1565 mNavigationBar = win; 1566 if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar); 1567 break; 1568 case TYPE_NAVIGATION_BAR_PANEL: 1569 mContext.enforceCallingOrSelfPermission( 1570 android.Manifest.permission.STATUS_BAR_SERVICE, 1571 "PhoneWindowManager"); 1572 break; 1573 case TYPE_STATUS_BAR_PANEL: 1574 mContext.enforceCallingOrSelfPermission( 1575 android.Manifest.permission.STATUS_BAR_SERVICE, 1576 "PhoneWindowManager"); 1577 break; 1578 case TYPE_STATUS_BAR_SUB_PANEL: 1579 mContext.enforceCallingOrSelfPermission( 1580 android.Manifest.permission.STATUS_BAR_SERVICE, 1581 "PhoneWindowManager"); 1582 break; 1583 case TYPE_KEYGUARD: 1584 if (mKeyguard != null) { 1585 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON; 1586 } 1587 mKeyguard = win; 1588 break; 1589 } 1590 return WindowManagerImpl.ADD_OKAY; 1591 } 1592 1593 /** {@inheritDoc} */ 1594 public void removeWindowLw(WindowState win) { 1595 if (mStatusBar == win) { 1596 mStatusBar = null; 1597 } else if (mKeyguard == win) { 1598 mKeyguard = null; 1599 } else if (mNavigationBar == win) { 1600 mNavigationBar = null; 1601 } 1602 } 1603 1604 static final boolean PRINT_ANIM = false; 1605 1606 /** {@inheritDoc} */ 1607 public int selectAnimationLw(WindowState win, int transit) { 1608 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win 1609 + ": transit=" + transit); 1610 if (win == mStatusBar) { 1611 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) { 1612 return R.anim.dock_top_exit; 1613 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) { 1614 return R.anim.dock_top_enter; 1615 } 1616 } else if (win == mNavigationBar) { 1617 // This can be on either the bottom or the right. 1618 if (mNavigationBarOnBottom) { 1619 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) { 1620 return R.anim.dock_bottom_exit; 1621 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) { 1622 return R.anim.dock_bottom_enter; 1623 } 1624 } else { 1625 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) { 1626 return R.anim.dock_right_exit; 1627 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) { 1628 return R.anim.dock_right_enter; 1629 } 1630 } 1631 } if (transit == TRANSIT_PREVIEW_DONE) { 1632 if (win.hasAppShownWindows()) { 1633 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT"); 1634 return com.android.internal.R.anim.app_starting_exit; 1635 } 1636 } 1637 1638 return 0; 1639 } 1640 1641 public Animation createForceHideEnterAnimation(boolean onWallpaper) { 1642 return AnimationUtils.loadAnimation(mContext, onWallpaper 1643 ? com.android.internal.R.anim.lock_screen_wallpaper_behind_enter 1644 : com.android.internal.R.anim.lock_screen_behind_enter); 1645 } 1646 1647 static ITelephony getTelephonyService() { 1648 return ITelephony.Stub.asInterface( 1649 ServiceManager.checkService(Context.TELEPHONY_SERVICE)); 1650 } 1651 1652 static IAudioService getAudioService() { 1653 IAudioService audioService = IAudioService.Stub.asInterface( 1654 ServiceManager.checkService(Context.AUDIO_SERVICE)); 1655 if (audioService == null) { 1656 Log.w(TAG, "Unable to find IAudioService interface."); 1657 } 1658 return audioService; 1659 } 1660 1661 boolean keyguardOn() { 1662 return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode(); 1663 } 1664 1665 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = { 1666 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, 1667 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR, 1668 }; 1669 1670 /** {@inheritDoc} */ 1671 @Override 1672 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) { 1673 final boolean keyguardOn = keyguardOn(); 1674 final int keyCode = event.getKeyCode(); 1675 final int repeatCount = event.getRepeatCount(); 1676 final int metaState = event.getMetaState(); 1677 final int flags = event.getFlags(); 1678 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 1679 final boolean canceled = event.isCanceled(); 1680 1681 if (DEBUG_INPUT) { 1682 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount=" 1683 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed 1684 + " canceled=" + canceled); 1685 } 1686 1687 // If we think we might have a volume down & power key chord on the way 1688 // but we're not sure, then tell the dispatcher to wait a little while and 1689 // try again later before dispatching. 1690 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) { 1691 if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) { 1692 final long now = SystemClock.uptimeMillis(); 1693 final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; 1694 if (now < timeoutTime) { 1695 return timeoutTime - now; 1696 } 1697 } 1698 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN 1699 && mVolumeDownKeyConsumedByScreenshotChord) { 1700 if (!down) { 1701 mVolumeDownKeyConsumedByScreenshotChord = false; 1702 } 1703 return -1; 1704 } 1705 } 1706 1707 // First we always handle the home key here, so applications 1708 // can never break it, although if keyguard is on, we do let 1709 // it handle it, because that gives us the correct 5 second 1710 // timeout. 1711 if (keyCode == KeyEvent.KEYCODE_HOME) { 1712 1713 // If we have released the home key, and didn't do anything else 1714 // while it was pressed, then it is time to go home! 1715 if (!down) { 1716 final boolean homeWasLongPressed = mHomeLongPressed; 1717 mHomePressed = false; 1718 mHomeLongPressed = false; 1719 if (!homeWasLongPressed) { 1720 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) { 1721 try { 1722 IStatusBarService statusbar = getStatusBarService(); 1723 if (statusbar != null) { 1724 statusbar.cancelPreloadRecentApps(); 1725 } 1726 } catch (RemoteException e) { 1727 Slog.e(TAG, "RemoteException when showing recent apps", e); 1728 // re-acquire status bar service next time it is needed. 1729 mStatusBarService = null; 1730 } 1731 } 1732 1733 mHomePressed = false; 1734 if (!canceled) { 1735 // If an incoming call is ringing, HOME is totally disabled. 1736 // (The user is already on the InCallScreen at this point, 1737 // and his ONLY options are to answer or reject the call.) 1738 boolean incomingRinging = false; 1739 try { 1740 ITelephony telephonyService = getTelephonyService(); 1741 if (telephonyService != null) { 1742 incomingRinging = telephonyService.isRinging(); 1743 } 1744 } catch (RemoteException ex) { 1745 Log.w(TAG, "RemoteException from getPhoneInterface()", ex); 1746 } 1747 1748 if (incomingRinging) { 1749 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); 1750 } else { 1751 launchHomeFromHotKey(); 1752 } 1753 } else { 1754 Log.i(TAG, "Ignoring HOME; event canceled."); 1755 } 1756 return -1; 1757 } 1758 } 1759 1760 // If a system window has focus, then it doesn't make sense 1761 // right now to interact with applications. 1762 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; 1763 if (attrs != null) { 1764 final int type = attrs.type; 1765 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD 1766 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) { 1767 // the "app" is keyguard, so give it the key 1768 return 0; 1769 } 1770 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; 1771 for (int i=0; i<typeCount; i++) { 1772 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { 1773 // don't do anything, but also don't pass it to the app 1774 return -1; 1775 } 1776 } 1777 } 1778 if (down) { 1779 if (!mHomePressed && mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) { 1780 try { 1781 IStatusBarService statusbar = getStatusBarService(); 1782 if (statusbar != null) { 1783 statusbar.preloadRecentApps(); 1784 } 1785 } catch (RemoteException e) { 1786 Slog.e(TAG, "RemoteException when preloading recent apps", e); 1787 // re-acquire status bar service next time it is needed. 1788 mStatusBarService = null; 1789 } 1790 } 1791 if (repeatCount == 0) { 1792 mHomePressed = true; 1793 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { 1794 if (!keyguardOn) { 1795 handleLongPressOnHome(); 1796 } 1797 } 1798 } 1799 return -1; 1800 } else if (keyCode == KeyEvent.KEYCODE_MENU) { 1801 // Hijack modified menu keys for debugging features 1802 final int chordBug = KeyEvent.META_SHIFT_ON; 1803 1804 if (down && repeatCount == 0) { 1805 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) { 1806 Intent intent = new Intent(Intent.ACTION_BUG_REPORT); 1807 mContext.sendOrderedBroadcast(intent, null); 1808 return -1; 1809 } else if (SHOW_PROCESSES_ON_ALT_MENU && 1810 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) { 1811 Intent service = new Intent(); 1812 service.setClassName(mContext, "com.android.server.LoadAverageService"); 1813 ContentResolver res = mContext.getContentResolver(); 1814 boolean shown = Settings.System.getInt( 1815 res, Settings.System.SHOW_PROCESSES, 0) != 0; 1816 if (!shown) { 1817 mContext.startService(service); 1818 } else { 1819 mContext.stopService(service); 1820 } 1821 Settings.System.putInt( 1822 res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1); 1823 return -1; 1824 } 1825 } 1826 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { 1827 if (down) { 1828 if (repeatCount == 0) { 1829 mSearchKeyShortcutPending = true; 1830 mConsumeSearchKeyUp = false; 1831 } 1832 } else { 1833 mSearchKeyShortcutPending = false; 1834 if (mConsumeSearchKeyUp) { 1835 mConsumeSearchKeyUp = false; 1836 return -1; 1837 } 1838 } 1839 return 0; 1840 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { 1841 if (down && repeatCount == 0 && !keyguardOn) { 1842 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS); 1843 } 1844 return -1; 1845 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) { 1846 if (down) { 1847 if (repeatCount == 0) { 1848 mAssistKeyLongPressed = false; 1849 } else if (repeatCount == 1) { 1850 mAssistKeyLongPressed = true; 1851 if (!keyguardOn) { 1852 launchAssistLongPressAction(); 1853 } 1854 } 1855 } else { 1856 if (mAssistKeyLongPressed) { 1857 mAssistKeyLongPressed = false; 1858 } else { 1859 if (!keyguardOn) { 1860 launchAssistAction(); 1861 } 1862 } 1863 } 1864 return -1; 1865 } 1866 1867 // Shortcuts are invoked through Search+key, so intercept those here 1868 // Any printing key that is chorded with Search should be consumed 1869 // even if no shortcut was invoked. This prevents text from being 1870 // inadvertently inserted when using a keyboard that has built-in macro 1871 // shortcut keys (that emit Search+x) and some of them are not registered. 1872 if (mSearchKeyShortcutPending) { 1873 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 1874 if (kcm.isPrintingKey(keyCode)) { 1875 mConsumeSearchKeyUp = true; 1876 mSearchKeyShortcutPending = false; 1877 if (down && repeatCount == 0 && !keyguardOn) { 1878 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); 1879 if (shortcutIntent != null) { 1880 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1881 try { 1882 mContext.startActivity(shortcutIntent); 1883 } catch (ActivityNotFoundException ex) { 1884 Slog.w(TAG, "Dropping shortcut key combination because " 1885 + "the activity to which it is registered was not found: " 1886 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex); 1887 } 1888 } else { 1889 Slog.i(TAG, "Dropping unregistered shortcut key combination: " 1890 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode)); 1891 } 1892 } 1893 return -1; 1894 } 1895 } 1896 1897 // Invoke shortcuts using Meta. 1898 if (down && repeatCount == 0 && !keyguardOn 1899 && (metaState & KeyEvent.META_META_ON) != 0) { 1900 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 1901 if (kcm.isPrintingKey(keyCode)) { 1902 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, 1903 metaState & ~(KeyEvent.META_META_ON 1904 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON)); 1905 if (shortcutIntent != null) { 1906 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1907 try { 1908 mContext.startActivity(shortcutIntent); 1909 } catch (ActivityNotFoundException ex) { 1910 Slog.w(TAG, "Dropping shortcut key combination because " 1911 + "the activity to which it is registered was not found: " 1912 + "META+" + KeyEvent.keyCodeToString(keyCode), ex); 1913 } 1914 return -1; 1915 } 1916 } 1917 } 1918 1919 // Handle application launch keys. 1920 if (down && repeatCount == 0 && !keyguardOn) { 1921 String category = sApplicationLaunchKeyCategories.get(keyCode); 1922 if (category != null) { 1923 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); 1924 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1925 try { 1926 mContext.startActivity(intent); 1927 } catch (ActivityNotFoundException ex) { 1928 Slog.w(TAG, "Dropping application launch key because " 1929 + "the activity to which it is registered was not found: " 1930 + "keyCode=" + keyCode + ", category=" + category, ex); 1931 } 1932 return -1; 1933 } 1934 } 1935 1936 // Display task switcher for ALT-TAB or Meta-TAB. 1937 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) { 1938 if (mRecentAppsDialogHeldModifiers == 0 && !keyguardOn) { 1939 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; 1940 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON) 1941 || KeyEvent.metaStateHasModifiers( 1942 shiftlessModifiers, KeyEvent.META_META_ON)) { 1943 mRecentAppsDialogHeldModifiers = shiftlessModifiers; 1944 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW); 1945 return -1; 1946 } 1947 } 1948 } else if (!down && mRecentAppsDialogHeldModifiers != 0 1949 && (metaState & mRecentAppsDialogHeldModifiers) == 0) { 1950 mRecentAppsDialogHeldModifiers = 0; 1951 showOrHideRecentAppsDialog(keyguardOn ? RECENT_APPS_BEHAVIOR_DISMISS : 1952 RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH); 1953 } 1954 1955 // Handle keyboard language switching. 1956 if (down && repeatCount == 0 1957 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 1958 || (keyCode == KeyEvent.KEYCODE_SPACE 1959 && (metaState & KeyEvent.META_CTRL_MASK) != 0))) { 1960 int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1; 1961 mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction); 1962 return -1; 1963 } 1964 if (mLanguageSwitchKeyPressed && !down 1965 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 1966 || keyCode == KeyEvent.KEYCODE_SPACE)) { 1967 mLanguageSwitchKeyPressed = false; 1968 return -1; 1969 } 1970 1971 // Let the application handle the key. 1972 return 0; 1973 } 1974 1975 /** {@inheritDoc} */ 1976 @Override 1977 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) { 1978 // Note: This method is only called if the initial down was unhandled. 1979 if (DEBUG_INPUT) { 1980 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction() 1981 + ", flags=" + event.getFlags() 1982 + ", keyCode=" + event.getKeyCode() 1983 + ", scanCode=" + event.getScanCode() 1984 + ", metaState=" + event.getMetaState() 1985 + ", repeatCount=" + event.getRepeatCount() 1986 + ", policyFlags=" + policyFlags); 1987 } 1988 1989 KeyEvent fallbackEvent = null; 1990 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 1991 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 1992 final int keyCode = event.getKeyCode(); 1993 final int metaState = event.getMetaState(); 1994 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN 1995 && event.getRepeatCount() == 0; 1996 1997 // Check for fallback actions specified by the key character map. 1998 final FallbackAction fallbackAction; 1999 if (initialDown) { 2000 fallbackAction = kcm.getFallbackAction(keyCode, metaState); 2001 } else { 2002 fallbackAction = mFallbackActions.get(keyCode); 2003 } 2004 2005 if (fallbackAction != null) { 2006 if (DEBUG_INPUT) { 2007 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode 2008 + " metaState=" + Integer.toHexString(fallbackAction.metaState)); 2009 } 2010 2011 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; 2012 fallbackEvent = KeyEvent.obtain( 2013 event.getDownTime(), event.getEventTime(), 2014 event.getAction(), fallbackAction.keyCode, 2015 event.getRepeatCount(), fallbackAction.metaState, 2016 event.getDeviceId(), event.getScanCode(), 2017 flags, event.getSource(), null); 2018 2019 if (!interceptFallback(win, fallbackEvent, policyFlags)) { 2020 fallbackEvent.recycle(); 2021 fallbackEvent = null; 2022 } 2023 2024 if (initialDown) { 2025 mFallbackActions.put(keyCode, fallbackAction); 2026 } else if (event.getAction() == KeyEvent.ACTION_UP) { 2027 mFallbackActions.remove(keyCode); 2028 fallbackAction.recycle(); 2029 } 2030 } 2031 } 2032 2033 if (DEBUG_INPUT) { 2034 if (fallbackEvent == null) { 2035 Slog.d(TAG, "No fallback."); 2036 } else { 2037 Slog.d(TAG, "Performing fallback: " + fallbackEvent); 2038 } 2039 } 2040 return fallbackEvent; 2041 } 2042 2043 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) { 2044 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true); 2045 if ((actions & ACTION_PASS_TO_USER) != 0) { 2046 long delayMillis = interceptKeyBeforeDispatching( 2047 win, fallbackEvent, policyFlags); 2048 if (delayMillis == 0) { 2049 return true; 2050 } 2051 } 2052 return false; 2053 } 2054 2055 private void launchAssistLongPressAction() { 2056 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 2057 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 2058 2059 // launch the search activity 2060 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS); 2061 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2062 try { 2063 // TODO: This only stops the factory-installed search manager. 2064 // Need to formalize an API to handle others 2065 SearchManager searchManager = getSearchManager(); 2066 if (searchManager != null) { 2067 searchManager.stopSearch(); 2068 } 2069 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 2070 } catch (ActivityNotFoundException e) { 2071 Slog.w(TAG, "No activity to handle assist long press action.", e); 2072 } 2073 } 2074 2075 private void launchAssistAction() { 2076 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 2077 Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) 2078 .getAssistIntent(mContext, UserHandle.USER_CURRENT); 2079 if (intent != null) { 2080 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 2081 | Intent.FLAG_ACTIVITY_SINGLE_TOP 2082 | Intent.FLAG_ACTIVITY_CLEAR_TOP); 2083 try { 2084 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 2085 } catch (ActivityNotFoundException e) { 2086 Slog.w(TAG, "No activity to handle assist action.", e); 2087 } 2088 } 2089 } 2090 2091 private SearchManager getSearchManager() { 2092 if (mSearchManager == null) { 2093 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); 2094 } 2095 return mSearchManager; 2096 } 2097 2098 /** 2099 * A home key -> launch home action was detected. Take the appropriate action 2100 * given the situation with the keyguard. 2101 */ 2102 void launchHomeFromHotKey() { 2103 if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) { 2104 // don't launch home if keyguard showing 2105 } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) { 2106 // when in keyguard restricted mode, must first verify unlock 2107 // before launching home 2108 mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() { 2109 public void onKeyguardExitResult(boolean success) { 2110 if (success) { 2111 try { 2112 ActivityManagerNative.getDefault().stopAppSwitches(); 2113 } catch (RemoteException e) { 2114 } 2115 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 2116 startDockOrHome(); 2117 } 2118 } 2119 }); 2120 } else { 2121 // no keyguard stuff to worry about, just launch home! 2122 try { 2123 ActivityManagerNative.getDefault().stopAppSwitches(); 2124 } catch (RemoteException e) { 2125 } 2126 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 2127 startDockOrHome(); 2128 } 2129 } 2130 2131 /** 2132 * A delayed callback use to determine when it is okay to re-allow applications 2133 * to use certain system UI flags. This is used to prevent applications from 2134 * spamming system UI changes that prevent the navigation bar from being shown. 2135 */ 2136 final Runnable mAllowSystemUiDelay = new Runnable() { 2137 @Override public void run() { 2138 } 2139 }; 2140 2141 /** 2142 * Input handler used while nav bar is hidden. Captures any touch on the screen, 2143 * to determine when the nav bar should be shown and prevent applications from 2144 * receiving those touches. 2145 */ 2146 final class HideNavInputEventReceiver extends InputEventReceiver { 2147 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) { 2148 super(inputChannel, looper); 2149 } 2150 2151 @Override 2152 public void onInputEvent(InputEvent event) { 2153 boolean handled = false; 2154 try { 2155 if (event instanceof MotionEvent 2156 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 2157 final MotionEvent motionEvent = (MotionEvent)event; 2158 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 2159 // When the user taps down, we re-show the nav bar. 2160 boolean changed = false; 2161 synchronized (mLock) { 2162 // Any user activity always causes us to show the 2163 // navigation controls, if they had been hidden. 2164 // We also clear the low profile and only content 2165 // flags so that tapping on the screen will atomically 2166 // restore all currently hidden screen decorations. 2167 int newVal = mResettingSystemUiFlags | 2168 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | 2169 View.SYSTEM_UI_FLAG_LOW_PROFILE | 2170 View.SYSTEM_UI_FLAG_FULLSCREEN; 2171 if (mResettingSystemUiFlags != newVal) { 2172 mResettingSystemUiFlags = newVal; 2173 changed = true; 2174 } 2175 // We don't allow the system's nav bar to be hidden 2176 // again for 1 second, to prevent applications from 2177 // spamming us and keeping it from being shown. 2178 newVal = mForceClearedSystemUiFlags | 2179 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 2180 if (mForceClearedSystemUiFlags != newVal) { 2181 mForceClearedSystemUiFlags = newVal; 2182 changed = true; 2183 mHandler.postDelayed(new Runnable() { 2184 @Override public void run() { 2185 synchronized (mLock) { 2186 // Clear flags. 2187 mForceClearedSystemUiFlags &= 2188 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 2189 } 2190 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 2191 } 2192 }, 1000); 2193 } 2194 } 2195 if (changed) { 2196 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 2197 } 2198 } 2199 } 2200 } finally { 2201 finishInputEvent(event, handled); 2202 } 2203 } 2204 } 2205 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory = 2206 new InputEventReceiver.Factory() { 2207 @Override 2208 public InputEventReceiver createInputEventReceiver( 2209 InputChannel inputChannel, Looper looper) { 2210 return new HideNavInputEventReceiver(inputChannel, looper); 2211 } 2212 }; 2213 2214 @Override 2215 public int adjustSystemUiVisibilityLw(int visibility) { 2216 // Reset any bits in mForceClearingStatusBarVisibility that 2217 // are now clear. 2218 mResettingSystemUiFlags &= visibility; 2219 // Clear any bits in the new visibility that are currently being 2220 // force cleared, before reporting it. 2221 return visibility & ~mResettingSystemUiFlags 2222 & ~mForceClearedSystemUiFlags; 2223 } 2224 2225 public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) { 2226 final int fl = attrs.flags; 2227 final int systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility); 2228 2229 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 2230 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 2231 int availRight, availBottom; 2232 if (mCanHideNavigationBar && 2233 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) { 2234 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 2235 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 2236 } else { 2237 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth; 2238 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight; 2239 } 2240 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 2241 if ((fl & FLAG_FULLSCREEN) != 0) { 2242 contentInset.set(mStableFullscreenLeft, mStableFullscreenTop, 2243 availRight - mStableFullscreenRight, 2244 availBottom - mStableFullscreenBottom); 2245 } else { 2246 contentInset.set(mStableLeft, mStableTop, 2247 availRight - mStableRight, availBottom - mStableBottom); 2248 } 2249 } else if ((fl & FLAG_FULLSCREEN) != 0) { 2250 contentInset.setEmpty(); 2251 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN 2252 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) { 2253 contentInset.set(mCurLeft, mCurTop, 2254 availRight - mCurRight, availBottom - mCurBottom); 2255 } else { 2256 contentInset.set(mCurLeft, mCurTop, 2257 availRight - mCurRight, availBottom - mCurBottom); 2258 } 2259 return; 2260 } 2261 contentInset.setEmpty(); 2262 } 2263 2264 /** {@inheritDoc} */ 2265 public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation) { 2266 mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0; 2267 mUnrestrictedScreenWidth = displayWidth; 2268 mUnrestrictedScreenHeight = displayHeight; 2269 mRestrictedScreenLeft = mRestrictedScreenTop = 0; 2270 mRestrictedScreenWidth = displayWidth; 2271 mRestrictedScreenHeight = displayHeight; 2272 mDockLeft = mContentLeft = mStableLeft = mStableFullscreenLeft 2273 = mSystemLeft = mCurLeft = 0; 2274 mDockTop = mContentTop = mStableTop = mStableFullscreenTop 2275 = mSystemTop = mCurTop = 0; 2276 mDockRight = mContentRight = mStableRight = mStableFullscreenRight 2277 = mSystemRight = mCurRight = displayWidth; 2278 mDockBottom = mContentBottom = mStableBottom = mStableFullscreenBottom 2279 = mSystemBottom = mCurBottom = displayHeight; 2280 mDockLayer = 0x10000000; 2281 mStatusBarLayer = -1; 2282 2283 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight) 2284 final Rect pf = mTmpParentFrame; 2285 final Rect df = mTmpDisplayFrame; 2286 final Rect vf = mTmpVisibleFrame; 2287 pf.left = df.left = vf.left = mDockLeft; 2288 pf.top = df.top = vf.top = mDockTop; 2289 pf.right = df.right = vf.right = mDockRight; 2290 pf.bottom = df.bottom = vf.bottom = mDockBottom; 2291 2292 // For purposes of putting out fake window up to steal focus, we will 2293 // drive nav being hidden only by whether it is requested. 2294 boolean navVisible = (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; 2295 2296 // When the navigation bar isn't visible, we put up a fake 2297 // input window to catch all touch events. This way we can 2298 // detect when the user presses anywhere to bring back the nav 2299 // bar and ensure the application doesn't see the event. 2300 if (navVisible) { 2301 if (mHideNavFakeWindow != null) { 2302 mHideNavFakeWindow.dismiss(); 2303 mHideNavFakeWindow = null; 2304 } 2305 } else if (mHideNavFakeWindow == null) { 2306 mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow( 2307 mHandler.getLooper(), mHideNavInputEventReceiverFactory, 2308 "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER, 2309 0, false, false, true); 2310 } 2311 2312 // For purposes of positioning and showing the nav bar, if we have 2313 // decided that it can't be hidden (because of the screen aspect ratio), 2314 // then take that into account. 2315 navVisible |= !mCanHideNavigationBar; 2316 2317 if (mNavigationBar != null) { 2318 // Force the navigation bar to its appropriate place and 2319 // size. We need to do this directly, instead of relying on 2320 // it to bubble up from the nav bar, because this needs to 2321 // change atomically with screen rotations. 2322 mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight); 2323 if (mNavigationBarOnBottom) { 2324 // It's a system nav bar or a portrait screen; nav bar goes on bottom. 2325 int top = displayHeight - mNavigationBarHeightForRotation[displayRotation]; 2326 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight); 2327 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top; 2328 if (navVisible) { 2329 mNavigationBar.showLw(true); 2330 mDockBottom = mTmpNavigationFrame.top; 2331 mRestrictedScreenHeight = mDockBottom - mDockTop; 2332 } else { 2333 // We currently want to hide the navigation UI. 2334 mNavigationBar.hideLw(true); 2335 } 2336 if (navVisible && !mNavigationBar.isAnimatingLw()) { 2337 // If the nav bar is currently requested to be visible, 2338 // and not in the process of animating on or off, then 2339 // we can tell the app that it is covered by it. 2340 mSystemBottom = mTmpNavigationFrame.top; 2341 } 2342 } else { 2343 // Landscape screen; nav bar goes to the right. 2344 int left = displayWidth - mNavigationBarWidthForRotation[displayRotation]; 2345 mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight); 2346 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left; 2347 if (navVisible) { 2348 mNavigationBar.showLw(true); 2349 mDockRight = mTmpNavigationFrame.left; 2350 mRestrictedScreenWidth = mDockRight - mDockLeft; 2351 } else { 2352 // We currently want to hide the navigation UI. 2353 mNavigationBar.hideLw(true); 2354 } 2355 if (navVisible && !mNavigationBar.isAnimatingLw()) { 2356 // If the nav bar is currently requested to be visible, 2357 // and not in the process of animating on or off, then 2358 // we can tell the app that it is covered by it. 2359 mSystemRight = mTmpNavigationFrame.left; 2360 } 2361 } 2362 // Make sure the content and current rectangles are updated to 2363 // account for the restrictions from the navigation bar. 2364 mContentTop = mCurTop = mDockTop; 2365 mContentBottom = mCurBottom = mDockBottom; 2366 mContentLeft = mCurLeft = mDockLeft; 2367 mContentRight = mCurRight = mDockRight; 2368 mStatusBarLayer = mNavigationBar.getSurfaceLayer(); 2369 // And compute the final frame. 2370 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, 2371 mTmpNavigationFrame, mTmpNavigationFrame); 2372 if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); 2373 } 2374 if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)", 2375 mDockLeft, mDockTop, mDockRight, mDockBottom)); 2376 2377 // decide where the status bar goes ahead of time 2378 if (mStatusBar != null) { 2379 // apply any navigation bar insets 2380 pf.left = df.left = mUnrestrictedScreenLeft; 2381 pf.top = df.top = mUnrestrictedScreenTop; 2382 pf.right = df.right = mUnrestrictedScreenWidth - mUnrestrictedScreenLeft; 2383 pf.bottom = df.bottom = mUnrestrictedScreenHeight - mUnrestrictedScreenTop; 2384 vf.left = mStableLeft; 2385 vf.top = mStableTop; 2386 vf.right = mStableRight; 2387 vf.bottom = mStableBottom; 2388 2389 mStatusBarLayer = mStatusBar.getSurfaceLayer(); 2390 2391 // Let the status bar determine its size. 2392 mStatusBar.computeFrameLw(pf, df, vf, vf); 2393 2394 // For layout, the status bar is always at the top with our fixed height. 2395 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; 2396 2397 // If the status bar is hidden, we don't want to cause 2398 // windows behind it to scroll. 2399 if (mStatusBar.isVisibleLw()) { 2400 // Status bar may go away, so the screen area it occupies 2401 // is available to apps but just covering them when the 2402 // status bar is visible. 2403 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight; 2404 2405 mContentTop = mCurTop = mDockTop; 2406 mContentBottom = mCurBottom = mDockBottom; 2407 mContentLeft = mCurLeft = mDockLeft; 2408 mContentRight = mCurRight = mDockRight; 2409 2410 if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " + 2411 String.format( 2412 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]", 2413 mDockLeft, mDockTop, mDockRight, mDockBottom, 2414 mContentLeft, mContentTop, mContentRight, mContentBottom, 2415 mCurLeft, mCurTop, mCurRight, mCurBottom)); 2416 } 2417 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()) { 2418 // If the status bar is currently requested to be visible, 2419 // and not in the process of animating on or off, then 2420 // we can tell the app that it is covered by it. 2421 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight; 2422 } 2423 } 2424 } 2425 2426 /** {@inheritDoc} */ 2427 public int getSystemDecorRectLw(Rect systemRect) { 2428 systemRect.left = mSystemLeft; 2429 systemRect.top = mSystemTop; 2430 systemRect.right = mSystemRight; 2431 systemRect.bottom = mSystemBottom; 2432 if (mStatusBar != null) return mStatusBar.getSurfaceLayer(); 2433 if (mNavigationBar != null) return mNavigationBar.getSurfaceLayer(); 2434 return 0; 2435 } 2436 2437 void setAttachedWindowFrames(WindowState win, int fl, int adjust, 2438 WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) { 2439 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) { 2440 // Here's a special case: if this attached window is a panel that is 2441 // above the dock window, and the window it is attached to is below 2442 // the dock window, then the frames we computed for the window it is 2443 // attached to can not be used because the dock is effectively part 2444 // of the underlying window and the attached window is floating on top 2445 // of the whole thing. So, we ignore the attached window and explicitly 2446 // compute the frames that would be appropriate without the dock. 2447 df.left = cf.left = vf.left = mDockLeft; 2448 df.top = cf.top = vf.top = mDockTop; 2449 df.right = cf.right = vf.right = mDockRight; 2450 df.bottom = cf.bottom = vf.bottom = mDockBottom; 2451 } else { 2452 // The effective display frame of the attached window depends on 2453 // whether it is taking care of insetting its content. If not, 2454 // we need to use the parent's content frame so that the entire 2455 // window is positioned within that content. Otherwise we can use 2456 // the display frame and let the attached window take care of 2457 // positioning its content appropriately. 2458 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 2459 cf.set(attached.getDisplayFrameLw()); 2460 } else { 2461 // If the window is resizing, then we want to base the content 2462 // frame on our attached content frame to resize... however, 2463 // things can be tricky if the attached window is NOT in resize 2464 // mode, in which case its content frame will be larger. 2465 // Ungh. So to deal with that, make sure the content frame 2466 // we end up using is not covering the IM dock. 2467 cf.set(attached.getContentFrameLw()); 2468 if (attached.getSurfaceLayer() < mDockLayer) { 2469 if (cf.left < mContentLeft) cf.left = mContentLeft; 2470 if (cf.top < mContentTop) cf.top = mContentTop; 2471 if (cf.right > mContentRight) cf.right = mContentRight; 2472 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom; 2473 } 2474 } 2475 df.set(insetDecors ? attached.getDisplayFrameLw() : cf); 2476 vf.set(attached.getVisibleFrameLw()); 2477 } 2478 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached 2479 // window should be positioned relative to its parent or the entire 2480 // screen. 2481 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 2482 ? attached.getFrameLw() : df); 2483 } 2484 2485 private void applyStableConstraints(int sysui, int fl, Rect r) { 2486 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 2487 // If app is requesting a stable layout, don't let the 2488 // content insets go below the stable values. 2489 if ((fl & FLAG_FULLSCREEN) != 0) { 2490 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft; 2491 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop; 2492 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight; 2493 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom; 2494 } else { 2495 if (r.left < mStableLeft) r.left = mStableLeft; 2496 if (r.top < mStableTop) r.top = mStableTop; 2497 if (r.right > mStableRight) r.right = mStableRight; 2498 if (r.bottom > mStableBottom) r.bottom = mStableBottom; 2499 } 2500 } 2501 } 2502 2503 /** {@inheritDoc} */ 2504 public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs, 2505 WindowState attached) { 2506 // we've already done the status bar 2507 if (win == mStatusBar || win == mNavigationBar) { 2508 return; 2509 } 2510 final boolean needsToOffsetInputMethodTarget = 2511 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null); 2512 if (needsToOffsetInputMethodTarget) { 2513 if (DEBUG_LAYOUT) { 2514 Slog.i(TAG, "Offset ime target window by the last ime window state"); 2515 } 2516 offsetInputMethodWindowLw(mLastInputMethodWindow); 2517 } 2518 2519 final int fl = attrs.flags; 2520 final int sim = attrs.softInputMode; 2521 final int sysUiFl = win.getSystemUiVisibility(); 2522 2523 final Rect pf = mTmpParentFrame; 2524 final Rect df = mTmpDisplayFrame; 2525 final Rect cf = mTmpContentFrame; 2526 final Rect vf = mTmpVisibleFrame; 2527 2528 final boolean hasNavBar = (mHasNavigationBar 2529 && mNavigationBar != null && mNavigationBar.isVisibleLw()); 2530 2531 if (attrs.type == TYPE_INPUT_METHOD) { 2532 pf.left = df.left = cf.left = vf.left = mDockLeft; 2533 pf.top = df.top = cf.top = vf.top = mDockTop; 2534 pf.right = df.right = cf.right = vf.right = mDockRight; 2535 pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom; 2536 // IM dock windows always go to the bottom of the screen. 2537 attrs.gravity = Gravity.BOTTOM; 2538 mDockLayer = win.getSurfaceLayer(); 2539 } else { 2540 final int adjust = sim & SOFT_INPUT_MASK_ADJUST; 2541 2542 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR)) 2543 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR) 2544 && (sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { 2545 if (DEBUG_LAYOUT) 2546 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() 2547 + "): IN_SCREEN, INSET_DECOR, !FULLSCREEN"); 2548 // This is the case for a normal activity window: we want it 2549 // to cover all of the screen space, and it can take care of 2550 // moving its contents to account for screen decorations that 2551 // intrude into that space. 2552 if (attached != null) { 2553 // If this window is attached to another, our display 2554 // frame is the same as the one we are attached to. 2555 setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf); 2556 } else { 2557 if (attrs.type == TYPE_STATUS_BAR_PANEL 2558 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { 2559 // Status bar panels are the only windows who can go on top of 2560 // the status bar. They are protected by the STATUS_BAR_SERVICE 2561 // permission, so they have the same privileges as the status 2562 // bar itself. 2563 // 2564 // However, they should still dodge the navigation bar if it exists. 2565 2566 pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft; 2567 pf.top = df.top = mUnrestrictedScreenTop; 2568 pf.right = df.right = hasNavBar 2569 ? mRestrictedScreenLeft+mRestrictedScreenWidth 2570 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2571 pf.bottom = df.bottom = hasNavBar 2572 ? mRestrictedScreenTop+mRestrictedScreenHeight 2573 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2574 2575 if (DEBUG_LAYOUT) { 2576 Log.v(TAG, String.format( 2577 "Laying out status bar window: (%d,%d - %d,%d)", 2578 pf.left, pf.top, pf.right, pf.bottom)); 2579 } 2580 } else if (mCanHideNavigationBar 2581 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 2582 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 2583 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 2584 // Asking for layout as if the nav bar is hidden, lets the 2585 // application extend into the unrestricted screen area. We 2586 // only do this for application windows to ensure no window that 2587 // can be above the nav bar can do this. 2588 pf.left = df.left = mUnrestrictedScreenLeft; 2589 pf.top = df.top = mUnrestrictedScreenTop; 2590 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2591 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2592 } else { 2593 pf.left = df.left = mRestrictedScreenLeft; 2594 pf.top = df.top = mRestrictedScreenTop; 2595 pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth; 2596 pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight; 2597 } 2598 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 2599 cf.left = mDockLeft; 2600 cf.top = mDockTop; 2601 cf.right = mDockRight; 2602 cf.bottom = mDockBottom; 2603 } else { 2604 cf.left = mContentLeft; 2605 cf.top = mContentTop; 2606 cf.right = mContentRight; 2607 cf.bottom = mContentBottom; 2608 } 2609 applyStableConstraints(sysUiFl, fl, cf); 2610 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 2611 vf.left = mCurLeft; 2612 vf.top = mCurTop; 2613 vf.right = mCurRight; 2614 vf.bottom = mCurBottom; 2615 } else { 2616 vf.set(cf); 2617 } 2618 } 2619 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl 2620 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 2621 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) { 2622 if (DEBUG_LAYOUT) 2623 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN"); 2624 // A window that has requested to fill the entire screen just 2625 // gets everything, period. 2626 if (attrs.type == TYPE_STATUS_BAR_PANEL 2627 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { 2628 pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft; 2629 pf.top = df.top = cf.top = mUnrestrictedScreenTop; 2630 pf.right = df.right = cf.right = hasNavBar 2631 ? mRestrictedScreenLeft+mRestrictedScreenWidth 2632 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2633 pf.bottom = df.bottom = cf.bottom = hasNavBar 2634 ? mRestrictedScreenTop+mRestrictedScreenHeight 2635 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2636 if (DEBUG_LAYOUT) { 2637 Log.v(TAG, String.format( 2638 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)", 2639 pf.left, pf.top, pf.right, pf.bottom)); 2640 } 2641 } else if (attrs.type == TYPE_NAVIGATION_BAR 2642 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) { 2643 // The navigation bar has Real Ultimate Power. 2644 pf.left = df.left = mUnrestrictedScreenLeft; 2645 pf.top = df.top = mUnrestrictedScreenTop; 2646 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2647 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2648 if (DEBUG_LAYOUT) { 2649 Log.v(TAG, String.format( 2650 "Laying out navigation bar window: (%d,%d - %d,%d)", 2651 pf.left, pf.top, pf.right, pf.bottom)); 2652 } 2653 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY 2654 || attrs.type == TYPE_BOOT_PROGRESS) 2655 && ((fl & FLAG_FULLSCREEN) != 0)) { 2656 // Fullscreen secure system overlays get what they ask for. 2657 pf.left = df.left = mUnrestrictedScreenLeft; 2658 pf.top = df.top = mUnrestrictedScreenTop; 2659 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2660 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2661 } else if (attrs.type == TYPE_BOOT_PROGRESS 2662 || attrs.type == TYPE_UNIVERSE_BACKGROUND) { 2663 // Boot progress screen always covers entire display. 2664 pf.left = df.left = cf.left = mUnrestrictedScreenLeft; 2665 pf.top = df.top = cf.top = mUnrestrictedScreenTop; 2666 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2667 pf.bottom = df.bottom = cf.bottom 2668 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2669 } else if (mCanHideNavigationBar 2670 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 2671 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 2672 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 2673 // Asking for layout as if the nav bar is hidden, lets the 2674 // application extend into the unrestricted screen area. We 2675 // only do this for application windows to ensure no window that 2676 // can be above the nav bar can do this. 2677 // XXX This assumes that an app asking for this will also 2678 // ask for layout in only content. We can't currently figure out 2679 // what the screen would be if only laying out to hide the nav bar. 2680 pf.left = df.left = cf.left = mUnrestrictedScreenLeft; 2681 pf.top = df.top = cf.top = mUnrestrictedScreenTop; 2682 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2683 pf.bottom = df.bottom = cf.bottom 2684 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2685 } else { 2686 pf.left = df.left = cf.left = mRestrictedScreenLeft; 2687 pf.top = df.top = cf.top = mRestrictedScreenTop; 2688 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth; 2689 pf.bottom = df.bottom = cf.bottom 2690 = mRestrictedScreenTop+mRestrictedScreenHeight; 2691 } 2692 applyStableConstraints(sysUiFl, fl, cf); 2693 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 2694 vf.left = mCurLeft; 2695 vf.top = mCurTop; 2696 vf.right = mCurRight; 2697 vf.bottom = mCurBottom; 2698 } else { 2699 vf.set(cf); 2700 } 2701 } else if (attached != null) { 2702 if (DEBUG_LAYOUT) 2703 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): attached to " + attached); 2704 // A child window should be placed inside of the same visible 2705 // frame that its parent had. 2706 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf); 2707 } else { 2708 if (DEBUG_LAYOUT) 2709 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window"); 2710 // Otherwise, a normal window must be placed inside the content 2711 // of all screen decorations. 2712 if (attrs.type == TYPE_STATUS_BAR_PANEL) { 2713 // Status bar panels are the only windows who can go on top of 2714 // the status bar. They are protected by the STATUS_BAR_SERVICE 2715 // permission, so they have the same privileges as the status 2716 // bar itself. 2717 pf.left = df.left = cf.left = mRestrictedScreenLeft; 2718 pf.top = df.top = cf.top = mRestrictedScreenTop; 2719 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth; 2720 pf.bottom = df.bottom = cf.bottom 2721 = mRestrictedScreenTop+mRestrictedScreenHeight; 2722 } else { 2723 pf.left = mContentLeft; 2724 pf.top = mContentTop; 2725 pf.right = mContentRight; 2726 pf.bottom = mContentBottom; 2727 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 2728 df.left = cf.left = mDockLeft; 2729 df.top = cf.top = mDockTop; 2730 df.right = cf.right = mDockRight; 2731 df.bottom = cf.bottom = mDockBottom; 2732 } else { 2733 df.left = cf.left = mContentLeft; 2734 df.top = cf.top = mContentTop; 2735 df.right = cf.right = mContentRight; 2736 df.bottom = cf.bottom = mContentBottom; 2737 } 2738 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 2739 vf.left = mCurLeft; 2740 vf.top = mCurTop; 2741 vf.right = mCurRight; 2742 vf.bottom = mCurBottom; 2743 } else { 2744 vf.set(cf); 2745 } 2746 } 2747 } 2748 } 2749 2750 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) { 2751 df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000; 2752 df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000; 2753 } 2754 2755 if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle() 2756 + ": sim=#" + Integer.toHexString(sim) 2757 + " attach=" + attached + " type=" + attrs.type 2758 + String.format(" flags=0x%08x", fl) 2759 + " pf=" + pf.toShortString() + " df=" + df.toShortString() 2760 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()); 2761 2762 win.computeFrameLw(pf, df, cf, vf); 2763 2764 // Dock windows carve out the bottom of the screen, so normal windows 2765 // can't appear underneath them. 2766 if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) { 2767 setLastInputMethodWindowLw(null, null); 2768 offsetInputMethodWindowLw(win); 2769 } 2770 } 2771 2772 private void offsetInputMethodWindowLw(WindowState win) { 2773 int top = win.getContentFrameLw().top; 2774 top += win.getGivenContentInsetsLw().top; 2775 if (mContentBottom > top) { 2776 mContentBottom = top; 2777 } 2778 top = win.getVisibleFrameLw().top; 2779 top += win.getGivenVisibleInsetsLw().top; 2780 if (mCurBottom > top) { 2781 mCurBottom = top; 2782 } 2783 if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom=" 2784 + mDockBottom + " mContentBottom=" 2785 + mContentBottom + " mCurBottom=" + mCurBottom); 2786 } 2787 2788 /** {@inheritDoc} */ 2789 @Override 2790 public void finishLayoutLw() { 2791 return; 2792 } 2793 2794 /** {@inheritDoc} */ 2795 public void beginAnimationLw(int displayWidth, int displayHeight) { 2796 mTopFullscreenOpaqueWindowState = null; 2797 mForceStatusBar = false; 2798 2799 mHideLockScreen = false; 2800 mAllowLockscreenWhenOn = false; 2801 mDismissKeyguard = false; 2802 } 2803 2804 /** {@inheritDoc} */ 2805 public void animatingWindowLw(WindowState win, 2806 WindowManager.LayoutParams attrs) { 2807 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw=" 2808 + win.isVisibleOrBehindKeyguardLw()); 2809 if (mTopFullscreenOpaqueWindowState == null && 2810 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) { 2811 if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) { 2812 mForceStatusBar = true; 2813 } 2814 if (((attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type <= LAST_APPLICATION_WINDOW) 2815 || attrs.type == TYPE_DREAM) 2816 && attrs.x == 0 && attrs.y == 0 2817 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT 2818 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) { 2819 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win); 2820 mTopFullscreenOpaqueWindowState = win; 2821 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) { 2822 if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win); 2823 mHideLockScreen = true; 2824 } 2825 if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) { 2826 if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win); 2827 mDismissKeyguard = true; 2828 } 2829 if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { 2830 mAllowLockscreenWhenOn = true; 2831 } 2832 } 2833 } 2834 } 2835 2836 /** {@inheritDoc} */ 2837 public int finishAnimationLw() { 2838 int changes = 0; 2839 boolean topIsFullscreen = false; 2840 2841 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) 2842 ? mTopFullscreenOpaqueWindowState.getAttrs() 2843 : null; 2844 2845 if (mStatusBar != null) { 2846 if (DEBUG_LAYOUT) Log.i(TAG, "force=" + mForceStatusBar 2847 + " top=" + mTopFullscreenOpaqueWindowState); 2848 if (mForceStatusBar) { 2849 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: forced"); 2850 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; 2851 } else if (mTopFullscreenOpaqueWindowState != null) { 2852 if (localLOGV) { 2853 Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() 2854 + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw()); 2855 Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() 2856 + " lp.flags=0x" + Integer.toHexString(lp.flags)); 2857 } 2858 topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 2859 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 2860 // The subtle difference between the window for mTopFullscreenOpaqueWindowState 2861 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window 2862 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the 2863 // case though. 2864 if (topIsFullscreen) { 2865 if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar"); 2866 if (mStatusBar.hideLw(true)) { 2867 changes |= FINISH_LAYOUT_REDO_LAYOUT; 2868 2869 mHandler.post(new Runnable() { public void run() { 2870 try { 2871 IStatusBarService statusbar = getStatusBarService(); 2872 if (statusbar != null) { 2873 statusbar.collapse(); 2874 } 2875 } catch (RemoteException ex) { 2876 // re-acquire status bar service next time it is needed. 2877 mStatusBarService = null; 2878 } 2879 }}); 2880 } else if (DEBUG_LAYOUT) { 2881 Log.v(TAG, "Preventing status bar from hiding by policy"); 2882 } 2883 } else { 2884 if (DEBUG_LAYOUT) Log.v(TAG, "** SHOWING status bar: top is not fullscreen"); 2885 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; 2886 } 2887 } 2888 } 2889 2890 mTopIsFullscreen = topIsFullscreen; 2891 2892 // Hide the key guard if a visible window explicitly specifies that it wants to be displayed 2893 // when the screen is locked 2894 if (mKeyguard != null) { 2895 if (localLOGV) Log.v(TAG, "finishAnimationLw::mHideKeyguard="+mHideLockScreen); 2896 if (mDismissKeyguard && !mKeyguardMediator.isSecure()) { 2897 if (mKeyguard.hideLw(true)) { 2898 changes |= FINISH_LAYOUT_REDO_LAYOUT 2899 | FINISH_LAYOUT_REDO_CONFIG 2900 | FINISH_LAYOUT_REDO_WALLPAPER; 2901 } 2902 if (mKeyguardMediator.isShowing()) { 2903 mHandler.post(new Runnable() { 2904 public void run() { 2905 mKeyguardMediator.keyguardDone(false, false); 2906 } 2907 }); 2908 } 2909 } else if (mHideLockScreen) { 2910 if (mKeyguard.hideLw(true)) { 2911 changes |= FINISH_LAYOUT_REDO_LAYOUT 2912 | FINISH_LAYOUT_REDO_CONFIG 2913 | FINISH_LAYOUT_REDO_WALLPAPER; 2914 } 2915 mKeyguardMediator.setHidden(true); 2916 } else { 2917 if (mKeyguard.showLw(true)) { 2918 changes |= FINISH_LAYOUT_REDO_LAYOUT 2919 | FINISH_LAYOUT_REDO_CONFIG 2920 | FINISH_LAYOUT_REDO_WALLPAPER; 2921 } 2922 mKeyguardMediator.setHidden(false); 2923 } 2924 } 2925 2926 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 2927 // If the navigation bar has been hidden or shown, we need to do another 2928 // layout pass to update that window. 2929 changes |= FINISH_LAYOUT_REDO_LAYOUT; 2930 } 2931 2932 // update since mAllowLockscreenWhenOn might have changed 2933 updateLockScreenTimeout(); 2934 return changes; 2935 } 2936 2937 public boolean allowAppAnimationsLw() { 2938 if (mKeyguard != null && mKeyguard.isVisibleLw() && !mKeyguard.isAnimatingLw()) { 2939 // If keyguard is currently visible, no reason to animate 2940 // behind it. 2941 return false; 2942 } 2943 return true; 2944 } 2945 2946 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 2947 mFocusedWindow = newFocus; 2948 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 2949 // If the navigation bar has been hidden or shown, we need to do another 2950 // layout pass to update that window. 2951 return FINISH_LAYOUT_REDO_LAYOUT; 2952 } 2953 return 0; 2954 } 2955 2956 /** {@inheritDoc} */ 2957 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 2958 // do nothing if headless 2959 if (mHeadless) return; 2960 2961 // lid changed state 2962 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 2963 if (newLidState == mLidState) { 2964 return; 2965 } 2966 2967 mLidState = newLidState; 2968 applyLidSwitchState(); 2969 updateRotation(true); 2970 2971 if (lidOpen) { 2972 if (keyguardIsShowingTq()) { 2973 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq( 2974 KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED); 2975 } else { 2976 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 2977 } 2978 } else if (!mLidControlsSleep) { 2979 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 2980 } 2981 } 2982 2983 void setHdmiPlugged(boolean plugged) { 2984 if (mHdmiPlugged != plugged) { 2985 mHdmiPlugged = plugged; 2986 updateRotation(true, true); 2987 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 2988 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2989 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 2990 mContext.sendStickyBroadcast(intent); 2991 } 2992 } 2993 2994 void initializeHdmiState() { 2995 boolean plugged = false; 2996 // watch for HDMI plug messages if the hdmi switch exists 2997 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 2998 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 2999 3000 final String filename = "/sys/class/switch/hdmi/state"; 3001 FileReader reader = null; 3002 try { 3003 reader = new FileReader(filename); 3004 char[] buf = new char[15]; 3005 int n = reader.read(buf); 3006 if (n > 1) { 3007 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 3008 } 3009 } catch (IOException ex) { 3010 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 3011 } catch (NumberFormatException ex) { 3012 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 3013 } finally { 3014 if (reader != null) { 3015 try { 3016 reader.close(); 3017 } catch (IOException ex) { 3018 } 3019 } 3020 } 3021 } 3022 // This dance forces the code in setHdmiPlugged to run. 3023 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 3024 mHdmiPlugged = !plugged; 3025 setHdmiPlugged(!mHdmiPlugged); 3026 } 3027 3028 /** 3029 * @return Whether music is being played right now. 3030 */ 3031 boolean isMusicActive() { 3032 final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); 3033 if (am == null) { 3034 Log.w(TAG, "isMusicActive: couldn't get AudioManager reference"); 3035 return false; 3036 } 3037 return am.isMusicActive(); 3038 } 3039 3040 /** 3041 * Tell the audio service to adjust the volume appropriate to the event. 3042 * @param keycode 3043 */ 3044 void handleVolumeKey(int stream, int keycode) { 3045 IAudioService audioService = getAudioService(); 3046 if (audioService == null) { 3047 return; 3048 } 3049 try { 3050 // since audio is playing, we shouldn't have to hold a wake lock 3051 // during the call, but we do it as a precaution for the rare possibility 3052 // that the music stops right before we call this 3053 // TODO: Actually handle MUTE. 3054 mBroadcastWakeLock.acquire(); 3055 audioService.adjustStreamVolume(stream, 3056 keycode == KeyEvent.KEYCODE_VOLUME_UP 3057 ? AudioManager.ADJUST_RAISE 3058 : AudioManager.ADJUST_LOWER, 3059 0); 3060 } catch (RemoteException e) { 3061 Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e); 3062 } finally { 3063 mBroadcastWakeLock.release(); 3064 } 3065 } 3066 3067 final Object mScreenshotLock = new Object(); 3068 ServiceConnection mScreenshotConnection = null; 3069 3070 final Runnable mScreenshotTimeout = new Runnable() { 3071 @Override public void run() { 3072 synchronized (mScreenshotLock) { 3073 if (mScreenshotConnection != null) { 3074 mContext.unbindService(mScreenshotConnection); 3075 mScreenshotConnection = null; 3076 } 3077 } 3078 } 3079 }; 3080 3081 // Assume this is called from the Handler thread. 3082 private void takeScreenshot() { 3083 synchronized (mScreenshotLock) { 3084 if (mScreenshotConnection != null) { 3085 return; 3086 } 3087 ComponentName cn = new ComponentName("com.android.systemui", 3088 "com.android.systemui.screenshot.TakeScreenshotService"); 3089 Intent intent = new Intent(); 3090 intent.setComponent(cn); 3091 ServiceConnection conn = new ServiceConnection() { 3092 @Override 3093 public void onServiceConnected(ComponentName name, IBinder service) { 3094 synchronized (mScreenshotLock) { 3095 if (mScreenshotConnection != this) { 3096 return; 3097 } 3098 Messenger messenger = new Messenger(service); 3099 Message msg = Message.obtain(null, 1); 3100 final ServiceConnection myConn = this; 3101 Handler h = new Handler(mHandler.getLooper()) { 3102 @Override 3103 public void handleMessage(Message msg) { 3104 synchronized (mScreenshotLock) { 3105 if (mScreenshotConnection == myConn) { 3106 mContext.unbindService(mScreenshotConnection); 3107 mScreenshotConnection = null; 3108 mHandler.removeCallbacks(mScreenshotTimeout); 3109 } 3110 } 3111 } 3112 }; 3113 msg.replyTo = new Messenger(h); 3114 msg.arg1 = msg.arg2 = 0; 3115 if (mStatusBar != null && mStatusBar.isVisibleLw()) 3116 msg.arg1 = 1; 3117 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 3118 msg.arg2 = 1; 3119 try { 3120 messenger.send(msg); 3121 } catch (RemoteException e) { 3122 } 3123 } 3124 } 3125 @Override 3126 public void onServiceDisconnected(ComponentName name) {} 3127 }; 3128 if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) { 3129 mScreenshotConnection = conn; 3130 mHandler.postDelayed(mScreenshotTimeout, 10000); 3131 } 3132 } 3133 } 3134 3135 /** {@inheritDoc} */ 3136 @Override 3137 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) { 3138 if (!mSystemBooted) { 3139 // If we have not yet booted, don't let key events do anything. 3140 return 0; 3141 } 3142 3143 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 3144 final boolean canceled = event.isCanceled(); 3145 final int keyCode = event.getKeyCode(); 3146 3147 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 3148 3149 // If screen is off then we treat the case where the keyguard is open but hidden 3150 // the same as if it were open and in front. 3151 // This will prevent any keys other than the power button from waking the screen 3152 // when the keyguard is hidden by another activity. 3153 final boolean keyguardActive = (mKeyguardMediator == null ? false : 3154 (isScreenOn ? 3155 mKeyguardMediator.isShowingAndNotHidden() : 3156 mKeyguardMediator.isShowing())); 3157 3158 if (keyCode == KeyEvent.KEYCODE_POWER) { 3159 policyFlags |= WindowManagerPolicy.FLAG_WAKE; 3160 } 3161 final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE 3162 | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; 3163 3164 if (DEBUG_INPUT) { 3165 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 3166 + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive 3167 + " policyFlags=" + Integer.toHexString(policyFlags) 3168 + " isWakeKey=" + isWakeKey); 3169 } 3170 3171 if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 3172 && event.getRepeatCount() == 0) { 3173 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 3174 } 3175 3176 // Basic policy based on screen state and keyguard. 3177 // FIXME: This policy isn't quite correct. We shouldn't care whether the screen 3178 // is on or off, really. We should care about whether the device is in an 3179 // interactive state or is in suspend pretending to be "off". 3180 // The primary screen might be turned off due to proximity sensor or 3181 // because we are presenting media on an auxiliary screen or remotely controlling 3182 // the device some other way (which is why we have an exemption here for injected 3183 // events). 3184 int result; 3185 if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) { 3186 // When the screen is on or if the key is injected pass the key to the application. 3187 result = ACTION_PASS_TO_USER; 3188 } else { 3189 // When the screen is off and the key is not injected, determine whether 3190 // to wake the device but don't pass the key to the application. 3191 result = 0; 3192 if (down && isWakeKey) { 3193 if (keyguardActive) { 3194 // If the keyguard is showing, let it decide what to do with the wake key. 3195 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode, 3196 mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED); 3197 } else { 3198 // Otherwise, wake the device ourselves. 3199 result |= ACTION_WAKE_UP; 3200 } 3201 } 3202 } 3203 3204 // Handle special keys. 3205 switch (keyCode) { 3206 case KeyEvent.KEYCODE_VOLUME_DOWN: 3207 case KeyEvent.KEYCODE_VOLUME_UP: 3208 case KeyEvent.KEYCODE_VOLUME_MUTE: { 3209 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 3210 if (down) { 3211 if (isScreenOn && !mVolumeDownKeyTriggered 3212 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3213 mVolumeDownKeyTriggered = true; 3214 mVolumeDownKeyTime = event.getDownTime(); 3215 mVolumeDownKeyConsumedByScreenshotChord = false; 3216 cancelPendingPowerKeyAction(); 3217 interceptScreenshotChord(); 3218 } 3219 } else { 3220 mVolumeDownKeyTriggered = false; 3221 cancelPendingScreenshotChordAction(); 3222 } 3223 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 3224 if (down) { 3225 if (isScreenOn && !mVolumeUpKeyTriggered 3226 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3227 mVolumeUpKeyTriggered = true; 3228 cancelPendingPowerKeyAction(); 3229 cancelPendingScreenshotChordAction(); 3230 } 3231 } else { 3232 mVolumeUpKeyTriggered = false; 3233 cancelPendingScreenshotChordAction(); 3234 } 3235 } 3236 if (down) { 3237 ITelephony telephonyService = getTelephonyService(); 3238 if (telephonyService != null) { 3239 try { 3240 if (telephonyService.isRinging()) { 3241 // If an incoming call is ringing, either VOLUME key means 3242 // "silence ringer". We handle these keys here, rather than 3243 // in the InCallScreen, to make sure we'll respond to them 3244 // even if the InCallScreen hasn't come to the foreground yet. 3245 // Look for the DOWN event here, to agree with the "fallback" 3246 // behavior in the InCallScreen. 3247 Log.i(TAG, "interceptKeyBeforeQueueing:" 3248 + " VOLUME key-down while ringing: Silence ringer!"); 3249 3250 // Silence the ringer. (It's safe to call this 3251 // even if the ringer has already been silenced.) 3252 telephonyService.silenceRinger(); 3253 3254 // And *don't* pass this key thru to the current activity 3255 // (which is probably the InCallScreen.) 3256 result &= ~ACTION_PASS_TO_USER; 3257 break; 3258 } 3259 if (telephonyService.isOffhook() 3260 && (result & ACTION_PASS_TO_USER) == 0) { 3261 // If we are in call but we decided not to pass the key to 3262 // the application, handle the volume change here. 3263 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode); 3264 break; 3265 } 3266 } catch (RemoteException ex) { 3267 Log.w(TAG, "ITelephony threw RemoteException", ex); 3268 } 3269 } 3270 3271 if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) { 3272 // If music is playing but we decided not to pass the key to the 3273 // application, handle the volume change here. 3274 handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode); 3275 break; 3276 } 3277 } 3278 break; 3279 } 3280 3281 case KeyEvent.KEYCODE_ENDCALL: { 3282 result &= ~ACTION_PASS_TO_USER; 3283 if (down) { 3284 ITelephony telephonyService = getTelephonyService(); 3285 boolean hungUp = false; 3286 if (telephonyService != null) { 3287 try { 3288 hungUp = telephonyService.endCall(); 3289 } catch (RemoteException ex) { 3290 Log.w(TAG, "ITelephony threw RemoteException", ex); 3291 } 3292 } 3293 interceptPowerKeyDown(!isScreenOn || hungUp); 3294 } else { 3295 if (interceptPowerKeyUp(canceled)) { 3296 if ((mEndcallBehavior 3297 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 3298 if (goHome()) { 3299 break; 3300 } 3301 } 3302 if ((mEndcallBehavior 3303 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 3304 result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP; 3305 } 3306 } 3307 } 3308 break; 3309 } 3310 3311 case KeyEvent.KEYCODE_POWER: { 3312 result &= ~ACTION_PASS_TO_USER; 3313 if (down) { 3314 if (isScreenOn && !mPowerKeyTriggered 3315 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3316 mPowerKeyTriggered = true; 3317 mPowerKeyTime = event.getDownTime(); 3318 interceptScreenshotChord(); 3319 } 3320 3321 ITelephony telephonyService = getTelephonyService(); 3322 boolean hungUp = false; 3323 if (telephonyService != null) { 3324 try { 3325 if (telephonyService.isRinging()) { 3326 // Pressing Power while there's a ringing incoming 3327 // call should silence the ringer. 3328 telephonyService.silenceRinger(); 3329 } else if ((mIncallPowerBehavior 3330 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 3331 && telephonyService.isOffhook()) { 3332 // Otherwise, if "Power button ends call" is enabled, 3333 // the Power button will hang up any current active call. 3334 hungUp = telephonyService.endCall(); 3335 } 3336 } catch (RemoteException ex) { 3337 Log.w(TAG, "ITelephony threw RemoteException", ex); 3338 } 3339 } 3340 interceptPowerKeyDown(!isScreenOn || hungUp 3341 || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered); 3342 } else { 3343 mPowerKeyTriggered = false; 3344 cancelPendingScreenshotChordAction(); 3345 if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) { 3346 result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP; 3347 } 3348 mPendingPowerKeyUpCanceled = false; 3349 } 3350 break; 3351 } 3352 3353 case KeyEvent.KEYCODE_MEDIA_PLAY: 3354 case KeyEvent.KEYCODE_MEDIA_PAUSE: 3355 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 3356 if (down) { 3357 ITelephony telephonyService = getTelephonyService(); 3358 if (telephonyService != null) { 3359 try { 3360 if (!telephonyService.isIdle()) { 3361 // Suppress PLAY/PAUSE toggle when phone is ringing or in-call 3362 // to avoid music playback. 3363 break; 3364 } 3365 } catch (RemoteException ex) { 3366 Log.w(TAG, "ITelephony threw RemoteException", ex); 3367 } 3368 } 3369 } 3370 case KeyEvent.KEYCODE_HEADSETHOOK: 3371 case KeyEvent.KEYCODE_MUTE: 3372 case KeyEvent.KEYCODE_MEDIA_STOP: 3373 case KeyEvent.KEYCODE_MEDIA_NEXT: 3374 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 3375 case KeyEvent.KEYCODE_MEDIA_REWIND: 3376 case KeyEvent.KEYCODE_MEDIA_RECORD: 3377 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { 3378 if ((result & ACTION_PASS_TO_USER) == 0) { 3379 // Only do this if we would otherwise not pass it to the user. In that 3380 // case, the PhoneWindow class will do the same thing, except it will 3381 // only do it if the showing app doesn't process the key on its own. 3382 // Note that we need to make a copy of the key event here because the 3383 // original key event will be recycled when we return. 3384 mBroadcastWakeLock.acquire(); 3385 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 3386 new KeyEvent(event)); 3387 msg.setAsynchronous(true); 3388 msg.sendToTarget(); 3389 } 3390 break; 3391 } 3392 3393 case KeyEvent.KEYCODE_CALL: { 3394 if (down) { 3395 ITelephony telephonyService = getTelephonyService(); 3396 if (telephonyService != null) { 3397 try { 3398 if (telephonyService.isRinging()) { 3399 Log.i(TAG, "interceptKeyBeforeQueueing:" 3400 + " CALL key-down while ringing: Answer the call!"); 3401 telephonyService.answerRingingCall(); 3402 3403 // And *don't* pass this key thru to the current activity 3404 // (which is presumably the InCallScreen.) 3405 result &= ~ACTION_PASS_TO_USER; 3406 } 3407 } catch (RemoteException ex) { 3408 Log.w(TAG, "ITelephony threw RemoteException", ex); 3409 } 3410 } 3411 } 3412 break; 3413 } 3414 } 3415 return result; 3416 } 3417 3418 /** {@inheritDoc} */ 3419 @Override 3420 public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) { 3421 int result = 0; 3422 3423 final boolean isWakeMotion = (policyFlags 3424 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; 3425 if (isWakeMotion) { 3426 if (mKeyguardMediator != null && mKeyguardMediator.isShowing()) { 3427 // If the keyguard is showing, let it decide what to do with the wake motion. 3428 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq(); 3429 } else { 3430 // Otherwise, wake the device ourselves. 3431 result |= ACTION_WAKE_UP; 3432 } 3433 } 3434 return result; 3435 } 3436 3437 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 3438 if (DEBUG_INPUT) { 3439 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 3440 } 3441 3442 if (mHavePendingMediaKeyRepeatWithWakeLock) { 3443 if (DEBUG_INPUT) { 3444 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 3445 } 3446 3447 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 3448 mHavePendingMediaKeyRepeatWithWakeLock = false; 3449 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 3450 } 3451 3452 dispatchMediaKeyWithWakeLockToAudioService(event); 3453 3454 if (event.getAction() == KeyEvent.ACTION_DOWN 3455 && event.getRepeatCount() == 0) { 3456 mHavePendingMediaKeyRepeatWithWakeLock = true; 3457 3458 Message msg = mHandler.obtainMessage( 3459 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 3460 msg.setAsynchronous(true); 3461 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 3462 } else { 3463 mBroadcastWakeLock.release(); 3464 } 3465 } 3466 3467 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 3468 mHavePendingMediaKeyRepeatWithWakeLock = false; 3469 3470 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 3471 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 3472 if (DEBUG_INPUT) { 3473 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 3474 } 3475 3476 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 3477 mBroadcastWakeLock.release(); 3478 } 3479 3480 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 3481 if (ActivityManagerNative.isSystemReady()) { 3482 IAudioService audioService = getAudioService(); 3483 if (audioService != null) { 3484 try { 3485 audioService.dispatchMediaKeyEventUnderWakelock(event); 3486 } catch (RemoteException e) { 3487 Log.e(TAG, "dispatchMediaKeyEvent threw exception " + e); 3488 } 3489 } 3490 } 3491 } 3492 3493 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 3494 public void onReceive(Context context, Intent intent) { 3495 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 3496 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 3497 Intent.EXTRA_DOCK_STATE_UNDOCKED); 3498 } else { 3499 try { 3500 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 3501 ServiceManager.getService(Context.UI_MODE_SERVICE)); 3502 mUiMode = uiModeService.getCurrentModeType(); 3503 } catch (RemoteException e) { 3504 } 3505 } 3506 updateRotation(true); 3507 updateOrientationListenerLp(); 3508 } 3509 }; 3510 3511 /** {@inheritDoc} */ 3512 public void screenTurnedOff(int why) { 3513 EventLog.writeEvent(70000, 0); 3514 synchronized (mLock) { 3515 mScreenOnEarly = false; 3516 mScreenOnFully = false; 3517 } 3518 if (mKeyguardMediator != null) { 3519 mKeyguardMediator.onScreenTurnedOff(why); 3520 } 3521 synchronized (mLock) { 3522 updateOrientationListenerLp(); 3523 updateLockScreenTimeout(); 3524 } 3525 } 3526 3527 /** {@inheritDoc} */ 3528 public void screenTurningOn(final ScreenOnListener screenOnListener) { 3529 EventLog.writeEvent(70000, 1); 3530 if (false) { 3531 RuntimeException here = new RuntimeException("here"); 3532 here.fillInStackTrace(); 3533 Slog.i(TAG, "Screen turning on...", here); 3534 } 3535 if (screenOnListener != null) { 3536 if (mKeyguardMediator != null) { 3537 try { 3538 mWindowManager.setEventDispatching(true); 3539 } catch (RemoteException unhandled) { 3540 } 3541 mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() { 3542 @Override public void onShown(IBinder windowToken) { 3543 if (windowToken != null) { 3544 try { 3545 mWindowManager.waitForWindowDrawn(windowToken, 3546 new IRemoteCallback.Stub() { 3547 @Override public void sendResult(Bundle data) { 3548 Slog.i(TAG, "Lock screen displayed!"); 3549 screenOnListener.onScreenOn(); 3550 synchronized (mLock) { 3551 mScreenOnFully = true; 3552 } 3553 } 3554 }); 3555 } catch (RemoteException e) { 3556 } 3557 } else { 3558 Slog.i(TAG, "No lock screen!"); 3559 screenOnListener.onScreenOn(); 3560 synchronized (mLock) { 3561 mScreenOnFully = true; 3562 } 3563 } 3564 } 3565 }); 3566 } 3567 } else { 3568 if (mKeyguardMediator != null) { 3569 // Must set mScreenOn = true. 3570 mKeyguardMediator.onScreenTurnedOn(null); 3571 } 3572 synchronized (mLock) { 3573 mScreenOnFully = true; 3574 } 3575 } 3576 synchronized (mLock) { 3577 mScreenOnEarly = true; 3578 updateOrientationListenerLp(); 3579 updateLockScreenTimeout(); 3580 } 3581 } 3582 3583 /** {@inheritDoc} */ 3584 public boolean isScreenOnEarly() { 3585 return mScreenOnEarly; 3586 } 3587 3588 /** {@inheritDoc} */ 3589 public boolean isScreenOnFully() { 3590 return mScreenOnFully; 3591 } 3592 3593 /** {@inheritDoc} */ 3594 public void enableKeyguard(boolean enabled) { 3595 if (mKeyguardMediator != null) { 3596 mKeyguardMediator.setKeyguardEnabled(enabled); 3597 } 3598 } 3599 3600 /** {@inheritDoc} */ 3601 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 3602 if (mKeyguardMediator != null) { 3603 mKeyguardMediator.verifyUnlock(callback); 3604 } 3605 } 3606 3607 private boolean keyguardIsShowingTq() { 3608 if (mKeyguardMediator == null) return false; 3609 return mKeyguardMediator.isShowingAndNotHidden(); 3610 } 3611 3612 3613 /** {@inheritDoc} */ 3614 public boolean isKeyguardLocked() { 3615 return keyguardOn(); 3616 } 3617 3618 /** {@inheritDoc} */ 3619 public boolean isKeyguardSecure() { 3620 if (mKeyguardMediator == null) return false; 3621 return mKeyguardMediator.isSecure(); 3622 } 3623 3624 /** {@inheritDoc} */ 3625 public boolean inKeyguardRestrictedKeyInputMode() { 3626 if (mKeyguardMediator == null) return false; 3627 return mKeyguardMediator.isInputRestricted(); 3628 } 3629 3630 public void dismissKeyguardLw() { 3631 if (!mKeyguardMediator.isSecure()) { 3632 if (mKeyguardMediator.isShowing()) { 3633 mHandler.post(new Runnable() { 3634 public void run() { 3635 mKeyguardMediator.keyguardDone(false, true); 3636 } 3637 }); 3638 } 3639 } 3640 } 3641 3642 void sendCloseSystemWindows() { 3643 sendCloseSystemWindows(mContext, null); 3644 } 3645 3646 void sendCloseSystemWindows(String reason) { 3647 sendCloseSystemWindows(mContext, reason); 3648 } 3649 3650 static void sendCloseSystemWindows(Context context, String reason) { 3651 if (ActivityManagerNative.isSystemReady()) { 3652 try { 3653 ActivityManagerNative.getDefault().closeSystemDialogs(reason); 3654 } catch (RemoteException e) { 3655 } 3656 } 3657 } 3658 3659 @Override 3660 public int rotationForOrientationLw(int orientation, int lastRotation) { 3661 if (false) { 3662 Slog.v(TAG, "rotationForOrientationLw(orient=" 3663 + orientation + ", last=" + lastRotation 3664 + "); user=" + mUserRotation + " " 3665 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 3666 ? "USER_ROTATION_LOCKED" : "") 3667 ); 3668 } 3669 3670 synchronized (mLock) { 3671 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 3672 if (sensorRotation < 0) { 3673 // Sensor is disabled, device probably just turned off. 3674 if (mLastSensorRotation >= 0) { 3675 sensorRotation = mLastSensorRotation; 3676 } else { 3677 // Sensor has never been enabled. Last resort is to use lastRotation. 3678 sensorRotation = lastRotation; 3679 } 3680 } else { 3681 // Valid sensor data, save it away. 3682 mLastSensorRotation = sensorRotation; 3683 } 3684 3685 final int preferredRotation; 3686 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 3687 // Ignore sensor when lid switch is open and rotation is forced. 3688 preferredRotation = mLidOpenRotation; 3689 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 3690 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 3691 // Ignore sensor when in car dock unless explicitly enabled. 3692 // This case can override the behavior of NOSENSOR, and can also 3693 // enable 180 degree rotation while docked. 3694 preferredRotation = mCarDockEnablesAccelerometer 3695 ? sensorRotation : mCarDockRotation; 3696 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 3697 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 3698 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 3699 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 3700 // Ignore sensor when in desk dock unless explicitly enabled. 3701 // This case can override the behavior of NOSENSOR, and can also 3702 // enable 180 degree rotation while docked. 3703 preferredRotation = mDeskDockEnablesAccelerometer 3704 ? sensorRotation : mDeskDockRotation; 3705 } else if (mHdmiPlugged) { 3706 // Ignore sensor when plugged into HDMI. 3707 // Note that the dock orientation overrides the HDMI orientation. 3708 preferredRotation = mHdmiRotation; 3709 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 3710 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 3711 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) 3712 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 3713 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 3714 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 3715 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 3716 // Otherwise, use sensor only if requested by the application or enabled 3717 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 3718 if (mAllowAllRotations < 0) { 3719 // Can't read this during init() because the context doesn't 3720 // have display metrics at that time so we cannot determine 3721 // tablet vs. phone then. 3722 mAllowAllRotations = mContext.getResources().getBoolean( 3723 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 3724 } 3725 if (sensorRotation != Surface.ROTATION_180 3726 || mAllowAllRotations == 1 3727 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) { 3728 preferredRotation = sensorRotation; 3729 } else { 3730 preferredRotation = lastRotation; 3731 } 3732 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 3733 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 3734 // Apply rotation lock. Does not apply to NOSENSOR. 3735 // The idea is that the user rotation expresses a weak preference for the direction 3736 // of gravity and as NOSENSOR is never affected by gravity, then neither should 3737 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 3738 preferredRotation = mUserRotation; 3739 } else { 3740 // No overriding preference. 3741 // We will do exactly what the application asked us to do. 3742 preferredRotation = -1; 3743 } 3744 3745 switch (orientation) { 3746 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 3747 // Return portrait unless overridden. 3748 if (isAnyPortrait(preferredRotation)) { 3749 return preferredRotation; 3750 } 3751 return mPortraitRotation; 3752 3753 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 3754 // Return landscape unless overridden. 3755 if (isLandscapeOrSeascape(preferredRotation)) { 3756 return preferredRotation; 3757 } 3758 return mLandscapeRotation; 3759 3760 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 3761 // Return reverse portrait unless overridden. 3762 if (isAnyPortrait(preferredRotation)) { 3763 return preferredRotation; 3764 } 3765 return mUpsideDownRotation; 3766 3767 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 3768 // Return seascape unless overridden. 3769 if (isLandscapeOrSeascape(preferredRotation)) { 3770 return preferredRotation; 3771 } 3772 return mSeascapeRotation; 3773 3774 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 3775 // Return either landscape rotation. 3776 if (isLandscapeOrSeascape(preferredRotation)) { 3777 return preferredRotation; 3778 } 3779 if (isLandscapeOrSeascape(lastRotation)) { 3780 return lastRotation; 3781 } 3782 return mLandscapeRotation; 3783 3784 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 3785 // Return either portrait rotation. 3786 if (isAnyPortrait(preferredRotation)) { 3787 return preferredRotation; 3788 } 3789 if (isAnyPortrait(lastRotation)) { 3790 return lastRotation; 3791 } 3792 return mPortraitRotation; 3793 3794 default: 3795 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 3796 // just return the preferred orientation we already calculated. 3797 if (preferredRotation >= 0) { 3798 return preferredRotation; 3799 } 3800 return Surface.ROTATION_0; 3801 } 3802 } 3803 } 3804 3805 @Override 3806 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 3807 switch (orientation) { 3808 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 3809 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 3810 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 3811 return isAnyPortrait(rotation); 3812 3813 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 3814 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 3815 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 3816 return isLandscapeOrSeascape(rotation); 3817 3818 default: 3819 return true; 3820 } 3821 } 3822 3823 @Override 3824 public void setRotationLw(int rotation) { 3825 mOrientationListener.setCurrentRotation(rotation); 3826 } 3827 3828 private boolean isLandscapeOrSeascape(int rotation) { 3829 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 3830 } 3831 3832 private boolean isAnyPortrait(int rotation) { 3833 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 3834 } 3835 3836 3837 // User rotation: to be used when all else fails in assigning an orientation to the device 3838 public void setUserRotationMode(int mode, int rot) { 3839 ContentResolver res = mContext.getContentResolver(); 3840 3841 // mUserRotationMode and mUserRotation will be assigned by the content observer 3842 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 3843 Settings.System.putInt(res, 3844 Settings.System.USER_ROTATION, 3845 rot); 3846 Settings.System.putInt(res, 3847 Settings.System.ACCELEROMETER_ROTATION, 3848 0); 3849 } else { 3850 Settings.System.putInt(res, 3851 Settings.System.ACCELEROMETER_ROTATION, 3852 1); 3853 } 3854 } 3855 3856 public void setSafeMode(boolean safeMode) { 3857 mSafeMode = safeMode; 3858 performHapticFeedbackLw(null, safeMode 3859 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 3860 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 3861 } 3862 3863 static long[] getLongIntArray(Resources r, int resid) { 3864 int[] ar = r.getIntArray(resid); 3865 if (ar == null) { 3866 return null; 3867 } 3868 long[] out = new long[ar.length]; 3869 for (int i=0; i<ar.length; i++) { 3870 out[i] = ar[i]; 3871 } 3872 return out; 3873 } 3874 3875 /** {@inheritDoc} */ 3876 public void systemReady() { 3877 if (mKeyguardMediator != null) { 3878 // tell the keyguard 3879 mKeyguardMediator.onSystemReady(); 3880 } 3881 synchronized (mLock) { 3882 updateOrientationListenerLp(); 3883 mSystemReady = true; 3884 mHandler.post(new Runnable() { 3885 public void run() { 3886 updateSettings(); 3887 } 3888 }); 3889 } 3890 } 3891 3892 /** {@inheritDoc} */ 3893 public void systemBooted() { 3894 synchronized (mLock) { 3895 mSystemBooted = true; 3896 } 3897 } 3898 3899 ProgressDialog mBootMsgDialog = null; 3900 3901 /** {@inheritDoc} */ 3902 public void showBootMessage(final CharSequence msg, final boolean always) { 3903 if (mHeadless) return; 3904 mHandler.post(new Runnable() { 3905 @Override public void run() { 3906 if (mBootMsgDialog == null) { 3907 mBootMsgDialog = new ProgressDialog(mContext) { 3908 // This dialog will consume all events coming in to 3909 // it, to avoid it trying to do things too early in boot. 3910 @Override public boolean dispatchKeyEvent(KeyEvent event) { 3911 return true; 3912 } 3913 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 3914 return true; 3915 } 3916 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 3917 return true; 3918 } 3919 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 3920 return true; 3921 } 3922 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 3923 return true; 3924 } 3925 @Override public boolean dispatchPopulateAccessibilityEvent( 3926 AccessibilityEvent event) { 3927 return true; 3928 } 3929 }; 3930 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 3931 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 3932 mBootMsgDialog.setIndeterminate(true); 3933 mBootMsgDialog.getWindow().setType( 3934 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 3935 mBootMsgDialog.getWindow().addFlags( 3936 WindowManager.LayoutParams.FLAG_DIM_BEHIND 3937 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 3938 mBootMsgDialog.getWindow().setDimAmount(1); 3939 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 3940 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 3941 mBootMsgDialog.getWindow().setAttributes(lp); 3942 mBootMsgDialog.setCancelable(false); 3943 mBootMsgDialog.show(); 3944 } 3945 mBootMsgDialog.setMessage(msg); 3946 } 3947 }); 3948 } 3949 3950 /** {@inheritDoc} */ 3951 public void hideBootMessages() { 3952 mHandler.post(new Runnable() { 3953 @Override public void run() { 3954 if (mBootMsgDialog != null) { 3955 mBootMsgDialog.dismiss(); 3956 mBootMsgDialog = null; 3957 } 3958 } 3959 }); 3960 } 3961 3962 /** {@inheritDoc} */ 3963 public void userActivity() { 3964 // *************************************** 3965 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 3966 // *************************************** 3967 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 3968 // WITH ITS LOCKS HELD. 3969 // 3970 // This code must be VERY careful about the locks 3971 // it acquires. 3972 // In fact, the current code acquires way too many, 3973 // and probably has lurking deadlocks. 3974 3975 synchronized (mScreenLockTimeout) { 3976 if (mLockScreenTimerActive) { 3977 // reset the timer 3978 mHandler.removeCallbacks(mScreenLockTimeout); 3979 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 3980 } 3981 } 3982 } 3983 3984 Runnable mScreenLockTimeout = new Runnable() { 3985 public void run() { 3986 synchronized (this) { 3987 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 3988 if (mKeyguardMediator != null) { 3989 mKeyguardMediator.doKeyguardTimeout(); 3990 } 3991 mLockScreenTimerActive = false; 3992 } 3993 } 3994 }; 3995 3996 public void lockNow() { 3997 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 3998 mHandler.removeCallbacks(mScreenLockTimeout); 3999 mHandler.post(mScreenLockTimeout); 4000 } 4001 4002 private void updateLockScreenTimeout() { 4003 synchronized (mScreenLockTimeout) { 4004 boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly && 4005 mKeyguardMediator != null && mKeyguardMediator.isSecure()); 4006 if (mLockScreenTimerActive != enable) { 4007 if (enable) { 4008 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 4009 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 4010 } else { 4011 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 4012 mHandler.removeCallbacks(mScreenLockTimeout); 4013 } 4014 mLockScreenTimerActive = enable; 4015 } 4016 } 4017 } 4018 4019 /** {@inheritDoc} */ 4020 public void enableScreenAfterBoot() { 4021 readLidState(); 4022 applyLidSwitchState(); 4023 updateRotation(true); 4024 } 4025 4026 private void applyLidSwitchState() { 4027 if (mLidState == LID_CLOSED && mLidControlsSleep) { 4028 mPowerManager.goToSleep(SystemClock.uptimeMillis()); 4029 } 4030 } 4031 4032 void updateRotation(boolean alwaysSendConfiguration) { 4033 try { 4034 //set orientation on WindowManager 4035 mWindowManager.updateRotation(alwaysSendConfiguration, false); 4036 } catch (RemoteException e) { 4037 // Ignore 4038 } 4039 } 4040 4041 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 4042 try { 4043 //set orientation on WindowManager 4044 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 4045 } catch (RemoteException e) { 4046 // Ignore 4047 } 4048 } 4049 4050 /** 4051 * Return an Intent to launch the currently active dock app as home. Returns 4052 * null if the standard home should be launched, which is the case if any of the following is 4053 * true: 4054 * <ul> 4055 * <li>The device is not in either car mode or desk mode 4056 * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false 4057 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 4058 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 4059 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 4060 * </ul> 4061 * @return 4062 */ 4063 Intent createHomeDockIntent() { 4064 Intent intent = null; 4065 4066 // What home does is based on the mode, not the dock state. That 4067 // is, when in car mode you should be taken to car home regardless 4068 // of whether we are actually in a car dock. 4069 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 4070 if (ENABLE_CAR_DOCK_HOME_CAPTURE) { 4071 intent = mCarDockIntent; 4072 } 4073 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 4074 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 4075 intent = mDeskDockIntent; 4076 } 4077 } 4078 4079 if (intent == null) { 4080 return null; 4081 } 4082 4083 ActivityInfo ai = intent.resolveActivityInfo( 4084 mContext.getPackageManager(), PackageManager.GET_META_DATA); 4085 if (ai == null) { 4086 return null; 4087 } 4088 4089 if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 4090 intent = new Intent(intent); 4091 intent.setClassName(ai.packageName, ai.name); 4092 return intent; 4093 } 4094 4095 return null; 4096 } 4097 4098 void startDockOrHome() { 4099 Intent dock = createHomeDockIntent(); 4100 if (dock != null) { 4101 try { 4102 mContext.startActivity(dock); 4103 return; 4104 } catch (ActivityNotFoundException e) { 4105 } 4106 } 4107 mContext.startActivity(mHomeIntent); 4108 } 4109 4110 /** 4111 * goes to the home screen 4112 * @return whether it did anything 4113 */ 4114 boolean goHome() { 4115 if (false) { 4116 // This code always brings home to the front. 4117 try { 4118 ActivityManagerNative.getDefault().stopAppSwitches(); 4119 } catch (RemoteException e) { 4120 } 4121 sendCloseSystemWindows(); 4122 startDockOrHome(); 4123 } else { 4124 // This code brings home to the front or, if it is already 4125 // at the front, puts the device to sleep. 4126 try { 4127 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 4128 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 4129 Log.d(TAG, "UTS-TEST-MODE"); 4130 } else { 4131 ActivityManagerNative.getDefault().stopAppSwitches(); 4132 sendCloseSystemWindows(); 4133 Intent dock = createHomeDockIntent(); 4134 if (dock != null) { 4135 int result = ActivityManagerNative.getDefault() 4136 .startActivity(null, dock, 4137 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 4138 null, null, 0, 4139 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 4140 null, null, null); 4141 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 4142 return false; 4143 } 4144 } 4145 } 4146 int result = ActivityManagerNative.getDefault() 4147 .startActivity(null, mHomeIntent, 4148 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 4149 null, null, 0, 4150 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 4151 null, null, null); 4152 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 4153 return false; 4154 } 4155 } catch (RemoteException ex) { 4156 // bummer, the activity manager, which is in this process, is dead 4157 } 4158 } 4159 return true; 4160 } 4161 4162 public void setCurrentOrientationLw(int newOrientation) { 4163 synchronized (mLock) { 4164 if (newOrientation != mCurrentAppOrientation) { 4165 mCurrentAppOrientation = newOrientation; 4166 updateOrientationListenerLp(); 4167 } 4168 } 4169 } 4170 4171 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 4172 final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(), 4173 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0; 4174 if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) { 4175 return false; 4176 } 4177 long[] pattern = null; 4178 switch (effectId) { 4179 case HapticFeedbackConstants.LONG_PRESS: 4180 pattern = mLongPressVibePattern; 4181 break; 4182 case HapticFeedbackConstants.VIRTUAL_KEY: 4183 pattern = mVirtualKeyVibePattern; 4184 break; 4185 case HapticFeedbackConstants.KEYBOARD_TAP: 4186 pattern = mKeyboardTapVibePattern; 4187 break; 4188 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 4189 pattern = mSafeModeDisabledVibePattern; 4190 break; 4191 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 4192 pattern = mSafeModeEnabledVibePattern; 4193 break; 4194 default: 4195 return false; 4196 } 4197 if (pattern.length == 1) { 4198 // One-shot vibration 4199 mVibrator.vibrate(pattern[0]); 4200 } else { 4201 // Pattern vibration 4202 mVibrator.vibrate(pattern, -1); 4203 } 4204 return true; 4205 } 4206 4207 public void screenOnStartedLw() { 4208 } 4209 4210 public void screenOnStoppedLw() { 4211 if (mPowerManager.isScreenOn()) { 4212 if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) { 4213 long curTime = SystemClock.uptimeMillis(); 4214 mPowerManager.userActivity(curTime, false); 4215 } 4216 } 4217 } 4218 4219 public boolean allowKeyRepeat() { 4220 // disable key repeat when screen is off 4221 return mScreenOnEarly; 4222 } 4223 4224 private int updateSystemUiVisibilityLw() { 4225 // If there is no window focused, there will be nobody to handle the events 4226 // anyway, so just hang on in whatever state we're in until things settle down. 4227 if (mFocusedWindow == null) { 4228 return 0; 4229 } 4230 final int visibility = mFocusedWindow.getSystemUiVisibility() 4231 & ~mResettingSystemUiFlags 4232 & ~mForceClearedSystemUiFlags; 4233 int diff = visibility ^ mLastSystemUiFlags; 4234 final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 4235 if (diff == 0 && mLastFocusNeedsMenu == needsMenu 4236 && mFocusedApp == mFocusedWindow.getAppToken()) { 4237 return 0; 4238 } 4239 mLastSystemUiFlags = visibility; 4240 mLastFocusNeedsMenu = needsMenu; 4241 mFocusedApp = mFocusedWindow.getAppToken(); 4242 mHandler.post(new Runnable() { 4243 public void run() { 4244 try { 4245 IStatusBarService statusbar = getStatusBarService(); 4246 if (statusbar != null) { 4247 statusbar.setSystemUiVisibility(visibility, 0xffffffff); 4248 statusbar.topAppWindowChanged(needsMenu); 4249 } 4250 } catch (RemoteException e) { 4251 // re-acquire status bar service next time it is needed. 4252 mStatusBarService = null; 4253 } 4254 } 4255 }); 4256 return diff; 4257 } 4258 4259 // Use this instead of checking config_showNavigationBar so that it can be consistently 4260 // overridden by qemu.hw.mainkeys in the emulator. 4261 public boolean hasNavigationBar() { 4262 return mHasNavigationBar; 4263 } 4264 4265 @Override 4266 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 4267 mLastInputMethodWindow = ime; 4268 mLastInputMethodTargetWindow = target; 4269 } 4270 4271 public void dump(String prefix, PrintWriter pw, String[] args) { 4272 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 4273 pw.print(" mSystemReady="); pw.print(mSystemReady); 4274 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 4275 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 4276 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 4277 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 4278 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 4279 || mForceClearedSystemUiFlags != 0) { 4280 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 4281 pw.print(Integer.toHexString(mLastSystemUiFlags)); 4282 pw.print(" mResettingSystemUiFlags=0x"); 4283 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 4284 pw.print(" mForceClearedSystemUiFlags=0x"); 4285 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 4286 } 4287 if (mLastFocusNeedsMenu) { 4288 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 4289 pw.println(mLastFocusNeedsMenu); 4290 } 4291 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 4292 pw.print(" mDockMode="); pw.print(mDockMode); 4293 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 4294 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 4295 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 4296 pw.print(" mUserRotation="); pw.print(mUserRotation); 4297 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 4298 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 4299 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 4300 pw.print(mCarDockEnablesAccelerometer); 4301 pw.print(" mDeskDockEnablesAccelerometer="); 4302 pw.println(mDeskDockEnablesAccelerometer); 4303 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 4304 pw.print(mLidKeyboardAccessibility); 4305 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 4306 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 4307 pw.print(prefix); pw.print("mLongPressOnPowerBehavior="); 4308 pw.print(mLongPressOnPowerBehavior); 4309 pw.print(" mHasSoftInput="); pw.println(mHasSoftInput); 4310 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 4311 pw.print(" mScreenOnFully="); pw.print(mScreenOnFully); 4312 pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled); 4313 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 4314 pw.print(","); pw.print(mUnrestrictedScreenTop); 4315 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 4316 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 4317 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 4318 pw.print(","); pw.print(mRestrictedScreenTop); 4319 pw.print(") "); pw.print(mRestrictedScreenWidth); 4320 pw.print("x"); pw.println(mRestrictedScreenHeight); 4321 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 4322 pw.print(","); pw.print(mStableFullscreenTop); 4323 pw.print(")-("); pw.print(mStableFullscreenRight); 4324 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 4325 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 4326 pw.print(","); pw.print(mStableTop); 4327 pw.print(")-("); pw.print(mStableRight); 4328 pw.print(","); pw.print(mStableBottom); pw.println(")"); 4329 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 4330 pw.print(","); pw.print(mSystemTop); 4331 pw.print(")-("); pw.print(mSystemRight); 4332 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 4333 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 4334 pw.print(","); pw.print(mCurTop); 4335 pw.print(")-("); pw.print(mCurRight); 4336 pw.print(","); pw.print(mCurBottom); pw.println(")"); 4337 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 4338 pw.print(","); pw.print(mContentTop); 4339 pw.print(")-("); pw.print(mContentRight); 4340 pw.print(","); pw.print(mContentBottom); pw.println(")"); 4341 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 4342 pw.print(","); pw.print(mDockTop); 4343 pw.print(")-("); pw.print(mDockRight); 4344 pw.print(","); pw.print(mDockBottom); pw.println(")"); 4345 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 4346 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 4347 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 4348 pw.println(mTopFullscreenOpaqueWindowState); 4349 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 4350 pw.print(" mForceStatusBar="); pw.print(mForceStatusBar); 4351 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen); 4352 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard); 4353 pw.print(" mHomePressed="); pw.println(mHomePressed); 4354 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 4355 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 4356 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 4357 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 4358 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 4359 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 4360 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 4361 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 4362 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 4363 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 4364 } 4365} 4366