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