PhoneWindowManager.java revision 9630704ed3b265f008a8f64ec60a33cf9dcd3345
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.UserId; 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 try { 1721 IStatusBarService statusbar = getStatusBarService(); 1722 if (statusbar != null) { 1723 statusbar.cancelPreloadRecentApps(); 1724 } 1725 } catch (RemoteException e) { 1726 Slog.e(TAG, "RemoteException when showing recent apps", e); 1727 // re-acquire status bar service next time it is needed. 1728 mStatusBarService = null; 1729 } 1730 1731 mHomePressed = false; 1732 if (!canceled) { 1733 // If an incoming call is ringing, HOME is totally disabled. 1734 // (The user is already on the InCallScreen at this point, 1735 // and his ONLY options are to answer or reject the call.) 1736 boolean incomingRinging = false; 1737 try { 1738 ITelephony telephonyService = getTelephonyService(); 1739 if (telephonyService != null) { 1740 incomingRinging = telephonyService.isRinging(); 1741 } 1742 } catch (RemoteException ex) { 1743 Log.w(TAG, "RemoteException from getPhoneInterface()", ex); 1744 } 1745 1746 if (incomingRinging) { 1747 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call."); 1748 } else { 1749 launchHomeFromHotKey(); 1750 } 1751 } else { 1752 Log.i(TAG, "Ignoring HOME; event canceled."); 1753 } 1754 return -1; 1755 } 1756 } 1757 1758 // If a system window has focus, then it doesn't make sense 1759 // right now to interact with applications. 1760 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null; 1761 if (attrs != null) { 1762 final int type = attrs.type; 1763 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD 1764 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) { 1765 // the "app" is keyguard, so give it the key 1766 return 0; 1767 } 1768 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length; 1769 for (int i=0; i<typeCount; i++) { 1770 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) { 1771 // don't do anything, but also don't pass it to the app 1772 return -1; 1773 } 1774 } 1775 } 1776 if (down) { 1777 if (!mHomePressed && mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) { 1778 try { 1779 IStatusBarService statusbar = getStatusBarService(); 1780 if (statusbar != null) { 1781 statusbar.preloadRecentApps(); 1782 } 1783 } catch (RemoteException e) { 1784 Slog.e(TAG, "RemoteException when preloading recent apps", e); 1785 // re-acquire status bar service next time it is needed. 1786 mStatusBarService = null; 1787 } 1788 } 1789 if (repeatCount == 0) { 1790 mHomePressed = true; 1791 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) { 1792 if (!keyguardOn) { 1793 handleLongPressOnHome(); 1794 } 1795 } 1796 } 1797 return -1; 1798 } else if (keyCode == KeyEvent.KEYCODE_MENU) { 1799 // Hijack modified menu keys for debugging features 1800 final int chordBug = KeyEvent.META_SHIFT_ON; 1801 1802 if (down && repeatCount == 0) { 1803 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) { 1804 Intent intent = new Intent(Intent.ACTION_BUG_REPORT); 1805 mContext.sendOrderedBroadcast(intent, null); 1806 return -1; 1807 } else if (SHOW_PROCESSES_ON_ALT_MENU && 1808 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) { 1809 Intent service = new Intent(); 1810 service.setClassName(mContext, "com.android.server.LoadAverageService"); 1811 ContentResolver res = mContext.getContentResolver(); 1812 boolean shown = Settings.System.getInt( 1813 res, Settings.System.SHOW_PROCESSES, 0) != 0; 1814 if (!shown) { 1815 mContext.startService(service); 1816 } else { 1817 mContext.stopService(service); 1818 } 1819 Settings.System.putInt( 1820 res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1); 1821 return -1; 1822 } 1823 } 1824 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) { 1825 if (down) { 1826 if (repeatCount == 0) { 1827 mSearchKeyShortcutPending = true; 1828 mConsumeSearchKeyUp = false; 1829 } 1830 } else { 1831 mSearchKeyShortcutPending = false; 1832 if (mConsumeSearchKeyUp) { 1833 mConsumeSearchKeyUp = false; 1834 return -1; 1835 } 1836 } 1837 return 0; 1838 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { 1839 if (down && repeatCount == 0 && !keyguardOn) { 1840 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS); 1841 } 1842 return -1; 1843 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) { 1844 if (down) { 1845 if (repeatCount == 0) { 1846 mAssistKeyLongPressed = false; 1847 } else if (repeatCount == 1) { 1848 mAssistKeyLongPressed = true; 1849 if (!keyguardOn) { 1850 launchAssistLongPressAction(); 1851 } 1852 } 1853 } else { 1854 if (mAssistKeyLongPressed) { 1855 mAssistKeyLongPressed = false; 1856 } else { 1857 if (!keyguardOn) { 1858 launchAssistAction(); 1859 } 1860 } 1861 } 1862 return -1; 1863 } 1864 1865 // Shortcuts are invoked through Search+key, so intercept those here 1866 // Any printing key that is chorded with Search should be consumed 1867 // even if no shortcut was invoked. This prevents text from being 1868 // inadvertently inserted when using a keyboard that has built-in macro 1869 // shortcut keys (that emit Search+x) and some of them are not registered. 1870 if (mSearchKeyShortcutPending) { 1871 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 1872 if (kcm.isPrintingKey(keyCode)) { 1873 mConsumeSearchKeyUp = true; 1874 mSearchKeyShortcutPending = false; 1875 if (down && repeatCount == 0 && !keyguardOn) { 1876 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState); 1877 if (shortcutIntent != null) { 1878 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1879 try { 1880 mContext.startActivity(shortcutIntent); 1881 } catch (ActivityNotFoundException ex) { 1882 Slog.w(TAG, "Dropping shortcut key combination because " 1883 + "the activity to which it is registered was not found: " 1884 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex); 1885 } 1886 } else { 1887 Slog.i(TAG, "Dropping unregistered shortcut key combination: " 1888 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode)); 1889 } 1890 } 1891 return -1; 1892 } 1893 } 1894 1895 // Invoke shortcuts using Meta. 1896 if (down && repeatCount == 0 && !keyguardOn 1897 && (metaState & KeyEvent.META_META_ON) != 0) { 1898 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 1899 if (kcm.isPrintingKey(keyCode)) { 1900 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, 1901 metaState & ~(KeyEvent.META_META_ON 1902 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON)); 1903 if (shortcutIntent != null) { 1904 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1905 try { 1906 mContext.startActivity(shortcutIntent); 1907 } catch (ActivityNotFoundException ex) { 1908 Slog.w(TAG, "Dropping shortcut key combination because " 1909 + "the activity to which it is registered was not found: " 1910 + "META+" + KeyEvent.keyCodeToString(keyCode), ex); 1911 } 1912 return -1; 1913 } 1914 } 1915 } 1916 1917 // Handle application launch keys. 1918 if (down && repeatCount == 0 && !keyguardOn) { 1919 String category = sApplicationLaunchKeyCategories.get(keyCode); 1920 if (category != null) { 1921 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category); 1922 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1923 try { 1924 mContext.startActivity(intent); 1925 } catch (ActivityNotFoundException ex) { 1926 Slog.w(TAG, "Dropping application launch key because " 1927 + "the activity to which it is registered was not found: " 1928 + "keyCode=" + keyCode + ", category=" + category, ex); 1929 } 1930 return -1; 1931 } 1932 } 1933 1934 // Display task switcher for ALT-TAB or Meta-TAB. 1935 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) { 1936 if (mRecentAppsDialogHeldModifiers == 0 && !keyguardOn) { 1937 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK; 1938 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON) 1939 || KeyEvent.metaStateHasModifiers( 1940 shiftlessModifiers, KeyEvent.META_META_ON)) { 1941 mRecentAppsDialogHeldModifiers = shiftlessModifiers; 1942 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW); 1943 return -1; 1944 } 1945 } 1946 } else if (!down && mRecentAppsDialogHeldModifiers != 0 1947 && (metaState & mRecentAppsDialogHeldModifiers) == 0) { 1948 mRecentAppsDialogHeldModifiers = 0; 1949 showOrHideRecentAppsDialog(keyguardOn ? RECENT_APPS_BEHAVIOR_DISMISS : 1950 RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH); 1951 } 1952 1953 // Handle keyboard language switching. 1954 if (down && repeatCount == 0 1955 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 1956 || (keyCode == KeyEvent.KEYCODE_SPACE 1957 && (metaState & KeyEvent.META_CTRL_MASK) != 0))) { 1958 int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1; 1959 mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction); 1960 return -1; 1961 } 1962 if (mLanguageSwitchKeyPressed && !down 1963 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH 1964 || keyCode == KeyEvent.KEYCODE_SPACE)) { 1965 mLanguageSwitchKeyPressed = false; 1966 return -1; 1967 } 1968 1969 // Let the application handle the key. 1970 return 0; 1971 } 1972 1973 /** {@inheritDoc} */ 1974 @Override 1975 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) { 1976 // Note: This method is only called if the initial down was unhandled. 1977 if (DEBUG_INPUT) { 1978 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction() 1979 + ", flags=" + event.getFlags() 1980 + ", keyCode=" + event.getKeyCode() 1981 + ", scanCode=" + event.getScanCode() 1982 + ", metaState=" + event.getMetaState() 1983 + ", repeatCount=" + event.getRepeatCount() 1984 + ", policyFlags=" + policyFlags); 1985 } 1986 1987 KeyEvent fallbackEvent = null; 1988 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 1989 final KeyCharacterMap kcm = event.getKeyCharacterMap(); 1990 final int keyCode = event.getKeyCode(); 1991 final int metaState = event.getMetaState(); 1992 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN 1993 && event.getRepeatCount() == 0; 1994 1995 // Check for fallback actions specified by the key character map. 1996 final FallbackAction fallbackAction; 1997 if (initialDown) { 1998 fallbackAction = kcm.getFallbackAction(keyCode, metaState); 1999 } else { 2000 fallbackAction = mFallbackActions.get(keyCode); 2001 } 2002 2003 if (fallbackAction != null) { 2004 if (DEBUG_INPUT) { 2005 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode 2006 + " metaState=" + Integer.toHexString(fallbackAction.metaState)); 2007 } 2008 2009 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK; 2010 fallbackEvent = KeyEvent.obtain( 2011 event.getDownTime(), event.getEventTime(), 2012 event.getAction(), fallbackAction.keyCode, 2013 event.getRepeatCount(), fallbackAction.metaState, 2014 event.getDeviceId(), event.getScanCode(), 2015 flags, event.getSource(), null); 2016 2017 if (!interceptFallback(win, fallbackEvent, policyFlags)) { 2018 fallbackEvent.recycle(); 2019 fallbackEvent = null; 2020 } 2021 2022 if (initialDown) { 2023 mFallbackActions.put(keyCode, fallbackAction); 2024 } else if (event.getAction() == KeyEvent.ACTION_UP) { 2025 mFallbackActions.remove(keyCode); 2026 fallbackAction.recycle(); 2027 } 2028 } 2029 } 2030 2031 if (DEBUG_INPUT) { 2032 if (fallbackEvent == null) { 2033 Slog.d(TAG, "No fallback."); 2034 } else { 2035 Slog.d(TAG, "Performing fallback: " + fallbackEvent); 2036 } 2037 } 2038 return fallbackEvent; 2039 } 2040 2041 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) { 2042 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true); 2043 if ((actions & ACTION_PASS_TO_USER) != 0) { 2044 long delayMillis = interceptKeyBeforeDispatching( 2045 win, fallbackEvent, policyFlags); 2046 if (delayMillis == 0) { 2047 return true; 2048 } 2049 } 2050 return false; 2051 } 2052 2053 private void launchAssistLongPressAction() { 2054 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false); 2055 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 2056 2057 // launch the search activity 2058 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS); 2059 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 2060 try { 2061 // TODO: This only stops the factory-installed search manager. 2062 // Need to formalize an API to handle others 2063 SearchManager searchManager = getSearchManager(); 2064 if (searchManager != null) { 2065 searchManager.stopSearch(); 2066 } 2067 mContext.startActivityAsUser(intent, UserId.USER_CURRENT); 2068 } catch (ActivityNotFoundException e) { 2069 Slog.w(TAG, "No activity to handle assist long press action.", e); 2070 } 2071 } 2072 2073 private void launchAssistAction() { 2074 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST); 2075 Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE)) 2076 .getAssistIntent(mContext, UserId.USER_CURRENT); 2077 if (intent != null) { 2078 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 2079 | Intent.FLAG_ACTIVITY_SINGLE_TOP 2080 | Intent.FLAG_ACTIVITY_CLEAR_TOP); 2081 try { 2082 mContext.startActivityAsUser(intent, UserId.USER_CURRENT); 2083 } catch (ActivityNotFoundException e) { 2084 Slog.w(TAG, "No activity to handle assist action.", e); 2085 } 2086 } 2087 } 2088 2089 private SearchManager getSearchManager() { 2090 if (mSearchManager == null) { 2091 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE); 2092 } 2093 return mSearchManager; 2094 } 2095 2096 /** 2097 * A home key -> launch home action was detected. Take the appropriate action 2098 * given the situation with the keyguard. 2099 */ 2100 void launchHomeFromHotKey() { 2101 if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) { 2102 // don't launch home if keyguard showing 2103 } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) { 2104 // when in keyguard restricted mode, must first verify unlock 2105 // before launching home 2106 mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() { 2107 public void onKeyguardExitResult(boolean success) { 2108 if (success) { 2109 try { 2110 ActivityManagerNative.getDefault().stopAppSwitches(); 2111 } catch (RemoteException e) { 2112 } 2113 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 2114 startDockOrHome(); 2115 } 2116 } 2117 }); 2118 } else { 2119 // no keyguard stuff to worry about, just launch home! 2120 try { 2121 ActivityManagerNative.getDefault().stopAppSwitches(); 2122 } catch (RemoteException e) { 2123 } 2124 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY); 2125 startDockOrHome(); 2126 } 2127 } 2128 2129 /** 2130 * A delayed callback use to determine when it is okay to re-allow applications 2131 * to use certain system UI flags. This is used to prevent applications from 2132 * spamming system UI changes that prevent the navigation bar from being shown. 2133 */ 2134 final Runnable mAllowSystemUiDelay = new Runnable() { 2135 @Override public void run() { 2136 } 2137 }; 2138 2139 /** 2140 * Input handler used while nav bar is hidden. Captures any touch on the screen, 2141 * to determine when the nav bar should be shown and prevent applications from 2142 * receiving those touches. 2143 */ 2144 final class HideNavInputEventReceiver extends InputEventReceiver { 2145 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) { 2146 super(inputChannel, looper); 2147 } 2148 2149 @Override 2150 public void onInputEvent(InputEvent event) { 2151 boolean handled = false; 2152 try { 2153 if (event instanceof MotionEvent 2154 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { 2155 final MotionEvent motionEvent = (MotionEvent)event; 2156 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) { 2157 // When the user taps down, we re-show the nav bar. 2158 boolean changed = false; 2159 synchronized (mLock) { 2160 // Any user activity always causes us to show the 2161 // navigation controls, if they had been hidden. 2162 // We also clear the low profile and only content 2163 // flags so that tapping on the screen will atomically 2164 // restore all currently hidden screen decorations. 2165 int newVal = mResettingSystemUiFlags | 2166 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | 2167 View.SYSTEM_UI_FLAG_LOW_PROFILE | 2168 View.SYSTEM_UI_FLAG_FULLSCREEN; 2169 if (mResettingSystemUiFlags != newVal) { 2170 mResettingSystemUiFlags = newVal; 2171 changed = true; 2172 } 2173 // We don't allow the system's nav bar to be hidden 2174 // again for 1 second, to prevent applications from 2175 // spamming us and keeping it from being shown. 2176 newVal = mForceClearedSystemUiFlags | 2177 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 2178 if (mForceClearedSystemUiFlags != newVal) { 2179 mForceClearedSystemUiFlags = newVal; 2180 changed = true; 2181 mHandler.postDelayed(new Runnable() { 2182 @Override public void run() { 2183 synchronized (mLock) { 2184 // Clear flags. 2185 mForceClearedSystemUiFlags &= 2186 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; 2187 } 2188 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 2189 } 2190 }, 1000); 2191 } 2192 } 2193 if (changed) { 2194 mWindowManagerFuncs.reevaluateStatusBarVisibility(); 2195 } 2196 } 2197 } 2198 } finally { 2199 finishInputEvent(event, handled); 2200 } 2201 } 2202 } 2203 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory = 2204 new InputEventReceiver.Factory() { 2205 @Override 2206 public InputEventReceiver createInputEventReceiver( 2207 InputChannel inputChannel, Looper looper) { 2208 return new HideNavInputEventReceiver(inputChannel, looper); 2209 } 2210 }; 2211 2212 @Override 2213 public int adjustSystemUiVisibilityLw(int visibility) { 2214 // Reset any bits in mForceClearingStatusBarVisibility that 2215 // are now clear. 2216 mResettingSystemUiFlags &= visibility; 2217 // Clear any bits in the new visibility that are currently being 2218 // force cleared, before reporting it. 2219 return visibility & ~mResettingSystemUiFlags 2220 & ~mForceClearedSystemUiFlags; 2221 } 2222 2223 public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) { 2224 final int fl = attrs.flags; 2225 final int systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility); 2226 2227 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) 2228 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) { 2229 int availRight, availBottom; 2230 if (mCanHideNavigationBar && 2231 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) { 2232 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth; 2233 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight; 2234 } else { 2235 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth; 2236 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight; 2237 } 2238 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 2239 if ((fl & FLAG_FULLSCREEN) != 0) { 2240 contentInset.set(mStableFullscreenLeft, mStableFullscreenTop, 2241 availRight - mStableFullscreenRight, 2242 availBottom - mStableFullscreenBottom); 2243 } else { 2244 contentInset.set(mStableLeft, mStableTop, 2245 availRight - mStableRight, availBottom - mStableBottom); 2246 } 2247 } else if ((fl & FLAG_FULLSCREEN) != 0) { 2248 contentInset.setEmpty(); 2249 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN 2250 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) { 2251 contentInset.set(mCurLeft, mCurTop, 2252 availRight - mCurRight, availBottom - mCurBottom); 2253 } else { 2254 contentInset.set(mCurLeft, mCurTop, 2255 availRight - mCurRight, availBottom - mCurBottom); 2256 } 2257 return; 2258 } 2259 contentInset.setEmpty(); 2260 } 2261 2262 /** {@inheritDoc} */ 2263 public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation) { 2264 mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0; 2265 mUnrestrictedScreenWidth = displayWidth; 2266 mUnrestrictedScreenHeight = displayHeight; 2267 mRestrictedScreenLeft = mRestrictedScreenTop = 0; 2268 mRestrictedScreenWidth = displayWidth; 2269 mRestrictedScreenHeight = displayHeight; 2270 mDockLeft = mContentLeft = mStableLeft = mStableFullscreenLeft 2271 = mSystemLeft = mCurLeft = 0; 2272 mDockTop = mContentTop = mStableTop = mStableFullscreenTop 2273 = mSystemTop = mCurTop = 0; 2274 mDockRight = mContentRight = mStableRight = mStableFullscreenRight 2275 = mSystemRight = mCurRight = displayWidth; 2276 mDockBottom = mContentBottom = mStableBottom = mStableFullscreenBottom 2277 = mSystemBottom = mCurBottom = displayHeight; 2278 mDockLayer = 0x10000000; 2279 mStatusBarLayer = -1; 2280 2281 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight) 2282 final Rect pf = mTmpParentFrame; 2283 final Rect df = mTmpDisplayFrame; 2284 final Rect vf = mTmpVisibleFrame; 2285 pf.left = df.left = vf.left = mDockLeft; 2286 pf.top = df.top = vf.top = mDockTop; 2287 pf.right = df.right = vf.right = mDockRight; 2288 pf.bottom = df.bottom = vf.bottom = mDockBottom; 2289 2290 // For purposes of putting out fake window up to steal focus, we will 2291 // drive nav being hidden only by whether it is requested. 2292 boolean navVisible = (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0; 2293 2294 // When the navigation bar isn't visible, we put up a fake 2295 // input window to catch all touch events. This way we can 2296 // detect when the user presses anywhere to bring back the nav 2297 // bar and ensure the application doesn't see the event. 2298 if (navVisible) { 2299 if (mHideNavFakeWindow != null) { 2300 mHideNavFakeWindow.dismiss(); 2301 mHideNavFakeWindow = null; 2302 } 2303 } else if (mHideNavFakeWindow == null) { 2304 mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow( 2305 mHandler.getLooper(), mHideNavInputEventReceiverFactory, 2306 "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER, 2307 0, false, false, true); 2308 } 2309 2310 // For purposes of positioning and showing the nav bar, if we have 2311 // decided that it can't be hidden (because of the screen aspect ratio), 2312 // then take that into account. 2313 navVisible |= !mCanHideNavigationBar; 2314 2315 if (mNavigationBar != null) { 2316 // Force the navigation bar to its appropriate place and 2317 // size. We need to do this directly, instead of relying on 2318 // it to bubble up from the nav bar, because this needs to 2319 // change atomically with screen rotations. 2320 mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight); 2321 if (mNavigationBarOnBottom) { 2322 // It's a system nav bar or a portrait screen; nav bar goes on bottom. 2323 int top = displayHeight - mNavigationBarHeightForRotation[displayRotation]; 2324 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight); 2325 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top; 2326 if (navVisible) { 2327 mNavigationBar.showLw(true); 2328 mDockBottom = mTmpNavigationFrame.top; 2329 mRestrictedScreenHeight = mDockBottom - mDockTop; 2330 } else { 2331 // We currently want to hide the navigation UI. 2332 mNavigationBar.hideLw(true); 2333 } 2334 if (navVisible && !mNavigationBar.isAnimatingLw()) { 2335 // If the nav bar is currently requested to be visible, 2336 // and not in the process of animating on or off, then 2337 // we can tell the app that it is covered by it. 2338 mSystemBottom = mTmpNavigationFrame.top; 2339 } 2340 } else { 2341 // Landscape screen; nav bar goes to the right. 2342 int left = displayWidth - mNavigationBarWidthForRotation[displayRotation]; 2343 mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight); 2344 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left; 2345 if (navVisible) { 2346 mNavigationBar.showLw(true); 2347 mDockRight = mTmpNavigationFrame.left; 2348 mRestrictedScreenWidth = mDockRight - mDockLeft; 2349 } else { 2350 // We currently want to hide the navigation UI. 2351 mNavigationBar.hideLw(true); 2352 } 2353 if (navVisible && !mNavigationBar.isAnimatingLw()) { 2354 // If the nav bar is currently requested to be visible, 2355 // and not in the process of animating on or off, then 2356 // we can tell the app that it is covered by it. 2357 mSystemRight = mTmpNavigationFrame.left; 2358 } 2359 } 2360 // Make sure the content and current rectangles are updated to 2361 // account for the restrictions from the navigation bar. 2362 mContentTop = mCurTop = mDockTop; 2363 mContentBottom = mCurBottom = mDockBottom; 2364 mContentLeft = mCurLeft = mDockLeft; 2365 mContentRight = mCurRight = mDockRight; 2366 mStatusBarLayer = mNavigationBar.getSurfaceLayer(); 2367 // And compute the final frame. 2368 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame, 2369 mTmpNavigationFrame, mTmpNavigationFrame); 2370 if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame); 2371 } 2372 if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)", 2373 mDockLeft, mDockTop, mDockRight, mDockBottom)); 2374 2375 // decide where the status bar goes ahead of time 2376 if (mStatusBar != null) { 2377 // apply any navigation bar insets 2378 pf.left = df.left = mUnrestrictedScreenLeft; 2379 pf.top = df.top = mUnrestrictedScreenTop; 2380 pf.right = df.right = mUnrestrictedScreenWidth - mUnrestrictedScreenLeft; 2381 pf.bottom = df.bottom = mUnrestrictedScreenHeight - mUnrestrictedScreenTop; 2382 vf.left = mStableLeft; 2383 vf.top = mStableTop; 2384 vf.right = mStableRight; 2385 vf.bottom = mStableBottom; 2386 2387 mStatusBarLayer = mStatusBar.getSurfaceLayer(); 2388 2389 // Let the status bar determine its size. 2390 mStatusBar.computeFrameLw(pf, df, vf, vf); 2391 2392 // For layout, the status bar is always at the top with our fixed height. 2393 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight; 2394 2395 // If the status bar is hidden, we don't want to cause 2396 // windows behind it to scroll. 2397 if (mStatusBar.isVisibleLw()) { 2398 // Status bar may go away, so the screen area it occupies 2399 // is available to apps but just covering them when the 2400 // status bar is visible. 2401 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight; 2402 2403 mContentTop = mCurTop = mDockTop; 2404 mContentBottom = mCurBottom = mDockBottom; 2405 mContentLeft = mCurLeft = mDockLeft; 2406 mContentRight = mCurRight = mDockRight; 2407 2408 if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " + 2409 String.format( 2410 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]", 2411 mDockLeft, mDockTop, mDockRight, mDockBottom, 2412 mContentLeft, mContentTop, mContentRight, mContentBottom, 2413 mCurLeft, mCurTop, mCurRight, mCurBottom)); 2414 } 2415 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()) { 2416 // If the status bar is currently requested to be visible, 2417 // and not in the process of animating on or off, then 2418 // we can tell the app that it is covered by it. 2419 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight; 2420 } 2421 } 2422 } 2423 2424 /** {@inheritDoc} */ 2425 public int getSystemDecorRectLw(Rect systemRect) { 2426 systemRect.left = mSystemLeft; 2427 systemRect.top = mSystemTop; 2428 systemRect.right = mSystemRight; 2429 systemRect.bottom = mSystemBottom; 2430 if (mStatusBar != null) return mStatusBar.getSurfaceLayer(); 2431 if (mNavigationBar != null) return mNavigationBar.getSurfaceLayer(); 2432 return 0; 2433 } 2434 2435 void setAttachedWindowFrames(WindowState win, int fl, int adjust, 2436 WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) { 2437 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) { 2438 // Here's a special case: if this attached window is a panel that is 2439 // above the dock window, and the window it is attached to is below 2440 // the dock window, then the frames we computed for the window it is 2441 // attached to can not be used because the dock is effectively part 2442 // of the underlying window and the attached window is floating on top 2443 // of the whole thing. So, we ignore the attached window and explicitly 2444 // compute the frames that would be appropriate without the dock. 2445 df.left = cf.left = vf.left = mDockLeft; 2446 df.top = cf.top = vf.top = mDockTop; 2447 df.right = cf.right = vf.right = mDockRight; 2448 df.bottom = cf.bottom = vf.bottom = mDockBottom; 2449 } else { 2450 // The effective display frame of the attached window depends on 2451 // whether it is taking care of insetting its content. If not, 2452 // we need to use the parent's content frame so that the entire 2453 // window is positioned within that content. Otherwise we can use 2454 // the display frame and let the attached window take care of 2455 // positioning its content appropriately. 2456 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 2457 cf.set(attached.getDisplayFrameLw()); 2458 } else { 2459 // If the window is resizing, then we want to base the content 2460 // frame on our attached content frame to resize... however, 2461 // things can be tricky if the attached window is NOT in resize 2462 // mode, in which case its content frame will be larger. 2463 // Ungh. So to deal with that, make sure the content frame 2464 // we end up using is not covering the IM dock. 2465 cf.set(attached.getContentFrameLw()); 2466 if (attached.getSurfaceLayer() < mDockLayer) { 2467 if (cf.left < mContentLeft) cf.left = mContentLeft; 2468 if (cf.top < mContentTop) cf.top = mContentTop; 2469 if (cf.right > mContentRight) cf.right = mContentRight; 2470 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom; 2471 } 2472 } 2473 df.set(insetDecors ? attached.getDisplayFrameLw() : cf); 2474 vf.set(attached.getVisibleFrameLw()); 2475 } 2476 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached 2477 // window should be positioned relative to its parent or the entire 2478 // screen. 2479 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0 2480 ? attached.getFrameLw() : df); 2481 } 2482 2483 private void applyStableConstraints(int sysui, int fl, Rect r) { 2484 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { 2485 // If app is requesting a stable layout, don't let the 2486 // content insets go below the stable values. 2487 if ((fl & FLAG_FULLSCREEN) != 0) { 2488 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft; 2489 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop; 2490 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight; 2491 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom; 2492 } else { 2493 if (r.left < mStableLeft) r.left = mStableLeft; 2494 if (r.top < mStableTop) r.top = mStableTop; 2495 if (r.right > mStableRight) r.right = mStableRight; 2496 if (r.bottom > mStableBottom) r.bottom = mStableBottom; 2497 } 2498 } 2499 } 2500 2501 /** {@inheritDoc} */ 2502 public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs, 2503 WindowState attached) { 2504 // we've already done the status bar 2505 if (win == mStatusBar || win == mNavigationBar) { 2506 return; 2507 } 2508 final boolean needsToOffsetInputMethodTarget = 2509 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null); 2510 if (needsToOffsetInputMethodTarget) { 2511 if (DEBUG_LAYOUT) { 2512 Slog.i(TAG, "Offset ime target window by the last ime window state"); 2513 } 2514 offsetInputMethodWindowLw(mLastInputMethodWindow); 2515 } 2516 2517 final int fl = attrs.flags; 2518 final int sim = attrs.softInputMode; 2519 final int sysUiFl = win.getSystemUiVisibility(); 2520 2521 final Rect pf = mTmpParentFrame; 2522 final Rect df = mTmpDisplayFrame; 2523 final Rect cf = mTmpContentFrame; 2524 final Rect vf = mTmpVisibleFrame; 2525 2526 final boolean hasNavBar = (mHasNavigationBar 2527 && mNavigationBar != null && mNavigationBar.isVisibleLw()); 2528 2529 if (attrs.type == TYPE_INPUT_METHOD) { 2530 pf.left = df.left = cf.left = vf.left = mDockLeft; 2531 pf.top = df.top = cf.top = vf.top = mDockTop; 2532 pf.right = df.right = cf.right = vf.right = mDockRight; 2533 pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom; 2534 // IM dock windows always go to the bottom of the screen. 2535 attrs.gravity = Gravity.BOTTOM; 2536 mDockLayer = win.getSurfaceLayer(); 2537 } else { 2538 final int adjust = sim & SOFT_INPUT_MASK_ADJUST; 2539 2540 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR)) 2541 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR) 2542 && (sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) { 2543 if (DEBUG_LAYOUT) 2544 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() 2545 + "): IN_SCREEN, INSET_DECOR, !FULLSCREEN"); 2546 // This is the case for a normal activity window: we want it 2547 // to cover all of the screen space, and it can take care of 2548 // moving its contents to account for screen decorations that 2549 // intrude into that space. 2550 if (attached != null) { 2551 // If this window is attached to another, our display 2552 // frame is the same as the one we are attached to. 2553 setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf); 2554 } else { 2555 if (attrs.type == TYPE_STATUS_BAR_PANEL 2556 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { 2557 // Status bar panels are the only windows who can go on top of 2558 // the status bar. They are protected by the STATUS_BAR_SERVICE 2559 // permission, so they have the same privileges as the status 2560 // bar itself. 2561 // 2562 // However, they should still dodge the navigation bar if it exists. 2563 2564 pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft; 2565 pf.top = df.top = mUnrestrictedScreenTop; 2566 pf.right = df.right = hasNavBar 2567 ? mRestrictedScreenLeft+mRestrictedScreenWidth 2568 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2569 pf.bottom = df.bottom = hasNavBar 2570 ? mRestrictedScreenTop+mRestrictedScreenHeight 2571 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2572 2573 if (DEBUG_LAYOUT) { 2574 Log.v(TAG, String.format( 2575 "Laying out status bar window: (%d,%d - %d,%d)", 2576 pf.left, pf.top, pf.right, pf.bottom)); 2577 } 2578 } else if (mCanHideNavigationBar 2579 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 2580 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 2581 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 2582 // Asking for layout as if the nav bar is hidden, lets the 2583 // application extend into the unrestricted screen area. We 2584 // only do this for application windows to ensure no window that 2585 // can be above the nav bar can do this. 2586 pf.left = df.left = mUnrestrictedScreenLeft; 2587 pf.top = df.top = mUnrestrictedScreenTop; 2588 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2589 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2590 } else { 2591 pf.left = df.left = mRestrictedScreenLeft; 2592 pf.top = df.top = mRestrictedScreenTop; 2593 pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth; 2594 pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight; 2595 } 2596 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 2597 cf.left = mDockLeft; 2598 cf.top = mDockTop; 2599 cf.right = mDockRight; 2600 cf.bottom = mDockBottom; 2601 } else { 2602 cf.left = mContentLeft; 2603 cf.top = mContentTop; 2604 cf.right = mContentRight; 2605 cf.bottom = mContentBottom; 2606 } 2607 applyStableConstraints(sysUiFl, fl, cf); 2608 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 2609 vf.left = mCurLeft; 2610 vf.top = mCurTop; 2611 vf.right = mCurRight; 2612 vf.bottom = mCurBottom; 2613 } else { 2614 vf.set(cf); 2615 } 2616 } 2617 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl 2618 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 2619 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) { 2620 if (DEBUG_LAYOUT) 2621 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN"); 2622 // A window that has requested to fill the entire screen just 2623 // gets everything, period. 2624 if (attrs.type == TYPE_STATUS_BAR_PANEL 2625 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) { 2626 pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft; 2627 pf.top = df.top = cf.top = mUnrestrictedScreenTop; 2628 pf.right = df.right = cf.right = hasNavBar 2629 ? mRestrictedScreenLeft+mRestrictedScreenWidth 2630 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2631 pf.bottom = df.bottom = cf.bottom = hasNavBar 2632 ? mRestrictedScreenTop+mRestrictedScreenHeight 2633 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2634 if (DEBUG_LAYOUT) { 2635 Log.v(TAG, String.format( 2636 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)", 2637 pf.left, pf.top, pf.right, pf.bottom)); 2638 } 2639 } else if (attrs.type == TYPE_NAVIGATION_BAR 2640 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) { 2641 // The navigation bar has Real Ultimate Power. 2642 pf.left = df.left = mUnrestrictedScreenLeft; 2643 pf.top = df.top = mUnrestrictedScreenTop; 2644 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2645 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2646 if (DEBUG_LAYOUT) { 2647 Log.v(TAG, String.format( 2648 "Laying out navigation bar window: (%d,%d - %d,%d)", 2649 pf.left, pf.top, pf.right, pf.bottom)); 2650 } 2651 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY 2652 || attrs.type == TYPE_BOOT_PROGRESS) 2653 && ((fl & FLAG_FULLSCREEN) != 0)) { 2654 // Fullscreen secure system overlays get what they ask for. 2655 pf.left = df.left = mUnrestrictedScreenLeft; 2656 pf.top = df.top = mUnrestrictedScreenTop; 2657 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2658 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2659 } else if (attrs.type == TYPE_BOOT_PROGRESS 2660 || attrs.type == TYPE_UNIVERSE_BACKGROUND) { 2661 // Boot progress screen always covers entire display. 2662 pf.left = df.left = cf.left = mUnrestrictedScreenLeft; 2663 pf.top = df.top = cf.top = mUnrestrictedScreenTop; 2664 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2665 pf.bottom = df.bottom = cf.bottom 2666 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2667 } else if (mCanHideNavigationBar 2668 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 2669 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW 2670 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { 2671 // Asking for layout as if the nav bar is hidden, lets the 2672 // application extend into the unrestricted screen area. We 2673 // only do this for application windows to ensure no window that 2674 // can be above the nav bar can do this. 2675 // XXX This assumes that an app asking for this will also 2676 // ask for layout in only content. We can't currently figure out 2677 // what the screen would be if only laying out to hide the nav bar. 2678 pf.left = df.left = cf.left = mUnrestrictedScreenLeft; 2679 pf.top = df.top = cf.top = mUnrestrictedScreenTop; 2680 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth; 2681 pf.bottom = df.bottom = cf.bottom 2682 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight; 2683 } else { 2684 pf.left = df.left = cf.left = mRestrictedScreenLeft; 2685 pf.top = df.top = cf.top = mRestrictedScreenTop; 2686 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth; 2687 pf.bottom = df.bottom = cf.bottom 2688 = mRestrictedScreenTop+mRestrictedScreenHeight; 2689 } 2690 applyStableConstraints(sysUiFl, fl, cf); 2691 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 2692 vf.left = mCurLeft; 2693 vf.top = mCurTop; 2694 vf.right = mCurRight; 2695 vf.bottom = mCurBottom; 2696 } else { 2697 vf.set(cf); 2698 } 2699 } else if (attached != null) { 2700 if (DEBUG_LAYOUT) 2701 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): attached to " + attached); 2702 // A child window should be placed inside of the same visible 2703 // frame that its parent had. 2704 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf); 2705 } else { 2706 if (DEBUG_LAYOUT) 2707 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window"); 2708 // Otherwise, a normal window must be placed inside the content 2709 // of all screen decorations. 2710 if (attrs.type == TYPE_STATUS_BAR_PANEL) { 2711 // Status bar panels are the only windows who can go on top of 2712 // the status bar. They are protected by the STATUS_BAR_SERVICE 2713 // permission, so they have the same privileges as the status 2714 // bar itself. 2715 pf.left = df.left = cf.left = mRestrictedScreenLeft; 2716 pf.top = df.top = cf.top = mRestrictedScreenTop; 2717 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth; 2718 pf.bottom = df.bottom = cf.bottom 2719 = mRestrictedScreenTop+mRestrictedScreenHeight; 2720 } else { 2721 pf.left = mContentLeft; 2722 pf.top = mContentTop; 2723 pf.right = mContentRight; 2724 pf.bottom = mContentBottom; 2725 if (adjust != SOFT_INPUT_ADJUST_RESIZE) { 2726 df.left = cf.left = mDockLeft; 2727 df.top = cf.top = mDockTop; 2728 df.right = cf.right = mDockRight; 2729 df.bottom = cf.bottom = mDockBottom; 2730 } else { 2731 df.left = cf.left = mContentLeft; 2732 df.top = cf.top = mContentTop; 2733 df.right = cf.right = mContentRight; 2734 df.bottom = cf.bottom = mContentBottom; 2735 } 2736 if (adjust != SOFT_INPUT_ADJUST_NOTHING) { 2737 vf.left = mCurLeft; 2738 vf.top = mCurTop; 2739 vf.right = mCurRight; 2740 vf.bottom = mCurBottom; 2741 } else { 2742 vf.set(cf); 2743 } 2744 } 2745 } 2746 } 2747 2748 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) { 2749 df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000; 2750 df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000; 2751 } 2752 2753 if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle() 2754 + ": sim=#" + Integer.toHexString(sim) 2755 + " attach=" + attached + " type=" + attrs.type 2756 + String.format(" flags=0x%08x", fl) 2757 + " pf=" + pf.toShortString() + " df=" + df.toShortString() 2758 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString()); 2759 2760 win.computeFrameLw(pf, df, cf, vf); 2761 2762 // Dock windows carve out the bottom of the screen, so normal windows 2763 // can't appear underneath them. 2764 if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) { 2765 setLastInputMethodWindowLw(null, null); 2766 offsetInputMethodWindowLw(win); 2767 } 2768 } 2769 2770 private void offsetInputMethodWindowLw(WindowState win) { 2771 int top = win.getContentFrameLw().top; 2772 top += win.getGivenContentInsetsLw().top; 2773 if (mContentBottom > top) { 2774 mContentBottom = top; 2775 } 2776 top = win.getVisibleFrameLw().top; 2777 top += win.getGivenVisibleInsetsLw().top; 2778 if (mCurBottom > top) { 2779 mCurBottom = top; 2780 } 2781 if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom=" 2782 + mDockBottom + " mContentBottom=" 2783 + mContentBottom + " mCurBottom=" + mCurBottom); 2784 } 2785 2786 /** {@inheritDoc} */ 2787 @Override 2788 public void finishLayoutLw() { 2789 return; 2790 } 2791 2792 /** {@inheritDoc} */ 2793 public void beginAnimationLw(int displayWidth, int displayHeight) { 2794 mTopFullscreenOpaqueWindowState = null; 2795 mForceStatusBar = false; 2796 2797 mHideLockScreen = false; 2798 mAllowLockscreenWhenOn = false; 2799 mDismissKeyguard = false; 2800 } 2801 2802 /** {@inheritDoc} */ 2803 public void animatingWindowLw(WindowState win, 2804 WindowManager.LayoutParams attrs) { 2805 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw=" 2806 + win.isVisibleOrBehindKeyguardLw()); 2807 if (mTopFullscreenOpaqueWindowState == null && 2808 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) { 2809 if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) { 2810 mForceStatusBar = true; 2811 } 2812 if (((attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type <= LAST_APPLICATION_WINDOW) 2813 || attrs.type == TYPE_DREAM) 2814 && attrs.x == 0 && attrs.y == 0 2815 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT 2816 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) { 2817 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win); 2818 mTopFullscreenOpaqueWindowState = win; 2819 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) { 2820 if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win); 2821 mHideLockScreen = true; 2822 } 2823 if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) { 2824 if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win); 2825 mDismissKeyguard = true; 2826 } 2827 if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) { 2828 mAllowLockscreenWhenOn = true; 2829 } 2830 } 2831 } 2832 } 2833 2834 /** {@inheritDoc} */ 2835 public int finishAnimationLw() { 2836 int changes = 0; 2837 boolean topIsFullscreen = false; 2838 2839 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null) 2840 ? mTopFullscreenOpaqueWindowState.getAttrs() 2841 : null; 2842 2843 if (mStatusBar != null) { 2844 if (DEBUG_LAYOUT) Log.i(TAG, "force=" + mForceStatusBar 2845 + " top=" + mTopFullscreenOpaqueWindowState); 2846 if (mForceStatusBar) { 2847 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: forced"); 2848 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; 2849 } else if (mTopFullscreenOpaqueWindowState != null) { 2850 if (localLOGV) { 2851 Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw() 2852 + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw()); 2853 Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs() 2854 + " lp.flags=0x" + Integer.toHexString(lp.flags)); 2855 } 2856 topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0 2857 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0; 2858 // The subtle difference between the window for mTopFullscreenOpaqueWindowState 2859 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window 2860 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the 2861 // case though. 2862 if (topIsFullscreen) { 2863 if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar"); 2864 if (mStatusBar.hideLw(true)) { 2865 changes |= FINISH_LAYOUT_REDO_LAYOUT; 2866 2867 mHandler.post(new Runnable() { public void run() { 2868 try { 2869 IStatusBarService statusbar = getStatusBarService(); 2870 if (statusbar != null) { 2871 statusbar.collapse(); 2872 } 2873 } catch (RemoteException ex) { 2874 // re-acquire status bar service next time it is needed. 2875 mStatusBarService = null; 2876 } 2877 }}); 2878 } else if (DEBUG_LAYOUT) { 2879 Log.v(TAG, "Preventing status bar from hiding by policy"); 2880 } 2881 } else { 2882 if (DEBUG_LAYOUT) Log.v(TAG, "** SHOWING status bar: top is not fullscreen"); 2883 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT; 2884 } 2885 } 2886 } 2887 2888 mTopIsFullscreen = topIsFullscreen; 2889 2890 // Hide the key guard if a visible window explicitly specifies that it wants to be displayed 2891 // when the screen is locked 2892 if (mKeyguard != null) { 2893 if (localLOGV) Log.v(TAG, "finishAnimationLw::mHideKeyguard="+mHideLockScreen); 2894 if (mDismissKeyguard && !mKeyguardMediator.isSecure()) { 2895 if (mKeyguard.hideLw(true)) { 2896 changes |= FINISH_LAYOUT_REDO_LAYOUT 2897 | FINISH_LAYOUT_REDO_CONFIG 2898 | FINISH_LAYOUT_REDO_WALLPAPER; 2899 } 2900 if (mKeyguardMediator.isShowing()) { 2901 mHandler.post(new Runnable() { 2902 public void run() { 2903 mKeyguardMediator.keyguardDone(false, false); 2904 } 2905 }); 2906 } 2907 } else if (mHideLockScreen) { 2908 if (mKeyguard.hideLw(true)) { 2909 changes |= FINISH_LAYOUT_REDO_LAYOUT 2910 | FINISH_LAYOUT_REDO_CONFIG 2911 | FINISH_LAYOUT_REDO_WALLPAPER; 2912 } 2913 mKeyguardMediator.setHidden(true); 2914 } else { 2915 if (mKeyguard.showLw(true)) { 2916 changes |= FINISH_LAYOUT_REDO_LAYOUT 2917 | FINISH_LAYOUT_REDO_CONFIG 2918 | FINISH_LAYOUT_REDO_WALLPAPER; 2919 } 2920 mKeyguardMediator.setHidden(false); 2921 } 2922 } 2923 2924 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 2925 // If the navigation bar has been hidden or shown, we need to do another 2926 // layout pass to update that window. 2927 changes |= FINISH_LAYOUT_REDO_LAYOUT; 2928 } 2929 2930 // update since mAllowLockscreenWhenOn might have changed 2931 updateLockScreenTimeout(); 2932 return changes; 2933 } 2934 2935 public boolean allowAppAnimationsLw() { 2936 if (mKeyguard != null && mKeyguard.isVisibleLw() && !mKeyguard.isAnimatingLw()) { 2937 // If keyguard is currently visible, no reason to animate 2938 // behind it. 2939 return false; 2940 } 2941 return true; 2942 } 2943 2944 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) { 2945 mFocusedWindow = newFocus; 2946 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) { 2947 // If the navigation bar has been hidden or shown, we need to do another 2948 // layout pass to update that window. 2949 return FINISH_LAYOUT_REDO_LAYOUT; 2950 } 2951 return 0; 2952 } 2953 2954 /** {@inheritDoc} */ 2955 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) { 2956 // do nothing if headless 2957 if (mHeadless) return; 2958 2959 // lid changed state 2960 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED; 2961 if (newLidState == mLidState) { 2962 return; 2963 } 2964 2965 mLidState = newLidState; 2966 applyLidSwitchState(); 2967 updateRotation(true); 2968 2969 if (lidOpen) { 2970 if (keyguardIsShowingTq()) { 2971 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq( 2972 KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED); 2973 } else { 2974 mPowerManager.wakeUp(SystemClock.uptimeMillis()); 2975 } 2976 } else if (!mLidControlsSleep) { 2977 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 2978 } 2979 } 2980 2981 void setHdmiPlugged(boolean plugged) { 2982 if (mHdmiPlugged != plugged) { 2983 mHdmiPlugged = plugged; 2984 updateRotation(true, true); 2985 Intent intent = new Intent(ACTION_HDMI_PLUGGED); 2986 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 2987 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged); 2988 mContext.sendStickyBroadcast(intent); 2989 } 2990 } 2991 2992 void initializeHdmiState() { 2993 boolean plugged = false; 2994 // watch for HDMI plug messages if the hdmi switch exists 2995 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) { 2996 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi"); 2997 2998 final String filename = "/sys/class/switch/hdmi/state"; 2999 FileReader reader = null; 3000 try { 3001 reader = new FileReader(filename); 3002 char[] buf = new char[15]; 3003 int n = reader.read(buf); 3004 if (n > 1) { 3005 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1)); 3006 } 3007 } catch (IOException ex) { 3008 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 3009 } catch (NumberFormatException ex) { 3010 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex); 3011 } finally { 3012 if (reader != null) { 3013 try { 3014 reader.close(); 3015 } catch (IOException ex) { 3016 } 3017 } 3018 } 3019 } 3020 // This dance forces the code in setHdmiPlugged to run. 3021 // Always do this so the sticky intent is stuck (to false) if there is no hdmi. 3022 mHdmiPlugged = !plugged; 3023 setHdmiPlugged(!mHdmiPlugged); 3024 } 3025 3026 /** 3027 * @return Whether music is being played right now. 3028 */ 3029 boolean isMusicActive() { 3030 final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); 3031 if (am == null) { 3032 Log.w(TAG, "isMusicActive: couldn't get AudioManager reference"); 3033 return false; 3034 } 3035 return am.isMusicActive(); 3036 } 3037 3038 /** 3039 * Tell the audio service to adjust the volume appropriate to the event. 3040 * @param keycode 3041 */ 3042 void handleVolumeKey(int stream, int keycode) { 3043 IAudioService audioService = getAudioService(); 3044 if (audioService == null) { 3045 return; 3046 } 3047 try { 3048 // since audio is playing, we shouldn't have to hold a wake lock 3049 // during the call, but we do it as a precaution for the rare possibility 3050 // that the music stops right before we call this 3051 // TODO: Actually handle MUTE. 3052 mBroadcastWakeLock.acquire(); 3053 audioService.adjustStreamVolume(stream, 3054 keycode == KeyEvent.KEYCODE_VOLUME_UP 3055 ? AudioManager.ADJUST_RAISE 3056 : AudioManager.ADJUST_LOWER, 3057 0); 3058 } catch (RemoteException e) { 3059 Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e); 3060 } finally { 3061 mBroadcastWakeLock.release(); 3062 } 3063 } 3064 3065 final Object mScreenshotLock = new Object(); 3066 ServiceConnection mScreenshotConnection = null; 3067 3068 final Runnable mScreenshotTimeout = new Runnable() { 3069 @Override public void run() { 3070 synchronized (mScreenshotLock) { 3071 if (mScreenshotConnection != null) { 3072 mContext.unbindService(mScreenshotConnection); 3073 mScreenshotConnection = null; 3074 } 3075 } 3076 } 3077 }; 3078 3079 // Assume this is called from the Handler thread. 3080 private void takeScreenshot() { 3081 synchronized (mScreenshotLock) { 3082 if (mScreenshotConnection != null) { 3083 return; 3084 } 3085 ComponentName cn = new ComponentName("com.android.systemui", 3086 "com.android.systemui.screenshot.TakeScreenshotService"); 3087 Intent intent = new Intent(); 3088 intent.setComponent(cn); 3089 ServiceConnection conn = new ServiceConnection() { 3090 @Override 3091 public void onServiceConnected(ComponentName name, IBinder service) { 3092 synchronized (mScreenshotLock) { 3093 if (mScreenshotConnection != this) { 3094 return; 3095 } 3096 Messenger messenger = new Messenger(service); 3097 Message msg = Message.obtain(null, 1); 3098 final ServiceConnection myConn = this; 3099 Handler h = new Handler(mHandler.getLooper()) { 3100 @Override 3101 public void handleMessage(Message msg) { 3102 synchronized (mScreenshotLock) { 3103 if (mScreenshotConnection == myConn) { 3104 mContext.unbindService(mScreenshotConnection); 3105 mScreenshotConnection = null; 3106 mHandler.removeCallbacks(mScreenshotTimeout); 3107 } 3108 } 3109 } 3110 }; 3111 msg.replyTo = new Messenger(h); 3112 msg.arg1 = msg.arg2 = 0; 3113 if (mStatusBar != null && mStatusBar.isVisibleLw()) 3114 msg.arg1 = 1; 3115 if (mNavigationBar != null && mNavigationBar.isVisibleLw()) 3116 msg.arg2 = 1; 3117 try { 3118 messenger.send(msg); 3119 } catch (RemoteException e) { 3120 } 3121 } 3122 } 3123 @Override 3124 public void onServiceDisconnected(ComponentName name) {} 3125 }; 3126 if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) { 3127 mScreenshotConnection = conn; 3128 mHandler.postDelayed(mScreenshotTimeout, 10000); 3129 } 3130 } 3131 } 3132 3133 /** {@inheritDoc} */ 3134 @Override 3135 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) { 3136 if (!mSystemBooted) { 3137 // If we have not yet booted, don't let key events do anything. 3138 return 0; 3139 } 3140 3141 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN; 3142 final boolean canceled = event.isCanceled(); 3143 final int keyCode = event.getKeyCode(); 3144 3145 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0; 3146 3147 // If screen is off then we treat the case where the keyguard is open but hidden 3148 // the same as if it were open and in front. 3149 // This will prevent any keys other than the power button from waking the screen 3150 // when the keyguard is hidden by another activity. 3151 final boolean keyguardActive = (mKeyguardMediator == null ? false : 3152 (isScreenOn ? 3153 mKeyguardMediator.isShowingAndNotHidden() : 3154 mKeyguardMediator.isShowing())); 3155 3156 if (keyCode == KeyEvent.KEYCODE_POWER) { 3157 policyFlags |= WindowManagerPolicy.FLAG_WAKE; 3158 } 3159 final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE 3160 | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; 3161 3162 if (DEBUG_INPUT) { 3163 Log.d(TAG, "interceptKeyTq keycode=" + keyCode 3164 + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive 3165 + " policyFlags=" + Integer.toHexString(policyFlags) 3166 + " isWakeKey=" + isWakeKey); 3167 } 3168 3169 if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0 3170 && event.getRepeatCount() == 0) { 3171 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false); 3172 } 3173 3174 // Basic policy based on screen state and keyguard. 3175 // FIXME: This policy isn't quite correct. We shouldn't care whether the screen 3176 // is on or off, really. We should care about whether the device is in an 3177 // interactive state or is in suspend pretending to be "off". 3178 // The primary screen might be turned off due to proximity sensor or 3179 // because we are presenting media on an auxiliary screen or remotely controlling 3180 // the device some other way (which is why we have an exemption here for injected 3181 // events). 3182 int result; 3183 if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) { 3184 // When the screen is on or if the key is injected pass the key to the application. 3185 result = ACTION_PASS_TO_USER; 3186 } else { 3187 // When the screen is off and the key is not injected, determine whether 3188 // to wake the device but don't pass the key to the application. 3189 result = 0; 3190 if (down && isWakeKey) { 3191 if (keyguardActive) { 3192 // If the keyguard is showing, let it decide what to do with the wake key. 3193 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode, 3194 mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED); 3195 } else { 3196 // Otherwise, wake the device ourselves. 3197 result |= ACTION_WAKE_UP; 3198 } 3199 } 3200 } 3201 3202 // Handle special keys. 3203 switch (keyCode) { 3204 case KeyEvent.KEYCODE_VOLUME_DOWN: 3205 case KeyEvent.KEYCODE_VOLUME_UP: 3206 case KeyEvent.KEYCODE_VOLUME_MUTE: { 3207 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { 3208 if (down) { 3209 if (isScreenOn && !mVolumeDownKeyTriggered 3210 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3211 mVolumeDownKeyTriggered = true; 3212 mVolumeDownKeyTime = event.getDownTime(); 3213 mVolumeDownKeyConsumedByScreenshotChord = false; 3214 cancelPendingPowerKeyAction(); 3215 interceptScreenshotChord(); 3216 } 3217 } else { 3218 mVolumeDownKeyTriggered = false; 3219 cancelPendingScreenshotChordAction(); 3220 } 3221 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { 3222 if (down) { 3223 if (isScreenOn && !mVolumeUpKeyTriggered 3224 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3225 mVolumeUpKeyTriggered = true; 3226 cancelPendingPowerKeyAction(); 3227 cancelPendingScreenshotChordAction(); 3228 } 3229 } else { 3230 mVolumeUpKeyTriggered = false; 3231 cancelPendingScreenshotChordAction(); 3232 } 3233 } 3234 if (down) { 3235 ITelephony telephonyService = getTelephonyService(); 3236 if (telephonyService != null) { 3237 try { 3238 if (telephonyService.isRinging()) { 3239 // If an incoming call is ringing, either VOLUME key means 3240 // "silence ringer". We handle these keys here, rather than 3241 // in the InCallScreen, to make sure we'll respond to them 3242 // even if the InCallScreen hasn't come to the foreground yet. 3243 // Look for the DOWN event here, to agree with the "fallback" 3244 // behavior in the InCallScreen. 3245 Log.i(TAG, "interceptKeyBeforeQueueing:" 3246 + " VOLUME key-down while ringing: Silence ringer!"); 3247 3248 // Silence the ringer. (It's safe to call this 3249 // even if the ringer has already been silenced.) 3250 telephonyService.silenceRinger(); 3251 3252 // And *don't* pass this key thru to the current activity 3253 // (which is probably the InCallScreen.) 3254 result &= ~ACTION_PASS_TO_USER; 3255 break; 3256 } 3257 if (telephonyService.isOffhook() 3258 && (result & ACTION_PASS_TO_USER) == 0) { 3259 // If we are in call but we decided not to pass the key to 3260 // the application, handle the volume change here. 3261 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode); 3262 break; 3263 } 3264 } catch (RemoteException ex) { 3265 Log.w(TAG, "ITelephony threw RemoteException", ex); 3266 } 3267 } 3268 3269 if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) { 3270 // If music is playing but we decided not to pass the key to the 3271 // application, handle the volume change here. 3272 handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode); 3273 break; 3274 } 3275 } 3276 break; 3277 } 3278 3279 case KeyEvent.KEYCODE_ENDCALL: { 3280 result &= ~ACTION_PASS_TO_USER; 3281 if (down) { 3282 ITelephony telephonyService = getTelephonyService(); 3283 boolean hungUp = false; 3284 if (telephonyService != null) { 3285 try { 3286 hungUp = telephonyService.endCall(); 3287 } catch (RemoteException ex) { 3288 Log.w(TAG, "ITelephony threw RemoteException", ex); 3289 } 3290 } 3291 interceptPowerKeyDown(!isScreenOn || hungUp); 3292 } else { 3293 if (interceptPowerKeyUp(canceled)) { 3294 if ((mEndcallBehavior 3295 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) { 3296 if (goHome()) { 3297 break; 3298 } 3299 } 3300 if ((mEndcallBehavior 3301 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) { 3302 result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP; 3303 } 3304 } 3305 } 3306 break; 3307 } 3308 3309 case KeyEvent.KEYCODE_POWER: { 3310 result &= ~ACTION_PASS_TO_USER; 3311 if (down) { 3312 if (isScreenOn && !mPowerKeyTriggered 3313 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { 3314 mPowerKeyTriggered = true; 3315 mPowerKeyTime = event.getDownTime(); 3316 interceptScreenshotChord(); 3317 } 3318 3319 ITelephony telephonyService = getTelephonyService(); 3320 boolean hungUp = false; 3321 if (telephonyService != null) { 3322 try { 3323 if (telephonyService.isRinging()) { 3324 // Pressing Power while there's a ringing incoming 3325 // call should silence the ringer. 3326 telephonyService.silenceRinger(); 3327 } else if ((mIncallPowerBehavior 3328 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0 3329 && telephonyService.isOffhook()) { 3330 // Otherwise, if "Power button ends call" is enabled, 3331 // the Power button will hang up any current active call. 3332 hungUp = telephonyService.endCall(); 3333 } 3334 } catch (RemoteException ex) { 3335 Log.w(TAG, "ITelephony threw RemoteException", ex); 3336 } 3337 } 3338 interceptPowerKeyDown(!isScreenOn || hungUp 3339 || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered); 3340 } else { 3341 mPowerKeyTriggered = false; 3342 cancelPendingScreenshotChordAction(); 3343 if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) { 3344 result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP; 3345 } 3346 mPendingPowerKeyUpCanceled = false; 3347 } 3348 break; 3349 } 3350 3351 case KeyEvent.KEYCODE_MEDIA_PLAY: 3352 case KeyEvent.KEYCODE_MEDIA_PAUSE: 3353 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: 3354 if (down) { 3355 ITelephony telephonyService = getTelephonyService(); 3356 if (telephonyService != null) { 3357 try { 3358 if (!telephonyService.isIdle()) { 3359 // Suppress PLAY/PAUSE toggle when phone is ringing or in-call 3360 // to avoid music playback. 3361 break; 3362 } 3363 } catch (RemoteException ex) { 3364 Log.w(TAG, "ITelephony threw RemoteException", ex); 3365 } 3366 } 3367 } 3368 case KeyEvent.KEYCODE_HEADSETHOOK: 3369 case KeyEvent.KEYCODE_MUTE: 3370 case KeyEvent.KEYCODE_MEDIA_STOP: 3371 case KeyEvent.KEYCODE_MEDIA_NEXT: 3372 case KeyEvent.KEYCODE_MEDIA_PREVIOUS: 3373 case KeyEvent.KEYCODE_MEDIA_REWIND: 3374 case KeyEvent.KEYCODE_MEDIA_RECORD: 3375 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: { 3376 if ((result & ACTION_PASS_TO_USER) == 0) { 3377 // Only do this if we would otherwise not pass it to the user. In that 3378 // case, the PhoneWindow class will do the same thing, except it will 3379 // only do it if the showing app doesn't process the key on its own. 3380 // Note that we need to make a copy of the key event here because the 3381 // original key event will be recycled when we return. 3382 mBroadcastWakeLock.acquire(); 3383 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK, 3384 new KeyEvent(event)); 3385 msg.setAsynchronous(true); 3386 msg.sendToTarget(); 3387 } 3388 break; 3389 } 3390 3391 case KeyEvent.KEYCODE_CALL: { 3392 if (down) { 3393 ITelephony telephonyService = getTelephonyService(); 3394 if (telephonyService != null) { 3395 try { 3396 if (telephonyService.isRinging()) { 3397 Log.i(TAG, "interceptKeyBeforeQueueing:" 3398 + " CALL key-down while ringing: Answer the call!"); 3399 telephonyService.answerRingingCall(); 3400 3401 // And *don't* pass this key thru to the current activity 3402 // (which is presumably the InCallScreen.) 3403 result &= ~ACTION_PASS_TO_USER; 3404 } 3405 } catch (RemoteException ex) { 3406 Log.w(TAG, "ITelephony threw RemoteException", ex); 3407 } 3408 } 3409 } 3410 break; 3411 } 3412 } 3413 return result; 3414 } 3415 3416 /** {@inheritDoc} */ 3417 @Override 3418 public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) { 3419 int result = 0; 3420 3421 final boolean isWakeMotion = (policyFlags 3422 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0; 3423 if (isWakeMotion) { 3424 if (mKeyguardMediator != null && mKeyguardMediator.isShowing()) { 3425 // If the keyguard is showing, let it decide what to do with the wake motion. 3426 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq(); 3427 } else { 3428 // Otherwise, wake the device ourselves. 3429 result |= ACTION_WAKE_UP; 3430 } 3431 } 3432 return result; 3433 } 3434 3435 void dispatchMediaKeyWithWakeLock(KeyEvent event) { 3436 if (DEBUG_INPUT) { 3437 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event); 3438 } 3439 3440 if (mHavePendingMediaKeyRepeatWithWakeLock) { 3441 if (DEBUG_INPUT) { 3442 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat"); 3443 } 3444 3445 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK); 3446 mHavePendingMediaKeyRepeatWithWakeLock = false; 3447 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock 3448 } 3449 3450 dispatchMediaKeyWithWakeLockToAudioService(event); 3451 3452 if (event.getAction() == KeyEvent.ACTION_DOWN 3453 && event.getRepeatCount() == 0) { 3454 mHavePendingMediaKeyRepeatWithWakeLock = true; 3455 3456 Message msg = mHandler.obtainMessage( 3457 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event); 3458 msg.setAsynchronous(true); 3459 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout()); 3460 } else { 3461 mBroadcastWakeLock.release(); 3462 } 3463 } 3464 3465 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) { 3466 mHavePendingMediaKeyRepeatWithWakeLock = false; 3467 3468 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event, 3469 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS); 3470 if (DEBUG_INPUT) { 3471 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent); 3472 } 3473 3474 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent); 3475 mBroadcastWakeLock.release(); 3476 } 3477 3478 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) { 3479 if (ActivityManagerNative.isSystemReady()) { 3480 IAudioService audioService = getAudioService(); 3481 if (audioService != null) { 3482 try { 3483 audioService.dispatchMediaKeyEventUnderWakelock(event); 3484 } catch (RemoteException e) { 3485 Log.e(TAG, "dispatchMediaKeyEvent threw exception " + e); 3486 } 3487 } 3488 } 3489 } 3490 3491 BroadcastReceiver mDockReceiver = new BroadcastReceiver() { 3492 public void onReceive(Context context, Intent intent) { 3493 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) { 3494 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 3495 Intent.EXTRA_DOCK_STATE_UNDOCKED); 3496 } else { 3497 try { 3498 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface( 3499 ServiceManager.getService(Context.UI_MODE_SERVICE)); 3500 mUiMode = uiModeService.getCurrentModeType(); 3501 } catch (RemoteException e) { 3502 } 3503 } 3504 updateRotation(true); 3505 updateOrientationListenerLp(); 3506 } 3507 }; 3508 3509 /** {@inheritDoc} */ 3510 public void screenTurnedOff(int why) { 3511 EventLog.writeEvent(70000, 0); 3512 synchronized (mLock) { 3513 mScreenOnEarly = false; 3514 mScreenOnFully = false; 3515 } 3516 if (mKeyguardMediator != null) { 3517 mKeyguardMediator.onScreenTurnedOff(why); 3518 } 3519 synchronized (mLock) { 3520 updateOrientationListenerLp(); 3521 updateLockScreenTimeout(); 3522 } 3523 } 3524 3525 /** {@inheritDoc} */ 3526 public void screenTurningOn(final ScreenOnListener screenOnListener) { 3527 EventLog.writeEvent(70000, 1); 3528 if (false) { 3529 RuntimeException here = new RuntimeException("here"); 3530 here.fillInStackTrace(); 3531 Slog.i(TAG, "Screen turning on...", here); 3532 } 3533 if (screenOnListener != null) { 3534 if (mKeyguardMediator != null) { 3535 try { 3536 mWindowManager.setEventDispatching(true); 3537 } catch (RemoteException unhandled) { 3538 } 3539 mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() { 3540 @Override public void onShown(IBinder windowToken) { 3541 if (windowToken != null) { 3542 try { 3543 mWindowManager.waitForWindowDrawn(windowToken, 3544 new IRemoteCallback.Stub() { 3545 @Override public void sendResult(Bundle data) { 3546 Slog.i(TAG, "Lock screen displayed!"); 3547 screenOnListener.onScreenOn(); 3548 synchronized (mLock) { 3549 mScreenOnFully = true; 3550 } 3551 } 3552 }); 3553 } catch (RemoteException e) { 3554 } 3555 } else { 3556 Slog.i(TAG, "No lock screen!"); 3557 screenOnListener.onScreenOn(); 3558 synchronized (mLock) { 3559 mScreenOnFully = true; 3560 } 3561 } 3562 } 3563 }); 3564 } 3565 } else { 3566 if (mKeyguardMediator != null) { 3567 // Must set mScreenOn = true. 3568 mKeyguardMediator.onScreenTurnedOn(null); 3569 } 3570 synchronized (mLock) { 3571 mScreenOnFully = true; 3572 } 3573 } 3574 synchronized (mLock) { 3575 mScreenOnEarly = true; 3576 updateOrientationListenerLp(); 3577 updateLockScreenTimeout(); 3578 } 3579 } 3580 3581 /** {@inheritDoc} */ 3582 public boolean isScreenOnEarly() { 3583 return mScreenOnEarly; 3584 } 3585 3586 /** {@inheritDoc} */ 3587 public boolean isScreenOnFully() { 3588 return mScreenOnFully; 3589 } 3590 3591 /** {@inheritDoc} */ 3592 public void enableKeyguard(boolean enabled) { 3593 if (mKeyguardMediator != null) { 3594 mKeyguardMediator.setKeyguardEnabled(enabled); 3595 } 3596 } 3597 3598 /** {@inheritDoc} */ 3599 public void exitKeyguardSecurely(OnKeyguardExitResult callback) { 3600 if (mKeyguardMediator != null) { 3601 mKeyguardMediator.verifyUnlock(callback); 3602 } 3603 } 3604 3605 private boolean keyguardIsShowingTq() { 3606 if (mKeyguardMediator == null) return false; 3607 return mKeyguardMediator.isShowingAndNotHidden(); 3608 } 3609 3610 3611 /** {@inheritDoc} */ 3612 public boolean isKeyguardLocked() { 3613 return keyguardOn(); 3614 } 3615 3616 /** {@inheritDoc} */ 3617 public boolean isKeyguardSecure() { 3618 if (mKeyguardMediator == null) return false; 3619 return mKeyguardMediator.isSecure(); 3620 } 3621 3622 /** {@inheritDoc} */ 3623 public boolean inKeyguardRestrictedKeyInputMode() { 3624 if (mKeyguardMediator == null) return false; 3625 return mKeyguardMediator.isInputRestricted(); 3626 } 3627 3628 public void dismissKeyguardLw() { 3629 if (!mKeyguardMediator.isSecure()) { 3630 if (mKeyguardMediator.isShowing()) { 3631 mHandler.post(new Runnable() { 3632 public void run() { 3633 mKeyguardMediator.keyguardDone(false, true); 3634 } 3635 }); 3636 } 3637 } 3638 } 3639 3640 void sendCloseSystemWindows() { 3641 sendCloseSystemWindows(mContext, null); 3642 } 3643 3644 void sendCloseSystemWindows(String reason) { 3645 sendCloseSystemWindows(mContext, reason); 3646 } 3647 3648 static void sendCloseSystemWindows(Context context, String reason) { 3649 if (ActivityManagerNative.isSystemReady()) { 3650 try { 3651 ActivityManagerNative.getDefault().closeSystemDialogs(reason); 3652 } catch (RemoteException e) { 3653 } 3654 } 3655 } 3656 3657 @Override 3658 public int rotationForOrientationLw(int orientation, int lastRotation) { 3659 if (false) { 3660 Slog.v(TAG, "rotationForOrientationLw(orient=" 3661 + orientation + ", last=" + lastRotation 3662 + "); user=" + mUserRotation + " " 3663 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) 3664 ? "USER_ROTATION_LOCKED" : "") 3665 ); 3666 } 3667 3668 synchronized (mLock) { 3669 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1 3670 if (sensorRotation < 0) { 3671 // Sensor is disabled, device probably just turned off. 3672 if (mLastSensorRotation >= 0) { 3673 sensorRotation = mLastSensorRotation; 3674 } else { 3675 // Sensor has never been enabled. Last resort is to use lastRotation. 3676 sensorRotation = lastRotation; 3677 } 3678 } else { 3679 // Valid sensor data, save it away. 3680 mLastSensorRotation = sensorRotation; 3681 } 3682 3683 final int preferredRotation; 3684 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) { 3685 // Ignore sensor when lid switch is open and rotation is forced. 3686 preferredRotation = mLidOpenRotation; 3687 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR 3688 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) { 3689 // Ignore sensor when in car dock unless explicitly enabled. 3690 // This case can override the behavior of NOSENSOR, and can also 3691 // enable 180 degree rotation while docked. 3692 preferredRotation = mCarDockEnablesAccelerometer 3693 ? sensorRotation : mCarDockRotation; 3694 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK 3695 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK 3696 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK) 3697 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) { 3698 // Ignore sensor when in desk dock unless explicitly enabled. 3699 // This case can override the behavior of NOSENSOR, and can also 3700 // enable 180 degree rotation while docked. 3701 preferredRotation = mDeskDockEnablesAccelerometer 3702 ? sensorRotation : mDeskDockRotation; 3703 } else if (mHdmiPlugged) { 3704 // Ignore sensor when plugged into HDMI. 3705 // Note that the dock orientation overrides the HDMI orientation. 3706 preferredRotation = mHdmiRotation; 3707 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE 3708 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER 3709 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) 3710 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR 3711 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR 3712 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE 3713 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) { 3714 // Otherwise, use sensor only if requested by the application or enabled 3715 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR. 3716 if (mAllowAllRotations < 0) { 3717 // Can't read this during init() because the context doesn't 3718 // have display metrics at that time so we cannot determine 3719 // tablet vs. phone then. 3720 mAllowAllRotations = mContext.getResources().getBoolean( 3721 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0; 3722 } 3723 if (sensorRotation != Surface.ROTATION_180 3724 || mAllowAllRotations == 1 3725 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) { 3726 preferredRotation = sensorRotation; 3727 } else { 3728 preferredRotation = lastRotation; 3729 } 3730 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED 3731 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 3732 // Apply rotation lock. Does not apply to NOSENSOR. 3733 // The idea is that the user rotation expresses a weak preference for the direction 3734 // of gravity and as NOSENSOR is never affected by gravity, then neither should 3735 // NOSENSOR be affected by rotation lock (although it will be affected by docks). 3736 preferredRotation = mUserRotation; 3737 } else { 3738 // No overriding preference. 3739 // We will do exactly what the application asked us to do. 3740 preferredRotation = -1; 3741 } 3742 3743 switch (orientation) { 3744 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 3745 // Return portrait unless overridden. 3746 if (isAnyPortrait(preferredRotation)) { 3747 return preferredRotation; 3748 } 3749 return mPortraitRotation; 3750 3751 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 3752 // Return landscape unless overridden. 3753 if (isLandscapeOrSeascape(preferredRotation)) { 3754 return preferredRotation; 3755 } 3756 return mLandscapeRotation; 3757 3758 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 3759 // Return reverse portrait unless overridden. 3760 if (isAnyPortrait(preferredRotation)) { 3761 return preferredRotation; 3762 } 3763 return mUpsideDownRotation; 3764 3765 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 3766 // Return seascape unless overridden. 3767 if (isLandscapeOrSeascape(preferredRotation)) { 3768 return preferredRotation; 3769 } 3770 return mSeascapeRotation; 3771 3772 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 3773 // Return either landscape rotation. 3774 if (isLandscapeOrSeascape(preferredRotation)) { 3775 return preferredRotation; 3776 } 3777 if (isLandscapeOrSeascape(lastRotation)) { 3778 return lastRotation; 3779 } 3780 return mLandscapeRotation; 3781 3782 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 3783 // Return either portrait rotation. 3784 if (isAnyPortrait(preferredRotation)) { 3785 return preferredRotation; 3786 } 3787 if (isAnyPortrait(lastRotation)) { 3788 return lastRotation; 3789 } 3790 return mPortraitRotation; 3791 3792 default: 3793 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR, 3794 // just return the preferred orientation we already calculated. 3795 if (preferredRotation >= 0) { 3796 return preferredRotation; 3797 } 3798 return Surface.ROTATION_0; 3799 } 3800 } 3801 } 3802 3803 @Override 3804 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) { 3805 switch (orientation) { 3806 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: 3807 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: 3808 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT: 3809 return isAnyPortrait(rotation); 3810 3811 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: 3812 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: 3813 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE: 3814 return isLandscapeOrSeascape(rotation); 3815 3816 default: 3817 return true; 3818 } 3819 } 3820 3821 @Override 3822 public void setRotationLw(int rotation) { 3823 mOrientationListener.setCurrentRotation(rotation); 3824 } 3825 3826 private boolean isLandscapeOrSeascape(int rotation) { 3827 return rotation == mLandscapeRotation || rotation == mSeascapeRotation; 3828 } 3829 3830 private boolean isAnyPortrait(int rotation) { 3831 return rotation == mPortraitRotation || rotation == mUpsideDownRotation; 3832 } 3833 3834 3835 // User rotation: to be used when all else fails in assigning an orientation to the device 3836 public void setUserRotationMode(int mode, int rot) { 3837 ContentResolver res = mContext.getContentResolver(); 3838 3839 // mUserRotationMode and mUserRotation will be assigned by the content observer 3840 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) { 3841 Settings.System.putInt(res, 3842 Settings.System.USER_ROTATION, 3843 rot); 3844 Settings.System.putInt(res, 3845 Settings.System.ACCELEROMETER_ROTATION, 3846 0); 3847 } else { 3848 Settings.System.putInt(res, 3849 Settings.System.ACCELEROMETER_ROTATION, 3850 1); 3851 } 3852 } 3853 3854 public void setSafeMode(boolean safeMode) { 3855 mSafeMode = safeMode; 3856 performHapticFeedbackLw(null, safeMode 3857 ? HapticFeedbackConstants.SAFE_MODE_ENABLED 3858 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true); 3859 } 3860 3861 static long[] getLongIntArray(Resources r, int resid) { 3862 int[] ar = r.getIntArray(resid); 3863 if (ar == null) { 3864 return null; 3865 } 3866 long[] out = new long[ar.length]; 3867 for (int i=0; i<ar.length; i++) { 3868 out[i] = ar[i]; 3869 } 3870 return out; 3871 } 3872 3873 /** {@inheritDoc} */ 3874 public void systemReady() { 3875 if (mKeyguardMediator != null) { 3876 // tell the keyguard 3877 mKeyguardMediator.onSystemReady(); 3878 } 3879 synchronized (mLock) { 3880 updateOrientationListenerLp(); 3881 mSystemReady = true; 3882 mHandler.post(new Runnable() { 3883 public void run() { 3884 updateSettings(); 3885 } 3886 }); 3887 } 3888 } 3889 3890 /** {@inheritDoc} */ 3891 public void systemBooted() { 3892 synchronized (mLock) { 3893 mSystemBooted = true; 3894 } 3895 } 3896 3897 ProgressDialog mBootMsgDialog = null; 3898 3899 /** {@inheritDoc} */ 3900 public void showBootMessage(final CharSequence msg, final boolean always) { 3901 if (mHeadless) return; 3902 mHandler.post(new Runnable() { 3903 @Override public void run() { 3904 if (mBootMsgDialog == null) { 3905 mBootMsgDialog = new ProgressDialog(mContext) { 3906 // This dialog will consume all events coming in to 3907 // it, to avoid it trying to do things too early in boot. 3908 @Override public boolean dispatchKeyEvent(KeyEvent event) { 3909 return true; 3910 } 3911 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { 3912 return true; 3913 } 3914 @Override public boolean dispatchTouchEvent(MotionEvent ev) { 3915 return true; 3916 } 3917 @Override public boolean dispatchTrackballEvent(MotionEvent ev) { 3918 return true; 3919 } 3920 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { 3921 return true; 3922 } 3923 @Override public boolean dispatchPopulateAccessibilityEvent( 3924 AccessibilityEvent event) { 3925 return true; 3926 } 3927 }; 3928 mBootMsgDialog.setTitle(R.string.android_upgrading_title); 3929 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); 3930 mBootMsgDialog.setIndeterminate(true); 3931 mBootMsgDialog.getWindow().setType( 3932 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); 3933 mBootMsgDialog.getWindow().addFlags( 3934 WindowManager.LayoutParams.FLAG_DIM_BEHIND 3935 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); 3936 mBootMsgDialog.getWindow().setDimAmount(1); 3937 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); 3938 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 3939 mBootMsgDialog.getWindow().setAttributes(lp); 3940 mBootMsgDialog.setCancelable(false); 3941 mBootMsgDialog.show(); 3942 } 3943 mBootMsgDialog.setMessage(msg); 3944 } 3945 }); 3946 } 3947 3948 /** {@inheritDoc} */ 3949 public void hideBootMessages() { 3950 mHandler.post(new Runnable() { 3951 @Override public void run() { 3952 if (mBootMsgDialog != null) { 3953 mBootMsgDialog.dismiss(); 3954 mBootMsgDialog = null; 3955 } 3956 } 3957 }); 3958 } 3959 3960 /** {@inheritDoc} */ 3961 public void userActivity() { 3962 // *************************************** 3963 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE 3964 // *************************************** 3965 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER 3966 // WITH ITS LOCKS HELD. 3967 // 3968 // This code must be VERY careful about the locks 3969 // it acquires. 3970 // In fact, the current code acquires way too many, 3971 // and probably has lurking deadlocks. 3972 3973 synchronized (mScreenLockTimeout) { 3974 if (mLockScreenTimerActive) { 3975 // reset the timer 3976 mHandler.removeCallbacks(mScreenLockTimeout); 3977 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 3978 } 3979 } 3980 } 3981 3982 Runnable mScreenLockTimeout = new Runnable() { 3983 public void run() { 3984 synchronized (this) { 3985 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard"); 3986 if (mKeyguardMediator != null) { 3987 mKeyguardMediator.doKeyguardTimeout(); 3988 } 3989 mLockScreenTimerActive = false; 3990 } 3991 } 3992 }; 3993 3994 public void lockNow() { 3995 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 3996 mHandler.removeCallbacks(mScreenLockTimeout); 3997 mHandler.post(mScreenLockTimeout); 3998 } 3999 4000 private void updateLockScreenTimeout() { 4001 synchronized (mScreenLockTimeout) { 4002 boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly && 4003 mKeyguardMediator != null && mKeyguardMediator.isSecure()); 4004 if (mLockScreenTimerActive != enable) { 4005 if (enable) { 4006 if (localLOGV) Log.v(TAG, "setting lockscreen timer"); 4007 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout); 4008 } else { 4009 if (localLOGV) Log.v(TAG, "clearing lockscreen timer"); 4010 mHandler.removeCallbacks(mScreenLockTimeout); 4011 } 4012 mLockScreenTimerActive = enable; 4013 } 4014 } 4015 } 4016 4017 /** {@inheritDoc} */ 4018 public void enableScreenAfterBoot() { 4019 readLidState(); 4020 applyLidSwitchState(); 4021 updateRotation(true); 4022 } 4023 4024 private void applyLidSwitchState() { 4025 if (mLidState == LID_CLOSED && mLidControlsSleep) { 4026 mPowerManager.goToSleep(SystemClock.uptimeMillis()); 4027 } 4028 } 4029 4030 void updateRotation(boolean alwaysSendConfiguration) { 4031 try { 4032 //set orientation on WindowManager 4033 mWindowManager.updateRotation(alwaysSendConfiguration, false); 4034 } catch (RemoteException e) { 4035 // Ignore 4036 } 4037 } 4038 4039 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) { 4040 try { 4041 //set orientation on WindowManager 4042 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout); 4043 } catch (RemoteException e) { 4044 // Ignore 4045 } 4046 } 4047 4048 /** 4049 * Return an Intent to launch the currently active dock app as home. Returns 4050 * null if the standard home should be launched, which is the case if any of the following is 4051 * true: 4052 * <ul> 4053 * <li>The device is not in either car mode or desk mode 4054 * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false 4055 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false 4056 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME 4057 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME 4058 * </ul> 4059 * @return 4060 */ 4061 Intent createHomeDockIntent() { 4062 Intent intent = null; 4063 4064 // What home does is based on the mode, not the dock state. That 4065 // is, when in car mode you should be taken to car home regardless 4066 // of whether we are actually in a car dock. 4067 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) { 4068 if (ENABLE_CAR_DOCK_HOME_CAPTURE) { 4069 intent = mCarDockIntent; 4070 } 4071 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) { 4072 if (ENABLE_DESK_DOCK_HOME_CAPTURE) { 4073 intent = mDeskDockIntent; 4074 } 4075 } 4076 4077 if (intent == null) { 4078 return null; 4079 } 4080 4081 ActivityInfo ai = intent.resolveActivityInfo( 4082 mContext.getPackageManager(), PackageManager.GET_META_DATA); 4083 if (ai == null) { 4084 return null; 4085 } 4086 4087 if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) { 4088 intent = new Intent(intent); 4089 intent.setClassName(ai.packageName, ai.name); 4090 return intent; 4091 } 4092 4093 return null; 4094 } 4095 4096 void startDockOrHome() { 4097 Intent dock = createHomeDockIntent(); 4098 if (dock != null) { 4099 try { 4100 mContext.startActivity(dock); 4101 return; 4102 } catch (ActivityNotFoundException e) { 4103 } 4104 } 4105 mContext.startActivity(mHomeIntent); 4106 } 4107 4108 /** 4109 * goes to the home screen 4110 * @return whether it did anything 4111 */ 4112 boolean goHome() { 4113 if (false) { 4114 // This code always brings home to the front. 4115 try { 4116 ActivityManagerNative.getDefault().stopAppSwitches(); 4117 } catch (RemoteException e) { 4118 } 4119 sendCloseSystemWindows(); 4120 startDockOrHome(); 4121 } else { 4122 // This code brings home to the front or, if it is already 4123 // at the front, puts the device to sleep. 4124 try { 4125 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) { 4126 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry. 4127 Log.d(TAG, "UTS-TEST-MODE"); 4128 } else { 4129 ActivityManagerNative.getDefault().stopAppSwitches(); 4130 sendCloseSystemWindows(); 4131 Intent dock = createHomeDockIntent(); 4132 if (dock != null) { 4133 int result = ActivityManagerNative.getDefault() 4134 .startActivity(null, dock, 4135 dock.resolveTypeIfNeeded(mContext.getContentResolver()), 4136 null, null, 0, 4137 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 4138 null, null, null); 4139 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 4140 return false; 4141 } 4142 } 4143 } 4144 int result = ActivityManagerNative.getDefault() 4145 .startActivity(null, mHomeIntent, 4146 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()), 4147 null, null, 0, 4148 ActivityManager.START_FLAG_ONLY_IF_NEEDED, 4149 null, null, null); 4150 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) { 4151 return false; 4152 } 4153 } catch (RemoteException ex) { 4154 // bummer, the activity manager, which is in this process, is dead 4155 } 4156 } 4157 return true; 4158 } 4159 4160 public void setCurrentOrientationLw(int newOrientation) { 4161 synchronized (mLock) { 4162 if (newOrientation != mCurrentAppOrientation) { 4163 mCurrentAppOrientation = newOrientation; 4164 updateOrientationListenerLp(); 4165 } 4166 } 4167 } 4168 4169 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) { 4170 final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(), 4171 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0; 4172 if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) { 4173 return false; 4174 } 4175 long[] pattern = null; 4176 switch (effectId) { 4177 case HapticFeedbackConstants.LONG_PRESS: 4178 pattern = mLongPressVibePattern; 4179 break; 4180 case HapticFeedbackConstants.VIRTUAL_KEY: 4181 pattern = mVirtualKeyVibePattern; 4182 break; 4183 case HapticFeedbackConstants.KEYBOARD_TAP: 4184 pattern = mKeyboardTapVibePattern; 4185 break; 4186 case HapticFeedbackConstants.SAFE_MODE_DISABLED: 4187 pattern = mSafeModeDisabledVibePattern; 4188 break; 4189 case HapticFeedbackConstants.SAFE_MODE_ENABLED: 4190 pattern = mSafeModeEnabledVibePattern; 4191 break; 4192 default: 4193 return false; 4194 } 4195 if (pattern.length == 1) { 4196 // One-shot vibration 4197 mVibrator.vibrate(pattern[0]); 4198 } else { 4199 // Pattern vibration 4200 mVibrator.vibrate(pattern, -1); 4201 } 4202 return true; 4203 } 4204 4205 public void screenOnStartedLw() { 4206 } 4207 4208 public void screenOnStoppedLw() { 4209 if (mPowerManager.isScreenOn()) { 4210 if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) { 4211 long curTime = SystemClock.uptimeMillis(); 4212 mPowerManager.userActivity(curTime, false); 4213 } 4214 } 4215 } 4216 4217 public boolean allowKeyRepeat() { 4218 // disable key repeat when screen is off 4219 return mScreenOnEarly; 4220 } 4221 4222 private int updateSystemUiVisibilityLw() { 4223 // If there is no window focused, there will be nobody to handle the events 4224 // anyway, so just hang on in whatever state we're in until things settle down. 4225 if (mFocusedWindow == null) { 4226 return 0; 4227 } 4228 final int visibility = mFocusedWindow.getSystemUiVisibility() 4229 & ~mResettingSystemUiFlags 4230 & ~mForceClearedSystemUiFlags; 4231 int diff = visibility ^ mLastSystemUiFlags; 4232 final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState); 4233 if (diff == 0 && mLastFocusNeedsMenu == needsMenu 4234 && mFocusedApp == mFocusedWindow.getAppToken()) { 4235 return 0; 4236 } 4237 mLastSystemUiFlags = visibility; 4238 mLastFocusNeedsMenu = needsMenu; 4239 mFocusedApp = mFocusedWindow.getAppToken(); 4240 mHandler.post(new Runnable() { 4241 public void run() { 4242 try { 4243 IStatusBarService statusbar = getStatusBarService(); 4244 if (statusbar != null) { 4245 statusbar.setSystemUiVisibility(visibility, 0xffffffff); 4246 statusbar.topAppWindowChanged(needsMenu); 4247 } 4248 } catch (RemoteException e) { 4249 // re-acquire status bar service next time it is needed. 4250 mStatusBarService = null; 4251 } 4252 } 4253 }); 4254 return diff; 4255 } 4256 4257 // Use this instead of checking config_showNavigationBar so that it can be consistently 4258 // overridden by qemu.hw.mainkeys in the emulator. 4259 public boolean hasNavigationBar() { 4260 return mHasNavigationBar; 4261 } 4262 4263 @Override 4264 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) { 4265 mLastInputMethodWindow = ime; 4266 mLastInputMethodTargetWindow = target; 4267 } 4268 4269 public void dump(String prefix, PrintWriter pw, String[] args) { 4270 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode); 4271 pw.print(" mSystemReady="); pw.print(mSystemReady); 4272 pw.print(" mSystemBooted="); pw.println(mSystemBooted); 4273 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState); 4274 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation); 4275 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged); 4276 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0 4277 || mForceClearedSystemUiFlags != 0) { 4278 pw.print(prefix); pw.print("mLastSystemUiFlags=0x"); 4279 pw.print(Integer.toHexString(mLastSystemUiFlags)); 4280 pw.print(" mResettingSystemUiFlags=0x"); 4281 pw.print(Integer.toHexString(mResettingSystemUiFlags)); 4282 pw.print(" mForceClearedSystemUiFlags=0x"); 4283 pw.println(Integer.toHexString(mForceClearedSystemUiFlags)); 4284 } 4285 if (mLastFocusNeedsMenu) { 4286 pw.print(prefix); pw.print("mLastFocusNeedsMenu="); 4287 pw.println(mLastFocusNeedsMenu); 4288 } 4289 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode); 4290 pw.print(" mDockMode="); pw.print(mDockMode); 4291 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation); 4292 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation); 4293 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode); 4294 pw.print(" mUserRotation="); pw.print(mUserRotation); 4295 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations); 4296 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation); 4297 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer="); 4298 pw.print(mCarDockEnablesAccelerometer); 4299 pw.print(" mDeskDockEnablesAccelerometer="); 4300 pw.println(mDeskDockEnablesAccelerometer); 4301 pw.print(prefix); pw.print("mLidKeyboardAccessibility="); 4302 pw.print(mLidKeyboardAccessibility); 4303 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility); 4304 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep); 4305 pw.print(prefix); pw.print("mLongPressOnPowerBehavior="); 4306 pw.print(mLongPressOnPowerBehavior); 4307 pw.print(" mHasSoftInput="); pw.println(mHasSoftInput); 4308 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly); 4309 pw.print(" mScreenOnFully="); pw.print(mScreenOnFully); 4310 pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled); 4311 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft); 4312 pw.print(","); pw.print(mUnrestrictedScreenTop); 4313 pw.print(") "); pw.print(mUnrestrictedScreenWidth); 4314 pw.print("x"); pw.println(mUnrestrictedScreenHeight); 4315 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft); 4316 pw.print(","); pw.print(mRestrictedScreenTop); 4317 pw.print(") "); pw.print(mRestrictedScreenWidth); 4318 pw.print("x"); pw.println(mRestrictedScreenHeight); 4319 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft); 4320 pw.print(","); pw.print(mStableFullscreenTop); 4321 pw.print(")-("); pw.print(mStableFullscreenRight); 4322 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")"); 4323 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft); 4324 pw.print(","); pw.print(mStableTop); 4325 pw.print(")-("); pw.print(mStableRight); 4326 pw.print(","); pw.print(mStableBottom); pw.println(")"); 4327 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft); 4328 pw.print(","); pw.print(mSystemTop); 4329 pw.print(")-("); pw.print(mSystemRight); 4330 pw.print(","); pw.print(mSystemBottom); pw.println(")"); 4331 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft); 4332 pw.print(","); pw.print(mCurTop); 4333 pw.print(")-("); pw.print(mCurRight); 4334 pw.print(","); pw.print(mCurBottom); pw.println(")"); 4335 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft); 4336 pw.print(","); pw.print(mContentTop); 4337 pw.print(")-("); pw.print(mContentRight); 4338 pw.print(","); pw.print(mContentBottom); pw.println(")"); 4339 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft); 4340 pw.print(","); pw.print(mDockTop); 4341 pw.print(")-("); pw.print(mDockRight); 4342 pw.print(","); pw.print(mDockBottom); pw.println(")"); 4343 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer); 4344 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer); 4345 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState="); 4346 pw.println(mTopFullscreenOpaqueWindowState); 4347 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen); 4348 pw.print(" mForceStatusBar="); pw.print(mForceStatusBar); 4349 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen); 4350 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard); 4351 pw.print(" mHomePressed="); pw.println(mHomePressed); 4352 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn); 4353 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout); 4354 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive); 4355 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior); 4356 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior); 4357 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior); 4358 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation); 4359 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation); 4360 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation); 4361 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation); 4362 } 4363} 4364