OSDN Git Service

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