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