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