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