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