• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.policy.impl;
18 
19 import android.app.Activity;
20 import android.app.ActivityManagerNative;
21 import android.app.IActivityManager;
22 import android.app.IStatusBar;
23 import android.content.ActivityNotFoundException;
24 import android.content.BroadcastReceiver;
25 import android.content.ContentResolver;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.content.pm.ActivityInfo;
30 import android.content.pm.PackageManager;
31 import android.content.res.Configuration;
32 import android.content.res.Resources;
33 import android.database.ContentObserver;
34 import android.graphics.Rect;
35 import android.os.BatteryManager;
36 import android.os.Handler;
37 import android.os.IBinder;
38 import android.os.LocalPowerManager;
39 import android.os.PowerManager;
40 import android.os.RemoteException;
41 import android.os.ServiceManager;
42 import android.os.SystemClock;
43 import android.os.SystemProperties;
44 import android.os.Vibrator;
45 import android.provider.Settings;
46 
47 import com.android.internal.policy.PolicyManager;
48 import com.android.internal.telephony.ITelephony;
49 import android.util.Config;
50 import android.util.EventLog;
51 import android.util.Log;
52 import android.view.Display;
53 import android.view.Gravity;
54 import android.view.HapticFeedbackConstants;
55 import android.view.IWindowManager;
56 import android.view.KeyEvent;
57 import android.view.MotionEvent;
58 import android.view.WindowOrientationListener;
59 import android.view.RawInputEvent;
60 import android.view.Surface;
61 import android.view.View;
62 import android.view.ViewConfiguration;
63 import android.view.Window;
64 import android.view.WindowManager;
65 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
66 import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
67 import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
68 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
69 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
70 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
71 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
72 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
73 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
74 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
75 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
76 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
77 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
78 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
79 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
80 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
81 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
82 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
83 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
84 import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
85 import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
86 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
87 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
88 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
89 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
90 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
91 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
92 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
93 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
94 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
95 import android.view.WindowManagerImpl;
96 import android.view.WindowManagerPolicy;
97 import android.view.WindowManagerPolicy.WindowState;
98 import android.view.animation.Animation;
99 import android.view.animation.AnimationUtils;
100 import android.media.IAudioService;
101 import android.media.AudioManager;
102 
103 /**
104  * WindowManagerPolicy implementation for the Android phone UI.  This
105  * introduces a new method suffix, Lp, for an internal lock of the
106  * PhoneWindowManager.  This is used to protect some internal state, and
107  * can be acquired with either thw Lw and Li lock held, so has the restrictions
108  * of both of those when held.
109  */
110 public class PhoneWindowManager implements WindowManagerPolicy {
111     static final String TAG = "WindowManager";
112     static final boolean DEBUG = false;
113     static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
114     static final boolean DEBUG_LAYOUT = false;
115     static final boolean SHOW_STARTING_ANIMATIONS = true;
116     static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
117 
118     // wallpaper is at the bottom, though the window manager may move it.
119     static final int WALLPAPER_LAYER = 2;
120     static final int APPLICATION_LAYER = 2;
121     static final int PHONE_LAYER = 3;
122     static final int SEARCH_BAR_LAYER = 4;
123     static final int STATUS_BAR_PANEL_LAYER = 5;
124     // toasts and the plugged-in battery thing
125     static final int TOAST_LAYER = 6;
126     static final int STATUS_BAR_LAYER = 7;
127     // SIM errors and unlock.  Not sure if this really should be in a high layer.
128     static final int PRIORITY_PHONE_LAYER = 8;
129     // like the ANR / app crashed dialogs
130     static final int SYSTEM_ALERT_LAYER = 9;
131     // system-level error dialogs
132     static final int SYSTEM_ERROR_LAYER = 10;
133     // on-screen keyboards and other such input method user interfaces go here.
134     static final int INPUT_METHOD_LAYER = 11;
135     // on-screen keyboards and other such input method user interfaces go here.
136     static final int INPUT_METHOD_DIALOG_LAYER = 12;
137     // the keyguard; nothing on top of these can take focus, since they are
138     // responsible for power management when displayed.
139     static final int KEYGUARD_LAYER = 13;
140     static final int KEYGUARD_DIALOG_LAYER = 14;
141     // things in here CAN NOT take focus, but are shown on top of everything else.
142     static final int SYSTEM_OVERLAY_LAYER = 15;
143 
144     static final int APPLICATION_MEDIA_SUBLAYER = -2;
145     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
146     static final int APPLICATION_PANEL_SUBLAYER = 1;
147     static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
148 
149     static final float SLIDE_TOUCH_EVENT_SIZE_LIMIT = 0.6f;
150 
151     // Debugging: set this to have the system act like there is no hard keyboard.
152     static final boolean KEYBOARD_ALWAYS_HIDDEN = false;
153 
154     static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
155     static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
156     static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
157 
158     final Object mLock = new Object();
159 
160     Context mContext;
161     IWindowManager mWindowManager;
162     LocalPowerManager mPowerManager;
163     Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
164 
165     // Vibrator pattern for haptic feedback of a long press.
166     long[] mLongPressVibePattern;
167 
168     // Vibrator pattern for haptic feedback of virtual key press.
169     long[] mVirtualKeyVibePattern;
170 
171     // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
172     long[] mSafeModeDisabledVibePattern;
173 
174     // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
175     long[] mSafeModeEnabledVibePattern;
176 
177     /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
178     boolean mEnableShiftMenuBugReports = false;
179 
180     boolean mSafeMode;
181     WindowState mStatusBar = null;
182     WindowState mKeyguard = null;
183     KeyguardViewMediator mKeyguardMediator;
184     GlobalActions mGlobalActions;
185     boolean mShouldTurnOffOnKeyUp;
186     RecentApplicationsDialog mRecentAppsDialog;
187     Handler mHandler;
188 
189     final IntentFilter mBatteryStatusFilter = new IntentFilter();
190 
191     boolean mLidOpen;
192     int mPlugged;
193     boolean mRegisteredBatteryReceiver;
194     int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
195     int mLidOpenRotation;
196     int mCarDockRotation;
197     int mDeskDockRotation;
198     int mCarDockKeepsScreenOn;
199     int mDeskDockKeepsScreenOn;
200     boolean mCarDockEnablesAccelerometer;
201     boolean mDeskDockEnablesAccelerometer;
202     int mLidKeyboardAccessibility;
203     int mLidNavigationAccessibility;
204     boolean mScreenOn = false;
205     boolean mOrientationSensorEnabled = false;
206     int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
207     static final int DEFAULT_ACCELEROMETER_ROTATION = 0;
208     int mAccelerometerDefault = DEFAULT_ACCELEROMETER_ROTATION;
209     boolean mHasSoftInput = false;
210 
211     // The current size of the screen.
212     int mW, mH;
213     // During layout, the current screen borders with all outer decoration
214     // (status bar, input method dock) accounted for.
215     int mCurLeft, mCurTop, mCurRight, mCurBottom;
216     // During layout, the frame in which content should be displayed
217     // to the user, accounting for all screen decoration except for any
218     // space they deem as available for other content.  This is usually
219     // the same as mCur*, but may be larger if the screen decor has supplied
220     // content insets.
221     int mContentLeft, mContentTop, mContentRight, mContentBottom;
222     // During layout, the current screen borders along with input method
223     // windows are placed.
224     int mDockLeft, mDockTop, mDockRight, mDockBottom;
225     // During layout, the layer at which the doc window is placed.
226     int mDockLayer;
227 
228     static final Rect mTmpParentFrame = new Rect();
229     static final Rect mTmpDisplayFrame = new Rect();
230     static final Rect mTmpContentFrame = new Rect();
231     static final Rect mTmpVisibleFrame = new Rect();
232 
233     WindowState mTopFullscreenOpaqueWindowState;
234     boolean mForceStatusBar;
235     boolean mHideLockScreen;
236     boolean mDismissKeyguard;
237     boolean mHomePressed;
238     Intent mHomeIntent;
239     Intent mCarDockIntent;
240     Intent mDeskDockIntent;
241     boolean mSearchKeyPressed;
242     boolean mConsumeSearchKeyUp;
243 
244     static final int ENDCALL_HOME = 0x1;
245     static final int ENDCALL_SLEEPS = 0x2;
246     static final int DEFAULT_ENDCALL_BEHAVIOR = ENDCALL_SLEEPS;
247     int mEndcallBehavior;
248 
249     int mLandscapeRotation = -1;
250     int mPortraitRotation = -1;
251 
252     // Nothing to see here, move along...
253     int mFancyRotationAnimation;
254 
255     ShortcutManager mShortcutManager;
256     PowerManager.WakeLock mBroadcastWakeLock;
257     PowerManager.WakeLock mDockWakeLock;
258 
259     class SettingsObserver extends ContentObserver {
SettingsObserver(Handler handler)260         SettingsObserver(Handler handler) {
261             super(handler);
262         }
263 
observe()264         void observe() {
265             ContentResolver resolver = mContext.getContentResolver();
266             resolver.registerContentObserver(Settings.System.getUriFor(
267                     Settings.System.END_BUTTON_BEHAVIOR), false, this);
268             resolver.registerContentObserver(Settings.System.getUriFor(
269                     Settings.System.ACCELEROMETER_ROTATION), false, this);
270             resolver.registerContentObserver(Settings.Secure.getUriFor(
271                     Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
272             resolver.registerContentObserver(Settings.System.getUriFor(
273                     "fancy_rotation_anim"), false, this);
274             update();
275         }
276 
onChange(boolean selfChange)277         @Override public void onChange(boolean selfChange) {
278             update();
279             try {
280                 mWindowManager.setRotation(USE_LAST_ROTATION, false,
281                         mFancyRotationAnimation);
282             } catch (RemoteException e) {
283                 // Ignore
284             }
285         }
286 
update()287         public void update() {
288             ContentResolver resolver = mContext.getContentResolver();
289             boolean updateRotation = false;
290             synchronized (mLock) {
291                 mEndcallBehavior = Settings.System.getInt(resolver,
292                         Settings.System.END_BUTTON_BEHAVIOR, DEFAULT_ENDCALL_BEHAVIOR);
293                 mFancyRotationAnimation = Settings.System.getInt(resolver,
294                         "fancy_rotation_anim", 0) != 0 ? 0x80 : 0;
295                 int accelerometerDefault = Settings.System.getInt(resolver,
296                         Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
297                 if (mAccelerometerDefault != accelerometerDefault) {
298                     mAccelerometerDefault = accelerometerDefault;
299                     updateOrientationListenerLp();
300                 }
301                 String imId = Settings.Secure.getString(resolver,
302                         Settings.Secure.DEFAULT_INPUT_METHOD);
303                 boolean hasSoftInput = imId != null && imId.length() > 0;
304                 if (mHasSoftInput != hasSoftInput) {
305                     mHasSoftInput = hasSoftInput;
306                     updateRotation = true;
307                 }
308             }
309             if (updateRotation) {
310                 updateRotation(0);
311             }
312         }
313     }
314 
315     class MyOrientationListener extends WindowOrientationListener {
MyOrientationListener(Context context)316         MyOrientationListener(Context context) {
317             super(context);
318         }
319 
320         @Override
onOrientationChanged(int rotation)321         public void onOrientationChanged(int rotation) {
322             // Send updates based on orientation value
323             if (localLOGV) Log.v(TAG, "onOrientationChanged, rotation changed to " +rotation);
324             try {
325                 mWindowManager.setRotation(rotation, false,
326                         mFancyRotationAnimation);
327             } catch (RemoteException e) {
328                 // Ignore
329 
330             }
331         }
332     }
333     MyOrientationListener mOrientationListener;
334 
useSensorForOrientationLp(int appOrientation)335     boolean useSensorForOrientationLp(int appOrientation) {
336         // The app says use the sensor.
337         if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
338             return true;
339         }
340         // The user preference says we can rotate, and the app is willing to rotate.
341         if (mAccelerometerDefault != 0 &&
342                 (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
343                  || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
344             return true;
345         }
346         // We're in a dock that has a rotation affinity, an the app is willing to rotate.
347         if ((mCarDockEnablesAccelerometer && mDockState == Intent.EXTRA_DOCK_STATE_CAR)
348                 || (mDeskDockEnablesAccelerometer && mDockState == Intent.EXTRA_DOCK_STATE_DESK)) {
349             // Note we override the nosensor flag here.
350             if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
351                     || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
352                     || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
353                 return true;
354             }
355         }
356         // Else, don't use the sensor.
357         return false;
358     }
359 
360     /*
361      * We always let the sensor be switched on by default except when
362      * the user has explicitly disabled sensor based rotation or when the
363      * screen is switched off.
364      */
needSensorRunningLp()365     boolean needSensorRunningLp() {
366         if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
367             // If the application has explicitly requested to follow the
368             // orientation, then we need to turn the sensor or.
369             return true;
370         }
371         if ((mCarDockEnablesAccelerometer && mDockState == Intent.EXTRA_DOCK_STATE_CAR) ||
372             (mDeskDockEnablesAccelerometer && mDockState == Intent.EXTRA_DOCK_STATE_DESK)) {
373             // enable accelerometer if we are docked in a dock that enables accelerometer
374             // orientation management,
375             return true;
376         }
377         if (mAccelerometerDefault == 0) {
378             // If the setting for using the sensor by default is enabled, then
379             // we will always leave it on.  Note that the user could go to
380             // a window that forces an orientation that does not use the
381             // sensor and in theory we could turn it off... however, when next
382             // turning it on we won't have a good value for the current
383             // orientation for a little bit, which can cause orientation
384             // changes to lag, so we'd like to keep it always on.  (It will
385             // still be turned off when the screen is off.)
386             return false;
387         }
388         return true;
389     }
390 
391     /*
392      * Various use cases for invoking this function
393      * screen turning off, should always disable listeners if already enabled
394      * screen turned on and current app has sensor based orientation, enable listeners
395      * if not already enabled
396      * screen turned on and current app does not have sensor orientation, disable listeners if
397      * already enabled
398      * screen turning on and current app has sensor based orientation, enable listeners if needed
399      * screen turning on and current app has nosensor based orientation, do nothing
400      */
updateOrientationListenerLp()401     void updateOrientationListenerLp() {
402         if (!mOrientationListener.canDetectOrientation()) {
403             // If sensor is turned off or nonexistent for some reason
404             return;
405         }
406         //Could have been invoked due to screen turning on or off or
407         //change of the currently visible window's orientation
408         if (localLOGV) Log.v(TAG, "Screen status="+mScreenOn+
409                 ", current orientation="+mCurrentAppOrientation+
410                 ", SensorEnabled="+mOrientationSensorEnabled);
411         boolean disable = true;
412         if (mScreenOn) {
413             if (needSensorRunningLp()) {
414                 disable = false;
415                 //enable listener if not already enabled
416                 if (!mOrientationSensorEnabled) {
417                     mOrientationListener.enable();
418                     if(localLOGV) Log.v(TAG, "Enabling listeners");
419                     mOrientationSensorEnabled = true;
420                 }
421             }
422         }
423         //check if sensors need to be disabled
424         if (disable && mOrientationSensorEnabled) {
425             mOrientationListener.disable();
426             if(localLOGV) Log.v(TAG, "Disabling listeners");
427             mOrientationSensorEnabled = false;
428         }
429     }
430 
431     Runnable mPowerLongPress = new Runnable() {
432         public void run() {
433             mShouldTurnOffOnKeyUp = false;
434             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
435             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
436             showGlobalActionsDialog();
437         }
438     };
439 
showGlobalActionsDialog()440     void showGlobalActionsDialog() {
441         if (mGlobalActions == null) {
442             mGlobalActions = new GlobalActions(mContext);
443         }
444         final boolean keyguardShowing = mKeyguardMediator.isShowing();
445         mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
446         if (keyguardShowing) {
447             // since it took two seconds of long press to bring this up,
448             // poke the wake lock so they have some time to see the dialog.
449             mKeyguardMediator.pokeWakelock();
450         }
451     }
452 
isDeviceProvisioned()453     boolean isDeviceProvisioned() {
454         return Settings.Secure.getInt(
455                 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
456     }
457 
458     /**
459      * When a home-key longpress expires, close other system windows and launch the recent apps
460      */
461     Runnable mHomeLongPress = new Runnable() {
462         public void run() {
463             /*
464              * Eat the longpress so it won't dismiss the recent apps dialog when
465              * the user lets go of the home key
466              */
467             mHomePressed = false;
468             performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
469             sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
470             showRecentAppsDialog();
471         }
472     };
473 
474     /**
475      * Create (if necessary) and launch the recent apps dialog
476      */
showRecentAppsDialog()477     void showRecentAppsDialog() {
478         if (mRecentAppsDialog == null) {
479             mRecentAppsDialog = new RecentApplicationsDialog(mContext);
480         }
481         mRecentAppsDialog.show();
482     }
483 
484     /** {@inheritDoc} */
init(Context context, IWindowManager windowManager, LocalPowerManager powerManager)485     public void init(Context context, IWindowManager windowManager,
486             LocalPowerManager powerManager) {
487         mContext = context;
488         mWindowManager = windowManager;
489         mPowerManager = powerManager;
490         mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
491         mHandler = new Handler();
492         mOrientationListener = new MyOrientationListener(mContext);
493         SettingsObserver settingsObserver = new SettingsObserver(mHandler);
494         settingsObserver.observe();
495         mShortcutManager = new ShortcutManager(context, mHandler);
496         mShortcutManager.observe();
497         mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
498         mHomeIntent.addCategory(Intent.CATEGORY_HOME);
499         mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
500                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
501         mCarDockIntent =  new Intent(Intent.ACTION_MAIN, null);
502         mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
503         mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
504                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
505         mDeskDockIntent =  new Intent(Intent.ACTION_MAIN, null);
506         mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
507         mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
508                 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
509         PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
510         mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
511                 "PhoneWindowManager.mBroadcastWakeLock");
512         mDockWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK,
513                 "PhoneWindowManager.mDockWakeLock");
514         mDockWakeLock.setReferenceCounted(false);
515         mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
516         mLidOpenRotation = readRotation(
517                 com.android.internal.R.integer.config_lidOpenRotation);
518         mCarDockRotation = readRotation(
519                 com.android.internal.R.integer.config_carDockRotation);
520         mDeskDockRotation = readRotation(
521                 com.android.internal.R.integer.config_deskDockRotation);
522         mCarDockKeepsScreenOn = mContext.getResources().getInteger(
523                 com.android.internal.R.integer.config_carDockKeepsScreenOn);
524         mDeskDockKeepsScreenOn = mContext.getResources().getInteger(
525                 com.android.internal.R.integer.config_deskDockKeepsScreenOn);
526         mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
527                 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
528         mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
529                 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
530         mLidKeyboardAccessibility = mContext.getResources().getInteger(
531                 com.android.internal.R.integer.config_lidKeyboardAccessibility);
532         mLidNavigationAccessibility = mContext.getResources().getInteger(
533                 com.android.internal.R.integer.config_lidNavigationAccessibility);
534         // register for battery events
535         mBatteryStatusFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
536         mPlugged = 0;
537         updatePlugged(context.registerReceiver(null, mBatteryStatusFilter));
538         // register for dock events
539         context.registerReceiver(mDockReceiver, new IntentFilter(Intent.ACTION_DOCK_EVENT));
540         mVibrator = new Vibrator();
541         mLongPressVibePattern = getLongIntArray(mContext.getResources(),
542                 com.android.internal.R.array.config_longPressVibePattern);
543         mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
544                 com.android.internal.R.array.config_virtualKeyVibePattern);
545         mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
546                 com.android.internal.R.array.config_safeModeDisabledVibePattern);
547         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
548                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
549     }
550 
updatePlugged(Intent powerIntent)551     void updatePlugged(Intent powerIntent) {
552         if (localLOGV) Log.v(TAG, "New battery status: " + powerIntent.getExtras());
553         if (powerIntent != null) {
554             mPlugged = powerIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
555             if (localLOGV) Log.v(TAG, "PLUGGED: " + mPlugged);
556         }
557     }
558 
readRotation(int resID)559     private int readRotation(int resID) {
560         try {
561             int rotation = mContext.getResources().getInteger(resID);
562             switch (rotation) {
563                 case 0:
564                     return Surface.ROTATION_0;
565                 case 90:
566                     return Surface.ROTATION_90;
567                 case 180:
568                     return Surface.ROTATION_180;
569                 case 270:
570                     return Surface.ROTATION_270;
571             }
572         } catch (Resources.NotFoundException e) {
573             // fall through
574         }
575         return -1;
576     }
577 
578     /** {@inheritDoc} */
checkAddPermission(WindowManager.LayoutParams attrs)579     public int checkAddPermission(WindowManager.LayoutParams attrs) {
580         int type = attrs.type;
581 
582         if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
583                 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
584             return WindowManagerImpl.ADD_OKAY;
585         }
586         String permission = null;
587         switch (type) {
588             case TYPE_TOAST:
589                 // XXX right now the app process has complete control over
590                 // this...  should introduce a token to let the system
591                 // monitor/control what they are doing.
592                 break;
593             case TYPE_INPUT_METHOD:
594             case TYPE_WALLPAPER:
595                 // The window manager will check these.
596                 break;
597             case TYPE_PHONE:
598             case TYPE_PRIORITY_PHONE:
599             case TYPE_SYSTEM_ALERT:
600             case TYPE_SYSTEM_ERROR:
601             case TYPE_SYSTEM_OVERLAY:
602                 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
603                 break;
604             default:
605                 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
606         }
607         if (permission != null) {
608             if (mContext.checkCallingOrSelfPermission(permission)
609                     != PackageManager.PERMISSION_GRANTED) {
610                 return WindowManagerImpl.ADD_PERMISSION_DENIED;
611             }
612         }
613         return WindowManagerImpl.ADD_OKAY;
614     }
615 
adjustWindowParamsLw(WindowManager.LayoutParams attrs)616     public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
617         switch (attrs.type) {
618             case TYPE_SYSTEM_OVERLAY:
619             case TYPE_TOAST:
620                 // These types of windows can't receive input events.
621                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
622                         | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
623                 break;
624         }
625     }
626 
readLidState()627     void readLidState() {
628         try {
629             int sw = mWindowManager.getSwitchState(RawInputEvent.SW_LID);
630             if (sw >= 0) {
631                 mLidOpen = sw == 0;
632             }
633         } catch (RemoteException e) {
634             // Ignore
635         }
636     }
637 
determineHiddenState(boolean lidOpen, int mode, int hiddenValue, int visibleValue)638     private int determineHiddenState(boolean lidOpen,
639             int mode, int hiddenValue, int visibleValue) {
640         switch (mode) {
641             case 1:
642                 return lidOpen ? visibleValue : hiddenValue;
643             case 2:
644                 return lidOpen ? hiddenValue : visibleValue;
645         }
646         return visibleValue;
647     }
648 
649     /** {@inheritDoc} */
adjustConfigurationLw(Configuration config)650     public void adjustConfigurationLw(Configuration config) {
651         readLidState();
652         final boolean lidOpen = !KEYBOARD_ALWAYS_HIDDEN && mLidOpen;
653         mPowerManager.setKeyboardVisibility(lidOpen);
654         config.hardKeyboardHidden = determineHiddenState(lidOpen,
655                 mLidKeyboardAccessibility, Configuration.HARDKEYBOARDHIDDEN_YES,
656                 Configuration.HARDKEYBOARDHIDDEN_NO);
657         config.navigationHidden = determineHiddenState(lidOpen,
658                 mLidNavigationAccessibility, Configuration.NAVIGATIONHIDDEN_YES,
659                 Configuration.NAVIGATIONHIDDEN_NO);
660         config.keyboardHidden = (config.hardKeyboardHidden
661                         == Configuration.HARDKEYBOARDHIDDEN_NO || mHasSoftInput)
662                 ? Configuration.KEYBOARDHIDDEN_NO
663                 : Configuration.KEYBOARDHIDDEN_YES;
664     }
665 
isCheekPressedAgainstScreen(MotionEvent ev)666     public boolean isCheekPressedAgainstScreen(MotionEvent ev) {
667         if(ev.getSize() > SLIDE_TOUCH_EVENT_SIZE_LIMIT) {
668             return true;
669         }
670         int size = ev.getHistorySize();
671         for(int i = 0; i < size; i++) {
672             if(ev.getHistoricalSize(i) > SLIDE_TOUCH_EVENT_SIZE_LIMIT) {
673                 return true;
674             }
675         }
676         return false;
677     }
678 
679     /** {@inheritDoc} */
windowTypeToLayerLw(int type)680     public int windowTypeToLayerLw(int type) {
681         if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
682             return APPLICATION_LAYER;
683         }
684         switch (type) {
685         case TYPE_STATUS_BAR:
686             return STATUS_BAR_LAYER;
687         case TYPE_STATUS_BAR_PANEL:
688             return STATUS_BAR_PANEL_LAYER;
689         case TYPE_SEARCH_BAR:
690             return SEARCH_BAR_LAYER;
691         case TYPE_PHONE:
692             return PHONE_LAYER;
693         case TYPE_KEYGUARD:
694             return KEYGUARD_LAYER;
695         case TYPE_KEYGUARD_DIALOG:
696             return KEYGUARD_DIALOG_LAYER;
697         case TYPE_SYSTEM_ALERT:
698             return SYSTEM_ALERT_LAYER;
699         case TYPE_SYSTEM_ERROR:
700             return SYSTEM_ERROR_LAYER;
701         case TYPE_INPUT_METHOD:
702             return INPUT_METHOD_LAYER;
703         case TYPE_INPUT_METHOD_DIALOG:
704             return INPUT_METHOD_DIALOG_LAYER;
705         case TYPE_SYSTEM_OVERLAY:
706             return SYSTEM_OVERLAY_LAYER;
707         case TYPE_PRIORITY_PHONE:
708             return PRIORITY_PHONE_LAYER;
709         case TYPE_TOAST:
710             return TOAST_LAYER;
711         case TYPE_WALLPAPER:
712             return WALLPAPER_LAYER;
713         }
714         Log.e(TAG, "Unknown window type: " + type);
715         return APPLICATION_LAYER;
716     }
717 
718     /** {@inheritDoc} */
subWindowTypeToLayerLw(int type)719     public int subWindowTypeToLayerLw(int type) {
720         switch (type) {
721         case TYPE_APPLICATION_PANEL:
722         case TYPE_APPLICATION_ATTACHED_DIALOG:
723             return APPLICATION_PANEL_SUBLAYER;
724         case TYPE_APPLICATION_MEDIA:
725             return APPLICATION_MEDIA_SUBLAYER;
726         case TYPE_APPLICATION_MEDIA_OVERLAY:
727             return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
728         case TYPE_APPLICATION_SUB_PANEL:
729             return APPLICATION_SUB_PANEL_SUBLAYER;
730         }
731         Log.e(TAG, "Unknown sub-window type: " + type);
732         return 0;
733     }
734 
getMaxWallpaperLayer()735     public int getMaxWallpaperLayer() {
736         return STATUS_BAR_LAYER;
737     }
738 
doesForceHide(WindowState win, WindowManager.LayoutParams attrs)739     public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
740         return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
741     }
742 
canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs)743     public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
744         return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
745                 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
746     }
747 
748     /** {@inheritDoc} */
addStartingWindow(IBinder appToken, String packageName, int theme, CharSequence nonLocalizedLabel, int labelRes, int icon)749     public View addStartingWindow(IBinder appToken, String packageName,
750                                   int theme, CharSequence nonLocalizedLabel,
751                                   int labelRes, int icon) {
752         if (!SHOW_STARTING_ANIMATIONS) {
753             return null;
754         }
755         if (packageName == null) {
756             return null;
757         }
758 
759     	Context context = mContext;
760     	boolean setTheme = false;
761     	//Log.i(TAG, "addStartingWindow " + packageName + ": nonLocalizedLabel="
762     	//        + nonLocalizedLabel + " theme=" + Integer.toHexString(theme));
763     	if (theme != 0 || labelRes != 0) {
764     	    try {
765     	        context = context.createPackageContext(packageName, 0);
766     	        if (theme != 0) {
767     	            context.setTheme(theme);
768     	            setTheme = true;
769     	        }
770     	    } catch (PackageManager.NameNotFoundException e) {
771                 // Ignore
772             }
773     	}
774     	if (!setTheme) {
775     	    context.setTheme(com.android.internal.R.style.Theme);
776     	}
777 
778         Window win = PolicyManager.makeNewWindow(context);
779         if (win.getWindowStyle().getBoolean(
780                 com.android.internal.R.styleable.Window_windowDisablePreview, false)) {
781             return null;
782         }
783 
784         Resources r = context.getResources();
785         win.setTitle(r.getText(labelRes, nonLocalizedLabel));
786 
787         win.setType(
788             WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
789         // Force the window flags: this is a fake window, so it is not really
790         // touchable or focusable by the user.  We also add in the ALT_FOCUSABLE_IM
791         // flag because we do know that the next window will take input
792         // focus, so we want to get the IME window up on top of us right away.
793         win.setFlags(
794             WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
795             WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
796             WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
797             WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
798             WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
799             WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
800 
801         win.setLayout(WindowManager.LayoutParams.FILL_PARENT,
802                             WindowManager.LayoutParams.FILL_PARENT);
803 
804         final WindowManager.LayoutParams params = win.getAttributes();
805         params.token = appToken;
806         params.packageName = packageName;
807         params.windowAnimations = win.getWindowStyle().getResourceId(
808                 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
809         params.setTitle("Starting " + packageName);
810 
811         try {
812             WindowManagerImpl wm = (WindowManagerImpl)
813                     context.getSystemService(Context.WINDOW_SERVICE);
814             View view = win.getDecorView();
815 
816             if (win.isFloating()) {
817                 // Whoops, there is no way to display an animation/preview
818                 // of such a thing!  After all that work...  let's skip it.
819                 // (Note that we must do this here because it is in
820                 // getDecorView() where the theme is evaluated...  maybe
821                 // we should peek the floating attribute from the theme
822                 // earlier.)
823                 return null;
824             }
825 
826             if (localLOGV) Log.v(
827                 TAG, "Adding starting window for " + packageName
828                 + " / " + appToken + ": "
829                 + (view.getParent() != null ? view : null));
830 
831             wm.addView(view, params);
832 
833             // Only return the view if it was successfully added to the
834             // window manager... which we can tell by it having a parent.
835             return view.getParent() != null ? view : null;
836         } catch (WindowManagerImpl.BadTokenException e) {
837             // ignore
838             Log.w(TAG, appToken + " already running, starting window not displayed");
839         }
840 
841         return null;
842     }
843 
844     /** {@inheritDoc} */
removeStartingWindow(IBinder appToken, View window)845     public void removeStartingWindow(IBinder appToken, View window) {
846         // RuntimeException e = new RuntimeException();
847         // Log.i(TAG, "remove " + appToken + " " + window, e);
848 
849         if (localLOGV) Log.v(
850             TAG, "Removing starting window for " + appToken + ": " + window);
851 
852         if (window != null) {
853             WindowManagerImpl wm = (WindowManagerImpl) mContext.getSystemService(Context.WINDOW_SERVICE);
854             wm.removeView(window);
855         }
856     }
857 
858     /**
859      * Preflight adding a window to the system.
860      *
861      * Currently enforces that three window types are singletons:
862      * <ul>
863      * <li>STATUS_BAR_TYPE</li>
864      * <li>KEYGUARD_TYPE</li>
865      * </ul>
866      *
867      * @param win The window to be added
868      * @param attrs Information about the window to be added
869      *
870      * @return If ok, WindowManagerImpl.ADD_OKAY.  If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON
871      */
prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs)872     public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
873         switch (attrs.type) {
874             case TYPE_STATUS_BAR:
875                 if (mStatusBar != null) {
876                     return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
877                 }
878                 mStatusBar = win;
879                 break;
880             case TYPE_KEYGUARD:
881                 if (mKeyguard != null) {
882                     return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
883                 }
884                 mKeyguard = win;
885                 break;
886         }
887         return WindowManagerImpl.ADD_OKAY;
888     }
889 
890     /** {@inheritDoc} */
removeWindowLw(WindowState win)891     public void removeWindowLw(WindowState win) {
892         if (mStatusBar == win) {
893             mStatusBar = null;
894         }
895         else if (mKeyguard == win) {
896             mKeyguard = null;
897         }
898     }
899 
900     static final boolean PRINT_ANIM = false;
901 
902     /** {@inheritDoc} */
selectAnimationLw(WindowState win, int transit)903     public int selectAnimationLw(WindowState win, int transit) {
904         if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
905               + ": transit=" + transit);
906         if (transit == TRANSIT_PREVIEW_DONE) {
907             if (win.hasAppShownWindows()) {
908                 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
909                 return com.android.internal.R.anim.app_starting_exit;
910             }
911         }
912 
913         return 0;
914     }
915 
createForceHideEnterAnimation()916     public Animation createForceHideEnterAnimation() {
917         return AnimationUtils.loadAnimation(mContext,
918                 com.android.internal.R.anim.lock_screen_behind_enter);
919     }
920 
getPhoneInterface()921     static ITelephony getPhoneInterface() {
922         return ITelephony.Stub.asInterface(ServiceManager.checkService(Context.TELEPHONY_SERVICE));
923     }
924 
getAudioInterface()925     static IAudioService getAudioInterface() {
926         return IAudioService.Stub.asInterface(ServiceManager.checkService(Context.AUDIO_SERVICE));
927     }
928 
keyguardOn()929     boolean keyguardOn() {
930         return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
931     }
932 
933     private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
934             WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
935             WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
936         };
937 
938     /** {@inheritDoc} */
interceptKeyTi(WindowState win, int code, int metaKeys, boolean down, int repeatCount, int flags)939     public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down,
940             int repeatCount, int flags) {
941         boolean keyguardOn = keyguardOn();
942 
943         if (false) {
944             Log.d(TAG, "interceptKeyTi code=" + code + " down=" + down + " repeatCount="
945                     + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
946         }
947 
948         // Clear a pending HOME longpress if the user releases Home
949         // TODO: This could probably be inside the next bit of logic, but that code
950         // turned out to be a bit fragile so I'm doing it here explicitly, for now.
951         if ((code == KeyEvent.KEYCODE_HOME) && !down) {
952             mHandler.removeCallbacks(mHomeLongPress);
953         }
954 
955         // If the HOME button is currently being held, then we do special
956         // chording with it.
957         if (mHomePressed) {
958 
959             // If we have released the home key, and didn't do anything else
960             // while it was pressed, then it is time to go home!
961             if (code == KeyEvent.KEYCODE_HOME) {
962                 if (!down) {
963                     mHomePressed = false;
964 
965                     if ((flags&KeyEvent.FLAG_CANCELED) == 0) {
966                         // If an incoming call is ringing, HOME is totally disabled.
967                         // (The user is already on the InCallScreen at this point,
968                         // and his ONLY options are to answer or reject the call.)
969                         boolean incomingRinging = false;
970                         try {
971                             ITelephony phoneServ = getPhoneInterface();
972                             if (phoneServ != null) {
973                                 incomingRinging = phoneServ.isRinging();
974                             } else {
975                                 Log.w(TAG, "Unable to find ITelephony interface");
976                             }
977                         } catch (RemoteException ex) {
978                             Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
979                         }
980 
981                         if (incomingRinging) {
982                             Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
983                         } else {
984                             launchHomeFromHotKey();
985                         }
986                     } else {
987                         Log.i(TAG, "Ignoring HOME; event canceled.");
988                     }
989                 }
990             }
991 
992             return true;
993         }
994 
995         // First we always handle the home key here, so applications
996         // can never break it, although if keyguard is on, we do let
997         // it handle it, because that gives us the correct 5 second
998         // timeout.
999         if (code == KeyEvent.KEYCODE_HOME) {
1000 
1001             // If a system window has focus, then it doesn't make sense
1002             // right now to interact with applications.
1003             WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
1004             if (attrs != null) {
1005                 final int type = attrs.type;
1006                 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
1007                         || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
1008                     // the "app" is keyguard, so give it the key
1009                     return false;
1010                 }
1011                 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
1012                 for (int i=0; i<typeCount; i++) {
1013                     if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
1014                         // don't do anything, but also don't pass it to the app
1015                         return true;
1016                     }
1017                 }
1018             }
1019 
1020             if (down && repeatCount == 0) {
1021                 if (!keyguardOn) {
1022                     mHandler.postDelayed(mHomeLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
1023                 }
1024                 mHomePressed = true;
1025             }
1026             return true;
1027         } else if (code == KeyEvent.KEYCODE_MENU) {
1028             // Hijack modified menu keys for debugging features
1029             final int chordBug = KeyEvent.META_SHIFT_ON;
1030 
1031             if (down && repeatCount == 0) {
1032                 if (mEnableShiftMenuBugReports && (metaKeys & chordBug) == chordBug) {
1033                     Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
1034                     mContext.sendOrderedBroadcast(intent, null);
1035                     return true;
1036                 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
1037                         (metaKeys & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
1038                     Intent service = new Intent();
1039                     service.setClassName(mContext, "com.android.server.LoadAverageService");
1040                     ContentResolver res = mContext.getContentResolver();
1041                     boolean shown = Settings.System.getInt(
1042                             res, Settings.System.SHOW_PROCESSES, 0) != 0;
1043                     if (!shown) {
1044                         mContext.startService(service);
1045                     } else {
1046                         mContext.stopService(service);
1047                     }
1048                     Settings.System.putInt(
1049                             res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
1050                     return true;
1051                 }
1052             }
1053         } else if (code == KeyEvent.KEYCODE_NOTIFICATION) {
1054             if (down) {
1055                 // this key doesn't exist on current hardware, but if a device
1056                 // didn't have a touchscreen, it would want one of these to open
1057                 // the status bar.
1058                 IStatusBar sbs = IStatusBar.Stub.asInterface(ServiceManager.getService("statusbar"));
1059                 if (sbs != null) {
1060                     try {
1061                         sbs.toggle();
1062                     } catch (RemoteException e) {
1063                         // we're screwed anyway, since it's in this process
1064                         throw new RuntimeException(e);
1065                     }
1066                 }
1067             }
1068             return true;
1069         } else if (code == KeyEvent.KEYCODE_SEARCH) {
1070             if (down) {
1071                 if (repeatCount == 0) {
1072                     mSearchKeyPressed = true;
1073                 }
1074             } else {
1075                 mSearchKeyPressed = false;
1076 
1077                 if (mConsumeSearchKeyUp) {
1078                     // Consume the up-event
1079                     mConsumeSearchKeyUp = false;
1080                     return true;
1081                 }
1082             }
1083         }
1084 
1085         // Shortcuts are invoked through Search+key, so intercept those here
1086         if (mSearchKeyPressed) {
1087             if (down && repeatCount == 0 && !keyguardOn) {
1088                 Intent shortcutIntent = mShortcutManager.getIntent(code, metaKeys);
1089                 if (shortcutIntent != null) {
1090                     shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1091                     mContext.startActivity(shortcutIntent);
1092 
1093                     /*
1094                      * We launched an app, so the up-event of the search key
1095                      * should be consumed
1096                      */
1097                     mConsumeSearchKeyUp = true;
1098                     return true;
1099                 }
1100             }
1101         }
1102 
1103         return false;
1104     }
1105 
1106     /**
1107      * A home key -> launch home action was detected.  Take the appropriate action
1108      * given the situation with the keyguard.
1109      */
launchHomeFromHotKey()1110     void launchHomeFromHotKey() {
1111         if (!mHideLockScreen && mKeyguardMediator.isShowing()) {
1112             // don't launch home if keyguard showing
1113         } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
1114             // when in keyguard restricted mode, must first verify unlock
1115             // before launching home
1116             mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
1117                 public void onKeyguardExitResult(boolean success) {
1118                     if (success) {
1119                         try {
1120                             ActivityManagerNative.getDefault().stopAppSwitches();
1121                         } catch (RemoteException e) {
1122                         }
1123                         sendCloseSystemWindows();
1124                         startDockOrHome();
1125                     }
1126                 }
1127             });
1128         } else {
1129             // no keyguard stuff to worry about, just launch home!
1130             try {
1131                 ActivityManagerNative.getDefault().stopAppSwitches();
1132             } catch (RemoteException e) {
1133             }
1134             sendCloseSystemWindows();
1135             startDockOrHome();
1136         }
1137     }
1138 
getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset)1139     public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
1140         final int fl = attrs.flags;
1141 
1142         if ((fl &
1143                 (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
1144                 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
1145             contentInset.set(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom);
1146         } else {
1147             contentInset.setEmpty();
1148         }
1149     }
1150 
1151     /** {@inheritDoc} */
beginLayoutLw(int displayWidth, int displayHeight)1152     public void beginLayoutLw(int displayWidth, int displayHeight) {
1153         mW = displayWidth;
1154         mH = displayHeight;
1155         mDockLeft = mContentLeft = mCurLeft = 0;
1156         mDockTop = mContentTop = mCurTop = 0;
1157         mDockRight = mContentRight = mCurRight = displayWidth;
1158         mDockBottom = mContentBottom = mCurBottom = displayHeight;
1159         mDockLayer = 0x10000000;
1160 
1161         mTopFullscreenOpaqueWindowState = null;
1162         mForceStatusBar = false;
1163         mHideLockScreen = false;
1164         mDismissKeyguard = false;
1165 
1166         // decide where the status bar goes ahead of time
1167         if (mStatusBar != null) {
1168             final Rect pf = mTmpParentFrame;
1169             final Rect df = mTmpDisplayFrame;
1170             final Rect vf = mTmpVisibleFrame;
1171             pf.left = df.left = vf.left = 0;
1172             pf.top = df.top = vf.top = 0;
1173             pf.right = df.right = vf.right = displayWidth;
1174             pf.bottom = df.bottom = vf.bottom = displayHeight;
1175 
1176             mStatusBar.computeFrameLw(pf, df, vf, vf);
1177             if (mStatusBar.isVisibleLw()) {
1178                 // If the status bar is hidden, we don't want to cause
1179                 // windows behind it to scroll.
1180                 mDockTop = mContentTop = mCurTop = mStatusBar.getFrameLw().bottom;
1181                 if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockBottom="
1182                         + mDockBottom + " mContentBottom="
1183                         + mContentBottom + " mCurBottom=" + mCurBottom);
1184             }
1185         }
1186     }
1187 
setAttachedWindowFrames(WindowState win, int fl, int sim, WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf)1188     void setAttachedWindowFrames(WindowState win, int fl, int sim,
1189             WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
1190         if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
1191             // Here's a special case: if this attached window is a panel that is
1192             // above the dock window, and the window it is attached to is below
1193             // the dock window, then the frames we computed for the window it is
1194             // attached to can not be used because the dock is effectively part
1195             // of the underlying window and the attached window is floating on top
1196             // of the whole thing.  So, we ignore the attached window and explicitly
1197             // compute the frames that would be appropriate without the dock.
1198             df.left = cf.left = vf.left = mDockLeft;
1199             df.top = cf.top = vf.top = mDockTop;
1200             df.right = cf.right = vf.right = mDockRight;
1201             df.bottom = cf.bottom = vf.bottom = mDockBottom;
1202         } else {
1203             // The effective display frame of the attached window depends on
1204             // whether it is taking care of insetting its content.  If not,
1205             // we need to use the parent's content frame so that the entire
1206             // window is positioned within that content.  Otherwise we can use
1207             // the display frame and let the attached window take care of
1208             // positioning its content appropriately.
1209             if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
1210                 cf.set(attached.getDisplayFrameLw());
1211             } else {
1212                 // If the window is resizing, then we want to base the content
1213                 // frame on our attached content frame to resize...  however,
1214                 // things can be tricky if the attached window is NOT in resize
1215                 // mode, in which case its content frame will be larger.
1216                 // Ungh.  So to deal with that, make sure the content frame
1217                 // we end up using is not covering the IM dock.
1218                 cf.set(attached.getContentFrameLw());
1219                 if (attached.getSurfaceLayer() < mDockLayer) {
1220                     if (cf.left < mContentLeft) cf.left = mContentLeft;
1221                     if (cf.top < mContentTop) cf.top = mContentTop;
1222                     if (cf.right > mContentRight) cf.right = mContentRight;
1223                     if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
1224                 }
1225             }
1226             df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
1227             vf.set(attached.getVisibleFrameLw());
1228         }
1229         // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
1230         // window should be positioned relative to its parent or the entire
1231         // screen.
1232         pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
1233                 ? attached.getFrameLw() : df);
1234     }
1235 
1236     /** {@inheritDoc} */
layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs, WindowState attached)1237     public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
1238             WindowState attached) {
1239         // we've already done the status bar
1240         if (win == mStatusBar) {
1241             return;
1242         }
1243 
1244         if (false) {
1245             if ("com.google.android.youtube".equals(attrs.packageName)
1246                     && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
1247                 Log.i(TAG, "GOTCHA!");
1248             }
1249         }
1250 
1251         final int fl = attrs.flags;
1252         final int sim = attrs.softInputMode;
1253 
1254         final Rect pf = mTmpParentFrame;
1255         final Rect df = mTmpDisplayFrame;
1256         final Rect cf = mTmpContentFrame;
1257         final Rect vf = mTmpVisibleFrame;
1258 
1259         if (attrs.type == TYPE_INPUT_METHOD) {
1260             pf.left = df.left = cf.left = vf.left = mDockLeft;
1261             pf.top = df.top = cf.top = vf.top = mDockTop;
1262             pf.right = df.right = cf.right = vf.right = mDockRight;
1263             pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
1264             // IM dock windows always go to the bottom of the screen.
1265             attrs.gravity = Gravity.BOTTOM;
1266             mDockLayer = win.getSurfaceLayer();
1267         } else {
1268             if ((fl &
1269                     (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
1270                     == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
1271                 // This is the case for a normal activity window: we want it
1272                 // to cover all of the screen space, and it can take care of
1273                 // moving its contents to account for screen decorations that
1274                 // intrude into that space.
1275                 if (attached != null) {
1276                     // If this window is attached to another, our display
1277                     // frame is the same as the one we are attached to.
1278                     setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
1279                 } else {
1280                     pf.left = df.left = 0;
1281                     pf.top = df.top = 0;
1282                     pf.right = df.right = mW;
1283                     pf.bottom = df.bottom = mH;
1284                     if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
1285                         cf.left = mDockLeft;
1286                         cf.top = mDockTop;
1287                         cf.right = mDockRight;
1288                         cf.bottom = mDockBottom;
1289                     } else {
1290                         cf.left = mContentLeft;
1291                         cf.top = mContentTop;
1292                         cf.right = mContentRight;
1293                         cf.bottom = mContentBottom;
1294                     }
1295                     vf.left = mCurLeft;
1296                     vf.top = mCurTop;
1297                     vf.right = mCurRight;
1298                     vf.bottom = mCurBottom;
1299                 }
1300             } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
1301                 // A window that has requested to fill the entire screen just
1302                 // gets everything, period.
1303                 pf.left = df.left = cf.left = 0;
1304                 pf.top = df.top = cf.top = 0;
1305                 pf.right = df.right = cf.right = mW;
1306                 pf.bottom = df.bottom = cf.bottom = mH;
1307                 vf.left = mCurLeft;
1308                 vf.top = mCurTop;
1309                 vf.right = mCurRight;
1310                 vf.bottom = mCurBottom;
1311             } else if (attached != null) {
1312                 // A child window should be placed inside of the same visible
1313                 // frame that its parent had.
1314                 setAttachedWindowFrames(win, fl, sim, attached, false, pf, df, cf, vf);
1315             } else {
1316                 // Otherwise, a normal window must be placed inside the content
1317                 // of all screen decorations.
1318                 pf.left = mContentLeft;
1319                 pf.top = mContentTop;
1320                 pf.right = mContentRight;
1321                 pf.bottom = mContentBottom;
1322                 if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
1323                     df.left = cf.left = mDockLeft;
1324                     df.top = cf.top = mDockTop;
1325                     df.right = cf.right = mDockRight;
1326                     df.bottom = cf.bottom = mDockBottom;
1327                 } else {
1328                     df.left = cf.left = mContentLeft;
1329                     df.top = cf.top = mContentTop;
1330                     df.right = cf.right = mContentRight;
1331                     df.bottom = cf.bottom = mContentBottom;
1332                 }
1333                 vf.left = mCurLeft;
1334                 vf.top = mCurTop;
1335                 vf.right = mCurRight;
1336                 vf.bottom = mCurBottom;
1337             }
1338         }
1339 
1340         if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
1341             df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
1342             df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
1343         }
1344 
1345         if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
1346                 + ": sim=#" + Integer.toHexString(sim)
1347                 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
1348                 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
1349 
1350         if (false) {
1351             if ("com.google.android.youtube".equals(attrs.packageName)
1352                     && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
1353                 if (true || localLOGV) Log.v(TAG, "Computing frame of " + win +
1354                         ": sim=#" + Integer.toHexString(sim)
1355                         + " pf=" + pf.toShortString() + " df=" + df.toShortString()
1356                         + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
1357             }
1358         }
1359 
1360         win.computeFrameLw(pf, df, cf, vf);
1361 
1362         if (mTopFullscreenOpaqueWindowState == null &&
1363                 win.isVisibleOrBehindKeyguardLw()) {
1364             if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
1365                 mForceStatusBar = true;
1366             }
1367             if (attrs.type >= FIRST_APPLICATION_WINDOW
1368                     && attrs.type <= LAST_APPLICATION_WINDOW
1369                     && win.fillsScreenLw(mW, mH, false, false)) {
1370                 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win);
1371                 mTopFullscreenOpaqueWindowState = win;
1372                 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
1373                     if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
1374                     mHideLockScreen = true;
1375                 }
1376             }
1377             if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
1378                 if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win);
1379                 mDismissKeyguard = true;
1380             }
1381         }
1382 
1383         // Dock windows carve out the bottom of the screen, so normal windows
1384         // can't appear underneath them.
1385         if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
1386             int top = win.getContentFrameLw().top;
1387             top += win.getGivenContentInsetsLw().top;
1388             if (mContentBottom > top) {
1389                 mContentBottom = top;
1390             }
1391             top = win.getVisibleFrameLw().top;
1392             top += win.getGivenVisibleInsetsLw().top;
1393             if (mCurBottom > top) {
1394                 mCurBottom = top;
1395             }
1396             if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom="
1397                     + mDockBottom + " mContentBottom="
1398                     + mContentBottom + " mCurBottom=" + mCurBottom);
1399         }
1400     }
1401 
1402     /** {@inheritDoc} */
finishLayoutLw()1403     public int finishLayoutLw() {
1404         int changes = 0;
1405         boolean hiding = false;
1406         if (mStatusBar != null) {
1407             if (localLOGV) Log.i(TAG, "force=" + mForceStatusBar
1408                     + " top=" + mTopFullscreenOpaqueWindowState);
1409             if (mForceStatusBar) {
1410                 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar");
1411                 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
1412             } else if (mTopFullscreenOpaqueWindowState != null) {
1413                 //Log.i(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
1414                 //        + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
1415                 //Log.i(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs());
1416                 WindowManager.LayoutParams lp =
1417                     mTopFullscreenOpaqueWindowState.getAttrs();
1418                 boolean hideStatusBar =
1419                     (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
1420                 if (hideStatusBar) {
1421                     if (DEBUG_LAYOUT) Log.v(TAG, "Hiding status bar");
1422                     if (mStatusBar.hideLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
1423                     hiding = true;
1424                 } else {
1425                     if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar");
1426                     if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
1427                 }
1428             }
1429         }
1430         // Hide the key guard if a visible window explicitly specifies that it wants to be displayed
1431         // when the screen is locked
1432         if (mKeyguard != null) {
1433             if (localLOGV) Log.v(TAG, "finishLayoutLw::mHideKeyguard="+mHideLockScreen);
1434             if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
1435                 if (mKeyguard.hideLw(false)) {
1436                     changes |= FINISH_LAYOUT_REDO_LAYOUT
1437                             | FINISH_LAYOUT_REDO_CONFIG
1438                             | FINISH_LAYOUT_REDO_WALLPAPER;
1439                 }
1440                 if (mKeyguardMediator.isShowing()) {
1441                     mHandler.post(new Runnable() {
1442                         public void run() {
1443                             mKeyguardMediator.keyguardDone(false, false);
1444                         }
1445                     });
1446                 }
1447             } else if (mHideLockScreen) {
1448                 if (mKeyguard.hideLw(false)) {
1449                     mKeyguardMediator.setHidden(true);
1450                     changes |= FINISH_LAYOUT_REDO_LAYOUT
1451                             | FINISH_LAYOUT_REDO_CONFIG
1452                             | FINISH_LAYOUT_REDO_WALLPAPER;
1453                 }
1454             } else {
1455                 if (mKeyguard.showLw(false)) {
1456                     mKeyguardMediator.setHidden(false);
1457                     changes |= FINISH_LAYOUT_REDO_LAYOUT
1458                             | FINISH_LAYOUT_REDO_CONFIG
1459                             | FINISH_LAYOUT_REDO_WALLPAPER;
1460                 }
1461             }
1462         }
1463 
1464         if (changes != 0 && hiding) {
1465             IStatusBar sbs = IStatusBar.Stub.asInterface(ServiceManager.getService("statusbar"));
1466             if (sbs != null) {
1467                 try {
1468                     // Make sure the window shade is hidden.
1469                     sbs.deactivate();
1470                 } catch (RemoteException e) {
1471                 }
1472             }
1473         }
1474 
1475         return changes;
1476     }
1477 
1478     /** {@inheritDoc} */
beginAnimationLw(int displayWidth, int displayHeight)1479     public void beginAnimationLw(int displayWidth, int displayHeight) {
1480     }
1481 
1482     /** {@inheritDoc} */
animatingWindowLw(WindowState win, WindowManager.LayoutParams attrs)1483     public void animatingWindowLw(WindowState win,
1484                                 WindowManager.LayoutParams attrs) {
1485     }
1486 
1487     /** {@inheritDoc} */
finishAnimationLw()1488     public boolean finishAnimationLw() {
1489         return false;
1490     }
1491 
1492     /** {@inheritDoc} */
preprocessInputEventTq(RawInputEvent event)1493     public boolean preprocessInputEventTq(RawInputEvent event) {
1494         switch (event.type) {
1495             case RawInputEvent.EV_SW:
1496                 if (event.keycode == RawInputEvent.SW_LID) {
1497                     // lid changed state
1498                     mLidOpen = event.value == 0;
1499                     boolean awakeNow = mKeyguardMediator.doLidChangeTq(mLidOpen);
1500                     updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
1501                     if (awakeNow) {
1502                         // If the lid opening and we don't have to keep the
1503                         // keyguard up, then we can turn on the screen
1504                         // immediately.
1505                         mKeyguardMediator.pokeWakelock();
1506                     } else if (keyguardIsShowingTq()) {
1507                         if (mLidOpen) {
1508                             // If we are opening the lid and not hiding the
1509                             // keyguard, then we need to have it turn on the
1510                             // screen once it is shown.
1511                             mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
1512                                     KeyEvent.KEYCODE_POWER);
1513                         }
1514                     } else {
1515                         // Light up the keyboard if we are sliding up.
1516                         if (mLidOpen) {
1517                             mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
1518                                     LocalPowerManager.BUTTON_EVENT);
1519                         } else {
1520                             mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
1521                                     LocalPowerManager.OTHER_EVENT);
1522                         }
1523                     }
1524                 }
1525         }
1526         return false;
1527     }
1528 
1529 
1530     /** {@inheritDoc} */
isAppSwitchKeyTqTiLwLi(int keycode)1531     public boolean isAppSwitchKeyTqTiLwLi(int keycode) {
1532         return keycode == KeyEvent.KEYCODE_HOME
1533                 || keycode == KeyEvent.KEYCODE_ENDCALL;
1534     }
1535 
1536     /** {@inheritDoc} */
isMovementKeyTi(int keycode)1537     public boolean isMovementKeyTi(int keycode) {
1538         switch (keycode) {
1539             case KeyEvent.KEYCODE_DPAD_UP:
1540             case KeyEvent.KEYCODE_DPAD_DOWN:
1541             case KeyEvent.KEYCODE_DPAD_LEFT:
1542             case KeyEvent.KEYCODE_DPAD_RIGHT:
1543                 return true;
1544         }
1545         return false;
1546     }
1547 
1548 
1549     /**
1550      * @return Whether a telephone call is in progress right now.
1551      */
isInCall()1552     boolean isInCall() {
1553         final ITelephony phone = getPhoneInterface();
1554         if (phone == null) {
1555             Log.w(TAG, "couldn't get ITelephony reference");
1556             return false;
1557         }
1558         try {
1559             return phone.isOffhook();
1560         } catch (RemoteException e) {
1561             Log.w(TAG, "ITelephony.isOffhhook threw RemoteException " + e);
1562             return false;
1563         }
1564     }
1565 
1566     /**
1567      * @return Whether music is being played right now.
1568      */
isMusicActive()1569     boolean isMusicActive() {
1570         final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
1571         if (am == null) {
1572             Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
1573             return false;
1574         }
1575         return am.isMusicActive();
1576     }
1577 
1578     /**
1579      * Tell the audio service to adjust the volume appropriate to the event.
1580      * @param keycode
1581      */
handleVolumeKey(int stream, int keycode)1582     void handleVolumeKey(int stream, int keycode) {
1583         final IAudioService audio = getAudioInterface();
1584         if (audio == null) {
1585             Log.w(TAG, "handleVolumeKey: couldn't get IAudioService reference");
1586             return;
1587         }
1588         try {
1589             // since audio is playing, we shouldn't have to hold a wake lock
1590             // during the call, but we do it as a precaution for the rare possibility
1591             // that the music stops right before we call this
1592             mBroadcastWakeLock.acquire();
1593             audio.adjustStreamVolume(stream,
1594                 keycode == KeyEvent.KEYCODE_VOLUME_UP
1595                             ? AudioManager.ADJUST_RAISE
1596                             : AudioManager.ADJUST_LOWER,
1597                     0);
1598         } catch (RemoteException e) {
1599             Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e);
1600         } finally {
1601             mBroadcastWakeLock.release();
1602         }
1603     }
1604 
isMediaKey(int code)1605     static boolean isMediaKey(int code) {
1606         if (code == KeyEvent.KEYCODE_HEADSETHOOK ||
1607                 code == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
1608                 code == KeyEvent.KEYCODE_MEDIA_STOP ||
1609                 code == KeyEvent.KEYCODE_MEDIA_NEXT ||
1610                 code == KeyEvent.KEYCODE_MEDIA_PREVIOUS ||
1611                 code == KeyEvent.KEYCODE_MEDIA_PREVIOUS ||
1612                 code == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
1613             return true;
1614         }
1615         return false;
1616     }
1617 
1618     /** {@inheritDoc} */
interceptKeyTq(RawInputEvent event, boolean screenIsOn)1619     public int interceptKeyTq(RawInputEvent event, boolean screenIsOn) {
1620         int result = ACTION_PASS_TO_USER;
1621         final boolean isWakeKey = isWakeKeyTq(event);
1622         final boolean keyguardShowing = keyguardIsShowingTq();
1623 
1624         if (false) {
1625             Log.d(TAG, "interceptKeyTq event=" + event + " keycode=" + event.keycode
1626                   + " screenIsOn=" + screenIsOn + " keyguardShowing=" + keyguardShowing);
1627         }
1628 
1629         if (keyguardShowing) {
1630             if (screenIsOn) {
1631                 // when the screen is on, always give the event to the keyguard
1632                 result |= ACTION_PASS_TO_USER;
1633             } else {
1634                 // otherwise, don't pass it to the user
1635                 result &= ~ACTION_PASS_TO_USER;
1636 
1637                 final boolean isKeyDown =
1638                         (event.type == RawInputEvent.EV_KEY) && (event.value != 0);
1639                 if (isWakeKey && isKeyDown) {
1640 
1641                     // tell the mediator about a wake key, it may decide to
1642                     // turn on the screen depending on whether the key is
1643                     // appropriate.
1644                     if (!mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(event.keycode)
1645                             && (event.keycode == KeyEvent.KEYCODE_VOLUME_DOWN
1646                                 || event.keycode == KeyEvent.KEYCODE_VOLUME_UP)) {
1647                         if (isInCall()) {
1648                             // if the keyguard didn't wake the device, we are in call, and
1649                             // it is a volume key, turn on the screen so that the user
1650                             // can more easily adjust the in call volume.
1651                             mKeyguardMediator.pokeWakelock();
1652                         } else if (isMusicActive()) {
1653                             // when keyguard is showing and screen off, we need
1654                             // to handle the volume key for music here
1655                             handleVolumeKey(AudioManager.STREAM_MUSIC, event.keycode);
1656                         }
1657                     }
1658                 }
1659             }
1660         } else if (!screenIsOn) {
1661             // If we are in-call with screen off and keyguard is not showing,
1662             // then handle the volume key ourselves.
1663             // This is necessary because the phone app will disable the keyguard
1664             // when the proximity sensor is in use.
1665             if (isInCall() && event.type == RawInputEvent.EV_KEY &&
1666                      (event.keycode == KeyEvent.KEYCODE_VOLUME_DOWN
1667                                 || event.keycode == KeyEvent.KEYCODE_VOLUME_UP)) {
1668                 result &= ~ACTION_PASS_TO_USER;
1669                 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, event.keycode);
1670             }
1671             if (isWakeKey) {
1672                 // a wake key has a sole purpose of waking the device; don't pass
1673                 // it to the user
1674                 result |= ACTION_POKE_USER_ACTIVITY;
1675                 result &= ~ACTION_PASS_TO_USER;
1676             }
1677         }
1678 
1679         int type = event.type;
1680         int code = event.keycode;
1681         boolean down = event.value != 0;
1682 
1683         if (type == RawInputEvent.EV_KEY) {
1684             if (code == KeyEvent.KEYCODE_ENDCALL
1685                     || code == KeyEvent.KEYCODE_POWER) {
1686                 if (down) {
1687                     boolean handled = false;
1688                     // key repeats are generated by the window manager, and we don't see them
1689                     // here, so unless the driver is doing something it shouldn't be, we know
1690                     // this is the real press event.
1691                     ITelephony phoneServ = getPhoneInterface();
1692                     if (phoneServ != null) {
1693                         try {
1694                             if (code == KeyEvent.KEYCODE_ENDCALL) {
1695                                 handled = phoneServ.endCall();
1696                             } else if (code == KeyEvent.KEYCODE_POWER && phoneServ.isRinging()) {
1697                                 // Pressing power during incoming call should silence the ringer
1698                                 phoneServ.silenceRinger();
1699                                 handled = true;
1700                             }
1701                         } catch (RemoteException ex) {
1702                             Log.w(TAG, "ITelephony threw RemoteException" + ex);
1703                         }
1704                     } else {
1705                         Log.w(TAG, "!!! Unable to find ITelephony interface !!!");
1706                     }
1707                     // power button should turn off screen in addition to hanging up the phone
1708                     if ((handled && code != KeyEvent.KEYCODE_POWER) || !screenIsOn) {
1709                         mShouldTurnOffOnKeyUp = false;
1710                     } else {
1711                         // only try to turn off the screen if we didn't already hang up
1712                         mShouldTurnOffOnKeyUp = true;
1713                         mHandler.postDelayed(mPowerLongPress,
1714                                 ViewConfiguration.getGlobalActionKeyTimeout());
1715                         result &= ~ACTION_PASS_TO_USER;
1716                     }
1717                 } else {
1718                     mHandler.removeCallbacks(mPowerLongPress);
1719                     if (mShouldTurnOffOnKeyUp) {
1720                         mShouldTurnOffOnKeyUp = false;
1721                         boolean gohome = (mEndcallBehavior & ENDCALL_HOME) != 0;
1722                         boolean sleeps = (mEndcallBehavior & ENDCALL_SLEEPS) != 0;
1723                         if (keyguardShowing
1724                                 || (sleeps && !gohome)
1725                                 || (gohome && !goHome() && sleeps)) {
1726                             // they must already be on the keyguad or home screen,
1727                             // go to sleep instead
1728                             Log.d(TAG, "I'm tired mEndcallBehavior=0x"
1729                                     + Integer.toHexString(mEndcallBehavior));
1730                             result &= ~ACTION_POKE_USER_ACTIVITY;
1731                             result |= ACTION_GO_TO_SLEEP;
1732                         }
1733                         result &= ~ACTION_PASS_TO_USER;
1734                     }
1735                 }
1736             } else if (isMediaKey(code)) {
1737                 // This key needs to be handled even if the screen is off.
1738                 // If others need to be handled while it's off, this is a reasonable
1739                 // pattern to follow.
1740                 if ((result & ACTION_PASS_TO_USER) == 0) {
1741                     // Only do this if we would otherwise not pass it to the user. In that
1742                     // case, the PhoneWindow class will do the same thing, except it will
1743                     // only do it if the showing app doesn't process the key on its own.
1744                     KeyEvent keyEvent = new KeyEvent(event.when, event.when,
1745                             down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP,
1746                             code, 0);
1747                     mBroadcastWakeLock.acquire();
1748                     mHandler.post(new PassHeadsetKey(keyEvent));
1749                 }
1750             } else if (code == KeyEvent.KEYCODE_CALL) {
1751                 // If an incoming call is ringing, answer it!
1752                 // (We handle this key here, rather than in the InCallScreen, to make
1753                 // sure we'll respond to the key even if the InCallScreen hasn't come to
1754                 // the foreground yet.)
1755 
1756                 // We answer the call on the DOWN event, to agree with
1757                 // the "fallback" behavior in the InCallScreen.
1758                 if (down) {
1759                     try {
1760                         ITelephony phoneServ = getPhoneInterface();
1761                         if (phoneServ != null) {
1762                             if (phoneServ.isRinging()) {
1763                                 Log.i(TAG, "interceptKeyTq:"
1764                                       + " CALL key-down while ringing: Answer the call!");
1765                                 phoneServ.answerRingingCall();
1766 
1767                                 // And *don't* pass this key thru to the current activity
1768                                 // (which is presumably the InCallScreen.)
1769                                 result &= ~ACTION_PASS_TO_USER;
1770                             }
1771                         } else {
1772                             Log.w(TAG, "CALL button: Unable to find ITelephony interface");
1773                         }
1774                     } catch (RemoteException ex) {
1775                         Log.w(TAG, "CALL button: RemoteException from getPhoneInterface()", ex);
1776                     }
1777                 }
1778             } else if ((code == KeyEvent.KEYCODE_VOLUME_UP)
1779                        || (code == KeyEvent.KEYCODE_VOLUME_DOWN)) {
1780                 // If an incoming call is ringing, either VOLUME key means
1781                 // "silence ringer".  We handle these keys here, rather than
1782                 // in the InCallScreen, to make sure we'll respond to them
1783                 // even if the InCallScreen hasn't come to the foreground yet.
1784 
1785                 // Look for the DOWN event here, to agree with the "fallback"
1786                 // behavior in the InCallScreen.
1787                 if (down) {
1788                     try {
1789                         ITelephony phoneServ = getPhoneInterface();
1790                         if (phoneServ != null) {
1791                             if (phoneServ.isRinging()) {
1792                                 Log.i(TAG, "interceptKeyTq:"
1793                                       + " VOLUME key-down while ringing: Silence ringer!");
1794                                 // Silence the ringer.  (It's safe to call this
1795                                 // even if the ringer has already been silenced.)
1796                                 phoneServ.silenceRinger();
1797 
1798                                 // And *don't* pass this key thru to the current activity
1799                                 // (which is probably the InCallScreen.)
1800                                 result &= ~ACTION_PASS_TO_USER;
1801                             }
1802                         } else {
1803                             Log.w(TAG, "VOLUME button: Unable to find ITelephony interface");
1804                         }
1805                     } catch (RemoteException ex) {
1806                         Log.w(TAG, "VOLUME button: RemoteException from getPhoneInterface()", ex);
1807                     }
1808                 }
1809             }
1810         }
1811 
1812         return result;
1813     }
1814 
1815     class PassHeadsetKey implements Runnable {
1816         KeyEvent mKeyEvent;
1817 
PassHeadsetKey(KeyEvent keyEvent)1818         PassHeadsetKey(KeyEvent keyEvent) {
1819             mKeyEvent = keyEvent;
1820         }
1821 
run()1822         public void run() {
1823             if (ActivityManagerNative.isSystemReady()) {
1824                 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
1825                 intent.putExtra(Intent.EXTRA_KEY_EVENT, mKeyEvent);
1826                 mContext.sendOrderedBroadcast(intent, null, mBroadcastDone,
1827                         mHandler, Activity.RESULT_OK, null, null);
1828             }
1829         }
1830     }
1831 
1832     BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
1833         public void onReceive(Context context, Intent intent) {
1834             mBroadcastWakeLock.release();
1835         }
1836     };
1837 
1838     BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
1839         public void onReceive(Context context, Intent intent) {
1840             updatePlugged(intent);
1841             updateDockKeepingScreenOn();
1842         }
1843     };
1844 
1845     BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
1846         public void onReceive(Context context, Intent intent) {
1847             mDockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
1848                     Intent.EXTRA_DOCK_STATE_UNDOCKED);
1849             boolean watchBattery = mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
1850             if (watchBattery != mRegisteredBatteryReceiver) {
1851                 mRegisteredBatteryReceiver = watchBattery;
1852                 if (watchBattery) {
1853                     updatePlugged(mContext.registerReceiver(mBatteryReceiver,
1854                             mBatteryStatusFilter));
1855                 } else {
1856                     mContext.unregisterReceiver(mBatteryReceiver);
1857                 }
1858             }
1859             updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
1860             updateDockKeepingScreenOn();
1861             updateOrientationListenerLp();
1862         }
1863     };
1864 
1865     /** {@inheritDoc} */
isWakeRelMovementTq(int device, int classes, RawInputEvent event)1866     public boolean isWakeRelMovementTq(int device, int classes,
1867             RawInputEvent event) {
1868         // if it's tagged with one of the wake bits, it wakes up the device
1869         return ((event.flags & (FLAG_WAKE | FLAG_WAKE_DROPPED)) != 0);
1870     }
1871 
1872     /** {@inheritDoc} */
isWakeAbsMovementTq(int device, int classes, RawInputEvent event)1873     public boolean isWakeAbsMovementTq(int device, int classes,
1874             RawInputEvent event) {
1875         // if it's tagged with one of the wake bits, it wakes up the device
1876         return ((event.flags & (FLAG_WAKE | FLAG_WAKE_DROPPED)) != 0);
1877     }
1878 
1879     /**
1880      * Given the current state of the world, should this key wake up the device?
1881      */
isWakeKeyTq(RawInputEvent event)1882     protected boolean isWakeKeyTq(RawInputEvent event) {
1883         // There are not key maps for trackball devices, but we'd still
1884         // like to have pressing it wake the device up, so force it here.
1885         int keycode = event.keycode;
1886         int flags = event.flags;
1887         if (keycode == RawInputEvent.BTN_MOUSE) {
1888             flags |= WindowManagerPolicy.FLAG_WAKE;
1889         }
1890         return (flags
1891                 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
1892     }
1893 
1894     /** {@inheritDoc} */
screenTurnedOff(int why)1895     public void screenTurnedOff(int why) {
1896         EventLog.writeEvent(70000, 0);
1897         mKeyguardMediator.onScreenTurnedOff(why);
1898         synchronized (mLock) {
1899             mScreenOn = false;
1900             updateOrientationListenerLp();
1901         }
1902     }
1903 
1904     /** {@inheritDoc} */
screenTurnedOn()1905     public void screenTurnedOn() {
1906         EventLog.writeEvent(70000, 1);
1907         mKeyguardMediator.onScreenTurnedOn();
1908         synchronized (mLock) {
1909             mScreenOn = true;
1910             updateOrientationListenerLp();
1911         }
1912     }
1913 
1914     /** {@inheritDoc} */
enableKeyguard(boolean enabled)1915     public void enableKeyguard(boolean enabled) {
1916         mKeyguardMediator.setKeyguardEnabled(enabled);
1917     }
1918 
1919     /** {@inheritDoc} */
exitKeyguardSecurely(OnKeyguardExitResult callback)1920     public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
1921         mKeyguardMediator.verifyUnlock(callback);
1922     }
1923 
1924     /** {@inheritDoc} */
keyguardIsShowingTq()1925     public boolean keyguardIsShowingTq() {
1926         return mKeyguardMediator.isShowing();
1927     }
1928 
1929     /** {@inheritDoc} */
inKeyguardRestrictedKeyInputMode()1930     public boolean inKeyguardRestrictedKeyInputMode() {
1931         return mKeyguardMediator.isInputRestricted();
1932     }
1933 
sendCloseSystemWindows()1934     void sendCloseSystemWindows() {
1935         sendCloseSystemWindows(mContext, null);
1936     }
1937 
sendCloseSystemWindows(String reason)1938     void sendCloseSystemWindows(String reason) {
1939         sendCloseSystemWindows(mContext, reason);
1940     }
1941 
sendCloseSystemWindows(Context context, String reason)1942     static void sendCloseSystemWindows(Context context, String reason) {
1943         if (ActivityManagerNative.isSystemReady()) {
1944             try {
1945                 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
1946             } catch (RemoteException e) {
1947             }
1948         }
1949     }
1950 
rotationForOrientationLw(int orientation, int lastRotation, boolean displayEnabled)1951     public int rotationForOrientationLw(int orientation, int lastRotation,
1952             boolean displayEnabled) {
1953 
1954         if (mPortraitRotation < 0) {
1955             // Initialize the rotation angles for each orientation once.
1956             Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
1957                     .getDefaultDisplay();
1958             if (d.getWidth() > d.getHeight()) {
1959                 mPortraitRotation = Surface.ROTATION_90;
1960                 mLandscapeRotation = Surface.ROTATION_0;
1961             } else {
1962                 mPortraitRotation = Surface.ROTATION_0;
1963                 mLandscapeRotation = Surface.ROTATION_90;
1964             }
1965         }
1966 
1967         synchronized (mLock) {
1968             switch (orientation) {
1969                 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
1970                     //always return landscape if orientation set to landscape
1971                     return mLandscapeRotation;
1972                 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
1973                     //always return portrait if orientation set to portrait
1974                     return mPortraitRotation;
1975             }
1976             // case for nosensor meaning ignore sensor and consider only lid
1977             // or orientation sensor disabled
1978             //or case.unspecified
1979             if (mLidOpen) {
1980                 return mLidOpenRotation;
1981             } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
1982                 return mCarDockRotation;
1983             } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
1984                 return mDeskDockRotation;
1985             } else {
1986                 if (useSensorForOrientationLp(orientation)) {
1987                     // If the user has enabled auto rotation by default, do it.
1988                     int curRotation = mOrientationListener.getCurrentRotation();
1989                     return curRotation >= 0 ? curRotation : lastRotation;
1990                 }
1991                 return Surface.ROTATION_0;
1992             }
1993         }
1994     }
1995 
detectSafeMode()1996     public boolean detectSafeMode() {
1997         try {
1998             int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);
1999             int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S);
2000             int dpadState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER);
2001             int trackballState = mWindowManager.getScancodeState(RawInputEvent.BTN_MOUSE);
2002             mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0;
2003             performHapticFeedbackLw(null, mSafeMode
2004                     ? HapticFeedbackConstants.SAFE_MODE_ENABLED
2005                     : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
2006             if (mSafeMode) {
2007                 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
2008                         + " dpad=" + dpadState + " trackball=" + trackballState + ")");
2009             } else {
2010                 Log.i(TAG, "SAFE MODE not enabled");
2011             }
2012             return mSafeMode;
2013         } catch (RemoteException e) {
2014             // Doom! (it's also local)
2015             throw new RuntimeException("window manager dead");
2016         }
2017     }
2018 
getLongIntArray(Resources r, int resid)2019     static long[] getLongIntArray(Resources r, int resid) {
2020         int[] ar = r.getIntArray(resid);
2021         if (ar == null) {
2022             return null;
2023         }
2024         long[] out = new long[ar.length];
2025         for (int i=0; i<ar.length; i++) {
2026             out[i] = ar[i];
2027         }
2028         return out;
2029     }
2030 
2031     /** {@inheritDoc} */
systemReady()2032     public void systemReady() {
2033         // tell the keyguard
2034         mKeyguardMediator.onSystemReady();
2035         android.os.SystemProperties.set("dev.bootcomplete", "1");
2036         synchronized (mLock) {
2037             updateOrientationListenerLp();
2038         }
2039     }
2040 
2041 
2042     /** {@inheritDoc} */
enableScreenAfterBoot()2043     public void enableScreenAfterBoot() {
2044         readLidState();
2045         updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
2046     }
2047 
updateDockKeepingScreenOn()2048     void updateDockKeepingScreenOn() {
2049         if (mPlugged != 0) {
2050             if (localLOGV) Log.v(TAG, "Update: mDockState=" + mDockState
2051                     + " mPlugged=" + mPlugged
2052                     + " mCarDockKeepsScreenOn" + mCarDockKeepsScreenOn
2053                     + " mDeskDockKeepsScreenOn" + mDeskDockKeepsScreenOn);
2054             if (mDockState == Intent.EXTRA_DOCK_STATE_CAR
2055                     && (mPlugged&mCarDockKeepsScreenOn) != 0) {
2056                 if (!mDockWakeLock.isHeld()) {
2057                     mDockWakeLock.acquire();
2058                 }
2059                 return;
2060             } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK
2061                     && (mPlugged&mDeskDockKeepsScreenOn) != 0) {
2062                 if (!mDockWakeLock.isHeld()) {
2063                     mDockWakeLock.acquire();
2064                 }
2065                 return;
2066             }
2067         }
2068 
2069         if (mDockWakeLock.isHeld()) {
2070             mDockWakeLock.release();
2071         }
2072     }
2073 
updateRotation(int animFlags)2074     void updateRotation(int animFlags) {
2075         mPowerManager.setKeyboardVisibility(mLidOpen);
2076         int rotation = Surface.ROTATION_0;
2077         if (mLidOpen) {
2078             rotation = mLidOpenRotation;
2079         } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
2080             rotation = mCarDockRotation;
2081         } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
2082             rotation = mDeskDockRotation;
2083         }
2084         //if lid is closed orientation will be portrait
2085         try {
2086             //set orientation on WindowManager
2087             mWindowManager.setRotation(rotation, true,
2088                     mFancyRotationAnimation | animFlags);
2089         } catch (RemoteException e) {
2090             // Ignore
2091         }
2092     }
2093 
2094     /**
2095      * Return an Intent to launch the currently active dock as home.  Returns
2096      * null if the standard home should be launched.
2097      * @return
2098      */
createHomeDockIntent()2099     Intent createHomeDockIntent() {
2100         if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
2101             return null;
2102         }
2103 
2104         Intent intent;
2105         if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
2106             intent = mCarDockIntent;
2107         } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
2108             intent = mDeskDockIntent;
2109         } else {
2110             Log.w(TAG, "Unknown dock state: " + mDockState);
2111             return null;
2112         }
2113 
2114         ActivityInfo ai = intent.resolveActivityInfo(
2115                 mContext.getPackageManager(), PackageManager.GET_META_DATA);
2116         if (ai == null) {
2117             return null;
2118         }
2119 
2120         if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
2121             intent = new Intent(intent);
2122             intent.setClassName(ai.packageName, ai.name);
2123             return intent;
2124         }
2125 
2126         return null;
2127     }
2128 
startDockOrHome()2129     void startDockOrHome() {
2130         Intent dock = createHomeDockIntent();
2131         if (dock != null) {
2132             try {
2133                 mContext.startActivity(dock);
2134                 return;
2135             } catch (ActivityNotFoundException e) {
2136             }
2137         }
2138         mContext.startActivity(mHomeIntent);
2139     }
2140 
2141     /**
2142      * goes to the home screen
2143      * @return whether it did anything
2144      */
goHome()2145     boolean goHome() {
2146         if (false) {
2147             // This code always brings home to the front.
2148             try {
2149                 ActivityManagerNative.getDefault().stopAppSwitches();
2150             } catch (RemoteException e) {
2151             }
2152             sendCloseSystemWindows();
2153             startDockOrHome();
2154         } else {
2155             // This code brings home to the front or, if it is already
2156             // at the front, puts the device to sleep.
2157             try {
2158                 ActivityManagerNative.getDefault().stopAppSwitches();
2159                 sendCloseSystemWindows();
2160                 Intent dock = createHomeDockIntent();
2161                 if (dock != null) {
2162                     int result = ActivityManagerNative.getDefault()
2163                             .startActivity(null, dock,
2164                                     dock.resolveTypeIfNeeded(mContext.getContentResolver()),
2165                                     null, 0, null, null, 0, true /* onlyIfNeeded*/, false);
2166                     if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
2167                         return false;
2168                     }
2169                 }
2170                 int result = ActivityManagerNative.getDefault()
2171                         .startActivity(null, mHomeIntent,
2172                                 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
2173                                 null, 0, null, null, 0, true /* onlyIfNeeded*/, false);
2174                 if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
2175                     return false;
2176                 }
2177             } catch (RemoteException ex) {
2178                 // bummer, the activity manager, which is in this process, is dead
2179             }
2180         }
2181         return true;
2182     }
2183 
setCurrentOrientationLw(int newOrientation)2184     public void setCurrentOrientationLw(int newOrientation) {
2185         synchronized (mLock) {
2186             if (newOrientation != mCurrentAppOrientation) {
2187                 mCurrentAppOrientation = newOrientation;
2188                 updateOrientationListenerLp();
2189             }
2190         }
2191     }
2192 
performHapticFeedbackLw(WindowState win, int effectId, boolean always)2193     public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
2194         final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
2195                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
2196         if (!always && (hapticsDisabled || mKeyguardMediator.isShowing())) {
2197             return false;
2198         }
2199         switch (effectId) {
2200             case HapticFeedbackConstants.LONG_PRESS:
2201                 mVibrator.vibrate(mLongPressVibePattern, -1);
2202                 return true;
2203             case HapticFeedbackConstants.VIRTUAL_KEY:
2204                 mVibrator.vibrate(mVirtualKeyVibePattern, -1);
2205                 return true;
2206             case HapticFeedbackConstants.SAFE_MODE_DISABLED:
2207                 mVibrator.vibrate(mSafeModeDisabledVibePattern, -1);
2208                 return true;
2209             case HapticFeedbackConstants.SAFE_MODE_ENABLED:
2210                 mVibrator.vibrate(mSafeModeEnabledVibePattern, -1);
2211                 return true;
2212         }
2213         return false;
2214     }
2215 
keyFeedbackFromInput(KeyEvent event)2216     public void keyFeedbackFromInput(KeyEvent event) {
2217         if (event.getAction() == KeyEvent.ACTION_DOWN
2218                 && (event.getFlags()&KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
2219             performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
2220         }
2221     }
2222 
screenOnStoppedLw()2223     public void screenOnStoppedLw() {
2224         if (!mKeyguardMediator.isShowing() && mPowerManager.isScreenOn()) {
2225             long curTime = SystemClock.uptimeMillis();
2226             mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
2227         }
2228     }
2229 
allowKeyRepeat()2230     public boolean allowKeyRepeat() {
2231         // disable key repeat when screen is off
2232         return mScreenOn;
2233     }
2234 }
2235 
2236