blob: ac38d0bb8fbabc43777c1f03e1981f2c06a59863 [file] [log] [blame]
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.policy.impl;
18
19import android.app.Activity;
20import android.app.ActivityManagerNative;
21import android.app.IActivityManager;
Dianne Hackborn78968392010-03-04 20:47:56 -080022import android.app.IUiModeManager;
23import android.app.UiModeManager;
Dianne Hackborn39c2d712009-09-22 11:41:31 -070024import android.content.ActivityNotFoundException;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080025import android.content.BroadcastReceiver;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080026import android.content.ContentResolver;
27import android.content.Context;
28import android.content.Intent;
Mike Lockwood1753f7f2009-08-24 14:49:07 -070029import android.content.IntentFilter;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080030import android.content.pm.ActivityInfo;
31import android.content.pm.PackageManager;
32import android.content.res.Configuration;
33import android.content.res.Resources;
34import android.database.ContentObserver;
Dianne Hackbornc777e072010-02-12 13:07:59 -080035import android.graphics.PixelFormat;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080036import android.graphics.Rect;
Joe Onorato664644d2011-01-23 17:53:23 -080037import android.os.Binder;
Dianne Hackborn247fe742011-01-08 17:25:57 -080038import android.os.Build;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080039import android.os.Handler;
40import android.os.IBinder;
41import android.os.LocalPowerManager;
42import android.os.PowerManager;
43import android.os.RemoteException;
44import android.os.ServiceManager;
45import android.os.SystemClock;
46import android.os.SystemProperties;
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -080047import android.os.UEventObserver;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080048import android.os.Vibrator;
49import android.provider.Settings;
50
Jim Millere6ad1a82010-08-20 19:25:39 -070051import com.android.internal.R;
Joe Onoratod208e702010-10-08 16:22:43 -040052import com.android.internal.app.ShutdownThread;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080053import com.android.internal.policy.PolicyManager;
Joe Onorato0cbda992010-05-02 16:28:15 -070054import com.android.internal.statusbar.IStatusBarService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080055import com.android.internal.telephony.ITelephony;
Jeff Browna41ca772010-08-11 14:46:32 -070056import com.android.internal.view.BaseInputHandler;
Dianne Hackborn6019c9d2010-03-01 21:43:11 -080057import com.android.internal.widget.PointerLocationView;
58
Jeff Brown4d396052010-10-29 21:50:21 -070059import android.telephony.TelephonyManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080060import android.util.Config;
61import android.util.EventLog;
62import android.util.Log;
Jeff Browna41ca772010-08-11 14:46:32 -070063import android.util.Slog;
Mitsuru Oshima831d0d92009-06-16 18:27:18 -070064import android.view.Display;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080065import android.view.Gravity;
66import android.view.HapticFeedbackConstants;
67import android.view.IWindowManager;
Jeff Browna41ca772010-08-11 14:46:32 -070068import android.view.InputChannel;
Jeff Brown4d396052010-10-29 21:50:21 -070069import android.view.InputDevice;
Jeff Browna41ca772010-08-11 14:46:32 -070070import android.view.InputQueue;
71import android.view.InputHandler;
Jeff Brown6b53e8d2010-11-10 16:03:06 -080072import android.view.KeyCharacterMap;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080073import android.view.KeyEvent;
74import android.view.MotionEvent;
75import android.view.WindowOrientationListener;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080076import android.view.Surface;
77import android.view.View;
78import android.view.ViewConfiguration;
79import android.view.Window;
80import android.view.WindowManager;
81import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
82import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
83import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
84import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
85import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
86import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -070087import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Dianne Hackborn39c2d712009-09-22 11:41:31 -070088import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Mike Lockwood28569302010-01-28 11:54:40 -050089import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080090import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
91import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
Dianne Hackborndea3ef72010-10-28 14:24:22 -070092import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080093import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
94import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
Dianne Hackborn5cb8d792009-05-21 17:34:15 -070095import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080096import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
97import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
98import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Christopher Tatea53146c2010-09-07 11:57:52 -070099import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800100import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
101import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
102import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
103import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
104import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
Jeff Brown3b2b3542010-10-15 00:54:27 -0700105import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800106import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
107import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
Joe Onorato29fc2c92010-11-24 10:26:50 -0800108import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800109import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800110import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
111import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
112import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
113import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
114import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
115import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700116import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Jeff Brown83c09682010-12-23 17:50:18 -0800117import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800118import android.view.WindowManagerImpl;
119import android.view.WindowManagerPolicy;
Jeff Brown6f2fba42011-02-19 01:08:02 -0800120import android.view.KeyCharacterMap.FallbackAction;
Dianne Hackborn01ad2f42009-09-24 19:24:56 -0700121import android.view.animation.Animation;
122import android.view.animation.AnimationUtils;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800123import android.media.IAudioService;
124import android.media.AudioManager;
125
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800126import java.io.File;
Dianne Hackbornf99f9c52011-01-12 15:49:25 -0800127import java.io.FileDescriptor;
Joe Onoratodc100302011-01-11 17:07:41 -0800128import java.io.FileReader;
129import java.io.IOException;
Dianne Hackbornf99f9c52011-01-12 15:49:25 -0800130import java.io.PrintWriter;
Dianne Hackborn08743722009-12-21 12:16:51 -0800131import java.util.ArrayList;
132
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800133/**
The Android Open Source Project0727d222009-03-11 12:11:58 -0700134 * WindowManagerPolicy implementation for the Android phone UI. This
135 * introduces a new method suffix, Lp, for an internal lock of the
136 * PhoneWindowManager. This is used to protect some internal state, and
137 * can be acquired with either thw Lw and Li lock held, so has the restrictions
138 * of both of those when held.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800139 */
140public class PhoneWindowManager implements WindowManagerPolicy {
141 static final String TAG = "WindowManager";
142 static final boolean DEBUG = false;
143 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
The Android Open Source Project11267662009-03-18 17:39:47 -0700144 static final boolean DEBUG_LAYOUT = false;
Jeff Brown49ed71d2010-12-06 17:13:33 -0800145 static final boolean DEBUG_FALLBACK = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800146 static final boolean SHOW_STARTING_ANIMATIONS = true;
147 static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
Joe Onoratod208e702010-10-08 16:22:43 -0400148
149 static final int LONG_PRESS_POWER_NOTHING = 0;
150 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
151 static final int LONG_PRESS_POWER_SHUT_OFF = 2;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800152
Joe Onorato46b0d682010-11-22 17:37:27 -0800153 static final int LONG_PRESS_HOME_NOTHING = 0;
154 static final int LONG_PRESS_HOME_RECENT_DIALOG = 1;
155 static final int LONG_PRESS_HOME_RECENT_ACTIVITY = 2;
156
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700157 // wallpaper is at the bottom, though the window manager may move it.
Dianne Hackborn3c3bd442009-08-19 17:09:46 -0700158 static final int WALLPAPER_LAYER = 2;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700159 static final int APPLICATION_LAYER = 2;
160 static final int PHONE_LAYER = 3;
161 static final int SEARCH_BAR_LAYER = 4;
Joe Onorato29fc2c92010-11-24 10:26:50 -0800162 static final int STATUS_BAR_SUB_PANEL_LAYER = 5;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800163 static final int SYSTEM_DIALOG_LAYER = 6;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800164 // toasts and the plugged-in battery thing
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800165 static final int TOAST_LAYER = 7;
166 static final int STATUS_BAR_LAYER = 8;
Joe Onorato29fc2c92010-11-24 10:26:50 -0800167 static final int STATUS_BAR_PANEL_LAYER = 9;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800168 // SIM errors and unlock. Not sure if this really should be in a high layer.
Joe Onorato29fc2c92010-11-24 10:26:50 -0800169 static final int PRIORITY_PHONE_LAYER = 10;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800170 // like the ANR / app crashed dialogs
Joe Onorato29fc2c92010-11-24 10:26:50 -0800171 static final int SYSTEM_ALERT_LAYER = 11;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800172 // system-level error dialogs
Joe Onorato29fc2c92010-11-24 10:26:50 -0800173 static final int SYSTEM_ERROR_LAYER = 12;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800174 // on-screen keyboards and other such input method user interfaces go here.
Joe Onorato29fc2c92010-11-24 10:26:50 -0800175 static final int INPUT_METHOD_LAYER = 13;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800176 // on-screen keyboards and other such input method user interfaces go here.
Joe Onorato29fc2c92010-11-24 10:26:50 -0800177 static final int INPUT_METHOD_DIALOG_LAYER = 14;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800178 // the keyguard; nothing on top of these can take focus, since they are
179 // responsible for power management when displayed.
Joe Onorato29fc2c92010-11-24 10:26:50 -0800180 static final int KEYGUARD_LAYER = 15;
181 static final int KEYGUARD_DIALOG_LAYER = 16;
Christopher Tatea53146c2010-09-07 11:57:52 -0700182 // the drag layer: input for drag-and-drop is associated with this window,
183 // which sits above all other focusable windows
Joe Onorato29fc2c92010-11-24 10:26:50 -0800184 static final int DRAG_LAYER = 17;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800185 // things in here CAN NOT take focus, but are shown on top of everything else.
Joe Onorato29fc2c92010-11-24 10:26:50 -0800186 static final int SYSTEM_OVERLAY_LAYER = 18;
187 static final int SECURE_SYSTEM_OVERLAY_LAYER = 19;
Jeff Brown83c09682010-12-23 17:50:18 -0800188 // the (mouse) pointer layer
189 static final int POINTER_LAYER = 20;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800190
Dianne Hackborn5cb8d792009-05-21 17:34:15 -0700191 static final int APPLICATION_MEDIA_SUBLAYER = -2;
192 static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800193 static final int APPLICATION_PANEL_SUBLAYER = 1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800194 static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800195
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800196 static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
197 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
198 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
Joe Onoratof275f0c2009-11-24 16:11:13 -0500199 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800200
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700201 // Useful scan codes.
202 private static final int SW_LID = 0x00;
203 private static final int BTN_MOUSE = 0x110;
204
The Android Open Source Project0727d222009-03-11 12:11:58 -0700205 final Object mLock = new Object();
206
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800207 Context mContext;
208 IWindowManager mWindowManager;
209 LocalPowerManager mPowerManager;
Joe Onorato93056472010-09-10 10:30:46 -0400210 IStatusBarService mStatusBarService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800211 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
212
Dianne Hackborn181ceb52009-08-27 22:16:40 -0700213 // Vibrator pattern for haptic feedback of a long press.
214 long[] mLongPressVibePattern;
215
216 // Vibrator pattern for haptic feedback of virtual key press.
217 long[] mVirtualKeyVibePattern;
218
Amith Yamasanic33cb712010-02-10 15:21:49 -0800219 // Vibrator pattern for a short vibration.
220 long[] mKeyboardTapVibePattern;
221
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700222 // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
223 long[] mSafeModeDisabledVibePattern;
224
225 // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
226 long[] mSafeModeEnabledVibePattern;
Romain Guy8154cd32010-03-29 14:41:15 -0700227
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800228 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
229 boolean mEnableShiftMenuBugReports = false;
230
231 boolean mSafeMode;
232 WindowState mStatusBar = null;
Daniel Sandler40427442010-07-16 11:44:52 -0400233 boolean mStatusBarCanHide;
Dianne Hackborn08743722009-12-21 12:16:51 -0800234 final ArrayList<WindowState> mStatusBarPanels = new ArrayList<WindowState>();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800235 WindowState mKeyguard = null;
236 KeyguardViewMediator mKeyguardMediator;
237 GlobalActions mGlobalActions;
Jeff Brown4d396052010-10-29 21:50:21 -0700238 volatile boolean mPowerKeyHandled;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800239 RecentApplicationsDialog mRecentAppsDialog;
240 Handler mHandler;
Jeff Brown4aed78b2011-01-14 17:36:55 -0800241
242 private static final int LID_ABSENT = -1;
243 private static final int LID_CLOSED = 0;
244 private static final int LID_OPEN = 1;
245
246 int mLidOpen = LID_ABSENT;
247
Dianne Hackbornc777e072010-02-12 13:07:59 -0800248 boolean mSystemReady;
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800249 boolean mHdmiPlugged;
Dianne Hackborn78968392010-03-04 20:47:56 -0800250 int mUiMode = Configuration.UI_MODE_TYPE_NORMAL;
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700251 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700252 int mLidOpenRotation;
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400253 int mCarDockRotation;
254 int mDeskDockRotation;
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400255
256 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
257 int mUserRotation = Surface.ROTATION_0;
258
Dianne Hackborna1111872010-11-23 20:55:11 -0800259 boolean mAllowAllRotations;
Mike Lockwoode9867d22009-09-20 01:59:02 -0400260 boolean mCarDockEnablesAccelerometer;
261 boolean mDeskDockEnablesAccelerometer;
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700262 int mLidKeyboardAccessibility;
263 int mLidNavigationAccessibility;
Joe Onoratod208e702010-10-08 16:22:43 -0400264 int mLongPressOnPowerBehavior = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800265 boolean mScreenOn = false;
266 boolean mOrientationSensorEnabled = false;
267 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
268 static final int DEFAULT_ACCELEROMETER_ROTATION = 0;
269 int mAccelerometerDefault = DEFAULT_ACCELEROMETER_ROTATION;
270 boolean mHasSoftInput = false;
271
Dianne Hackbornc777e072010-02-12 13:07:59 -0800272 int mPointerLocationMode = 0;
273 PointerLocationView mPointerLocationView = null;
Jeff Browna41ca772010-08-11 14:46:32 -0700274 InputChannel mPointerLocationInputChannel;
Joe Onorato664644d2011-01-23 17:53:23 -0800275
276 // The last window we were told about in focusChanged.
277 WindowState mFocusedWindow;
278
Jeff Browna41ca772010-08-11 14:46:32 -0700279 private final InputHandler mPointerLocationInputHandler = new BaseInputHandler() {
280 @Override
Jeff Brown3915bb82010-11-05 15:02:16 -0700281 public void handleMotion(MotionEvent event, InputQueue.FinishedCallback finishedCallback) {
282 boolean handled = false;
283 try {
284 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
285 synchronized (mLock) {
286 if (mPointerLocationView != null) {
Jeff Brown33bbfd22011-02-24 20:55:35 -0800287 mPointerLocationView.addPointerEvent(event);
Jeff Brown3915bb82010-11-05 15:02:16 -0700288 handled = true;
289 }
290 }
Jeff Brown93ed4e32010-09-23 13:51:48 -0700291 }
Jeff Brown3915bb82010-11-05 15:02:16 -0700292 } finally {
293 finishedCallback.finished(handled);
Jeff Browna41ca772010-08-11 14:46:32 -0700294 }
295 }
296 };
Dianne Hackbornc777e072010-02-12 13:07:59 -0800297
Joe Onorato29fc2c92010-11-24 10:26:50 -0800298 // The current size of the screen; really; (ir)regardless of whether the status
299 // bar can be hidden or not
300 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
301 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
Dianne Hackborn82de1ae2010-10-28 11:28:39 -0700302 // The current size of the screen; these may be different than (0,0)-(dw,dh)
303 // if the status bar can't be hidden; in that case it effectively carves out
304 // that area of the display from all other windows.
Joe Onorato29fc2c92010-11-24 10:26:50 -0800305 int mRestrictedScreenLeft, mRestrictedScreenTop;
306 int mRestrictedScreenWidth, mRestrictedScreenHeight;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800307 // During layout, the current screen borders with all outer decoration
308 // (status bar, input method dock) accounted for.
309 int mCurLeft, mCurTop, mCurRight, mCurBottom;
310 // During layout, the frame in which content should be displayed
311 // to the user, accounting for all screen decoration except for any
312 // space they deem as available for other content. This is usually
313 // the same as mCur*, but may be larger if the screen decor has supplied
314 // content insets.
315 int mContentLeft, mContentTop, mContentRight, mContentBottom;
Dianne Hackborn8e11ef02010-11-18 19:47:42 -0800316 // During layout, the current screen borders along which input method
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800317 // windows are placed.
318 int mDockLeft, mDockTop, mDockRight, mDockBottom;
319 // During layout, the layer at which the doc window is placed.
320 int mDockLayer;
321
322 static final Rect mTmpParentFrame = new Rect();
323 static final Rect mTmpDisplayFrame = new Rect();
324 static final Rect mTmpContentFrame = new Rect();
325 static final Rect mTmpVisibleFrame = new Rect();
326
327 WindowState mTopFullscreenOpaqueWindowState;
Joe Onorato93056472010-09-10 10:30:46 -0400328 boolean mTopIsFullscreen;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800329 boolean mForceStatusBar;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700330 boolean mHideLockScreen;
331 boolean mDismissKeyguard;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800332 boolean mHomePressed;
333 Intent mHomeIntent;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700334 Intent mCarDockIntent;
335 Intent mDeskDockIntent;
Jeff Brown49ed71d2010-12-06 17:13:33 -0800336 int mShortcutKeyPressed = -1;
337 boolean mConsumeShortcutKeyUp;
Daniel Sandlere02d8082010-10-08 15:13:22 -0400338 boolean mShowMenuKey = false; // track FLAG_NEEDS_MENU_KEY on frontmost window
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800339
Mike Lockwood28569302010-01-28 11:54:40 -0500340 // support for activating the lock screen while the screen is on
341 boolean mAllowLockscreenWhenOn;
342 int mLockScreenTimeout;
343 boolean mLockScreenTimerActive;
344
David Brownbaf8d092010-03-08 21:52:59 -0800345 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800346 int mEndcallBehavior;
David Brownbaf8d092010-03-08 21:52:59 -0800347
348 // Behavior of POWER button while in-call and screen on.
349 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
350 int mIncallPowerBehavior;
351
Steve Howarda7bfe6a2010-09-23 16:47:49 -0700352 int mLandscapeRotation = -1; // default landscape rotation
353 int mSeascapeRotation = -1; // "other" landscape rotation, 180 degrees from mLandscapeRotation
Dianne Hackborne5439f22010-10-02 16:53:50 -0700354 int mPortraitRotation = -1; // default portrait rotation
355 int mUpsideDownRotation = -1; // "other" portrait rotation
Mitsuru Oshima831d0d92009-06-16 18:27:18 -0700356
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700357 // Nothing to see here, move along...
358 int mFancyRotationAnimation;
Jim Milleree969aa2010-08-26 20:17:43 -0700359
Joe Onorato46b0d682010-11-22 17:37:27 -0800360 // What we do when the user long presses on home
361 private int mLongPressOnHomeBehavior = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800362
363 ShortcutManager mShortcutManager;
364 PowerManager.WakeLock mBroadcastWakeLock;
365
Jeff Brown49ed71d2010-12-06 17:13:33 -0800366 final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction();
367
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800368 private UEventObserver mHDMIObserver = new UEventObserver() {
369 @Override
370 public void onUEvent(UEventObserver.UEvent event) {
371 setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
372 }
373 };
374
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800375 class SettingsObserver extends ContentObserver {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800376 SettingsObserver(Handler handler) {
377 super(handler);
378 }
David Brownbaf8d092010-03-08 21:52:59 -0800379
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800380 void observe() {
381 ContentResolver resolver = mContext.getContentResolver();
382 resolver.registerContentObserver(Settings.System.getUriFor(
383 Settings.System.END_BUTTON_BEHAVIOR), false, this);
David Brownbaf8d092010-03-08 21:52:59 -0800384 resolver.registerContentObserver(Settings.Secure.getUriFor(
385 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800386 resolver.registerContentObserver(Settings.System.getUriFor(
387 Settings.System.ACCELEROMETER_ROTATION), false, this);
Mike Lockwood28569302010-01-28 11:54:40 -0500388 resolver.registerContentObserver(Settings.System.getUriFor(
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400389 Settings.System.USER_ROTATION), false, this);
390 resolver.registerContentObserver(Settings.System.getUriFor(
Mike Lockwood28569302010-01-28 11:54:40 -0500391 Settings.System.SCREEN_OFF_TIMEOUT), false, this);
Dianne Hackbornc777e072010-02-12 13:07:59 -0800392 resolver.registerContentObserver(Settings.System.getUriFor(
Jeff Brown4519f072011-01-23 13:16:01 -0800393 Settings.System.WINDOW_ORIENTATION_LISTENER_LOG), false, this);
394 resolver.registerContentObserver(Settings.System.getUriFor(
Dianne Hackbornc777e072010-02-12 13:07:59 -0800395 Settings.System.POINTER_LOCATION), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800396 resolver.registerContentObserver(Settings.Secure.getUriFor(
397 Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700398 resolver.registerContentObserver(Settings.System.getUriFor(
399 "fancy_rotation_anim"), false, this);
Dianne Hackbornc777e072010-02-12 13:07:59 -0800400 updateSettings();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800401 }
402
403 @Override public void onChange(boolean selfChange) {
Dianne Hackbornc777e072010-02-12 13:07:59 -0800404 updateSettings();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800405 try {
Dianne Hackborn32bc91d2009-03-27 16:16:03 -0700406 mWindowManager.setRotation(USE_LAST_ROTATION, false,
407 mFancyRotationAnimation);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800408 } catch (RemoteException e) {
409 // Ignore
410 }
411 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800412 }
413
414 class MyOrientationListener extends WindowOrientationListener {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800415 MyOrientationListener(Context context) {
416 super(context);
417 }
418
419 @Override
The Android Open Source Projectd06b0972009-03-13 13:04:23 -0700420 public void onOrientationChanged(int rotation) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800421 // Send updates based on orientation value
Dianne Hackborn05726582009-09-22 17:28:24 -0700422 if (localLOGV) Log.v(TAG, "onOrientationChanged, rotation changed to " +rotation);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700423 try {
Dianne Hackborn32bc91d2009-03-27 16:16:03 -0700424 mWindowManager.setRotation(rotation, false,
425 mFancyRotationAnimation);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700426 } catch (RemoteException e) {
427 // Ignore
Wink Saville37c124c2009-04-02 01:37:02 -0700428
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800429 }
430 }
431 }
432 MyOrientationListener mOrientationListener;
433
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700434 boolean useSensorForOrientationLp(int appOrientation) {
Joe Onorato1b58b3e2009-09-22 16:44:16 -0700435 // The app says use the sensor.
Dianne Hackborne5439f22010-10-02 16:53:50 -0700436 if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
437 || appOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
438 || appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
439 || appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800440 return true;
441 }
Joe Onorato1b58b3e2009-09-22 16:44:16 -0700442 // The user preference says we can rotate, and the app is willing to rotate.
443 if (mAccelerometerDefault != 0 &&
444 (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
Dianne Hackborne5439f22010-10-02 16:53:50 -0700445 || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800446 return true;
447 }
Dianne Hackborne5439f22010-10-02 16:53:50 -0700448 // We're in a dock that has a rotation affinity, and the app is willing to rotate.
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700449 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR)
450 || (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) {
Joe Onorato1b58b3e2009-09-22 16:44:16 -0700451 // Note we override the nosensor flag here.
452 if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
453 || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
Dianne Hackborne5439f22010-10-02 16:53:50 -0700454 || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
Joe Onorato1b58b3e2009-09-22 16:44:16 -0700455 return true;
456 }
457 }
458 // Else, don't use the sensor.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800459 return false;
460 }
461
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700462 /*
463 * We always let the sensor be switched on by default except when
464 * the user has explicitly disabled sensor based rotation or when the
465 * screen is switched off.
466 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700467 boolean needSensorRunningLp() {
Dianne Hackborne5439f22010-10-02 16:53:50 -0700468 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
469 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
470 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
471 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800472 // If the application has explicitly requested to follow the
473 // orientation, then we need to turn the sensor or.
474 return true;
475 }
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700476 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
477 (mDeskDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_DESK)) {
Mike Lockwoode9867d22009-09-20 01:59:02 -0400478 // enable accelerometer if we are docked in a dock that enables accelerometer
479 // orientation management,
480 return true;
481 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700482 if (mAccelerometerDefault == 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800483 // If the setting for using the sensor by default is enabled, then
484 // we will always leave it on. Note that the user could go to
485 // a window that forces an orientation that does not use the
486 // sensor and in theory we could turn it off... however, when next
487 // turning it on we won't have a good value for the current
488 // orientation for a little bit, which can cause orientation
489 // changes to lag, so we'd like to keep it always on. (It will
490 // still be turned off when the screen is off.)
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700491 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800492 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700493 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800494 }
495
496 /*
497 * Various use cases for invoking this function
498 * screen turning off, should always disable listeners if already enabled
499 * screen turned on and current app has sensor based orientation, enable listeners
500 * if not already enabled
501 * screen turned on and current app does not have sensor orientation, disable listeners if
502 * already enabled
503 * screen turning on and current app has sensor based orientation, enable listeners if needed
504 * screen turning on and current app has nosensor based orientation, do nothing
505 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700506 void updateOrientationListenerLp() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800507 if (!mOrientationListener.canDetectOrientation()) {
508 // If sensor is turned off or nonexistent for some reason
509 return;
510 }
511 //Could have been invoked due to screen turning on or off or
512 //change of the currently visible window's orientation
Dianne Hackborn05726582009-09-22 17:28:24 -0700513 if (localLOGV) Log.v(TAG, "Screen status="+mScreenOn+
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800514 ", current orientation="+mCurrentAppOrientation+
515 ", SensorEnabled="+mOrientationSensorEnabled);
516 boolean disable = true;
The Android Open Source Project0727d222009-03-11 12:11:58 -0700517 if (mScreenOn) {
518 if (needSensorRunningLp()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800519 disable = false;
520 //enable listener if not already enabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700521 if (!mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800522 mOrientationListener.enable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700523 if(localLOGV) Log.v(TAG, "Enabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800524 mOrientationSensorEnabled = true;
525 }
526 }
527 }
528 //check if sensors need to be disabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700529 if (disable && mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800530 mOrientationListener.disable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700531 if(localLOGV) Log.v(TAG, "Disabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800532 mOrientationSensorEnabled = false;
533 }
534 }
535
Jeff Brown4d396052010-10-29 21:50:21 -0700536 private void interceptPowerKeyDown(boolean handled) {
537 mPowerKeyHandled = handled;
538 if (!handled) {
539 mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
540 }
541 }
542
543 private boolean interceptPowerKeyUp(boolean canceled) {
544 if (!mPowerKeyHandled) {
545 mHandler.removeCallbacks(mPowerLongPress);
546 return !canceled;
547 } else {
548 mPowerKeyHandled = true;
549 return false;
550 }
551 }
552
553 private final Runnable mPowerLongPress = new Runnable() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800554 public void run() {
Jeff Brown4d396052010-10-29 21:50:21 -0700555 if (!mPowerKeyHandled) {
556 // The context isn't read
557 if (mLongPressOnPowerBehavior < 0) {
558 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
559 com.android.internal.R.integer.config_longPressOnPowerBehavior);
560 }
561 switch (mLongPressOnPowerBehavior) {
562 case LONG_PRESS_POWER_NOTHING:
563 break;
564 case LONG_PRESS_POWER_GLOBAL_ACTIONS:
565 mPowerKeyHandled = true;
566 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
567 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
568 showGlobalActionsDialog();
569 break;
570 case LONG_PRESS_POWER_SHUT_OFF:
571 mPowerKeyHandled = true;
572 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
573 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
574 ShutdownThread.shutdown(mContext, true);
575 break;
576 }
Joe Onoratod208e702010-10-08 16:22:43 -0400577 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800578 }
579 };
580
581 void showGlobalActionsDialog() {
582 if (mGlobalActions == null) {
583 mGlobalActions = new GlobalActions(mContext);
584 }
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -0800585 final boolean keyguardShowing = mKeyguardMediator.isShowingAndNotHidden();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800586 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
587 if (keyguardShowing) {
588 // since it took two seconds of long press to bring this up,
589 // poke the wake lock so they have some time to see the dialog.
590 mKeyguardMediator.pokeWakelock();
591 }
592 }
593
594 boolean isDeviceProvisioned() {
595 return Settings.Secure.getInt(
596 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
597 }
598
599 /**
600 * When a home-key longpress expires, close other system windows and launch the recent apps
601 */
602 Runnable mHomeLongPress = new Runnable() {
603 public void run() {
Patrick Dubroyece94522011-02-23 18:35:01 -0800604 handleLongPressOnHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800605 }
606 };
607
Patrick Dubroyece94522011-02-23 18:35:01 -0800608 private void handleLongPressOnHome() {
Jim Milleree969aa2010-08-26 20:17:43 -0700609 // We can't initialize this in init() since the configuration hasn't been loaded yet.
Joe Onorato46b0d682010-11-22 17:37:27 -0800610 if (mLongPressOnHomeBehavior < 0) {
611 mLongPressOnHomeBehavior
Joe Onorato50262e52010-11-26 14:04:54 -0800612 = mContext.getResources().getInteger(R.integer.config_longPressOnHomeBehavior);
Joe Onorato46b0d682010-11-22 17:37:27 -0800613 if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
614 mLongPressOnHomeBehavior > LONG_PRESS_HOME_RECENT_ACTIVITY) {
615 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
616 }
617 }
618
619 if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
620 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
621 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
Patrick Dubroyece94522011-02-23 18:35:01 -0800622
623 // Eat the longpress so it won't dismiss the recent apps dialog when
624 // the user lets go of the home key
625 mHomePressed = false;
Jim Milleree969aa2010-08-26 20:17:43 -0700626 }
Patrick Dubroyece94522011-02-23 18:35:01 -0800627
Joe Onorato46b0d682010-11-22 17:37:27 -0800628 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
Jeff Brown54875002011-04-06 15:33:01 -0700629 showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
Joe Onorato46b0d682010-11-22 17:37:27 -0800630 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_ACTIVITY) {
Jim Millere6ad1a82010-08-20 19:25:39 -0700631 try {
Jim Milleree969aa2010-08-26 20:17:43 -0700632 Intent intent = new Intent();
633 intent.setClassName("com.android.systemui",
Joe Onorato46b0d682010-11-22 17:37:27 -0800634 "com.android.systemui.recent.RecentApplicationsActivity");
Jim Milleree969aa2010-08-26 20:17:43 -0700635 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
636 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
637 mContext.startActivity(intent);
Jim Millere6ad1a82010-08-20 19:25:39 -0700638 return;
639 } catch (ActivityNotFoundException e) {
640 Log.e(TAG, "Failed to launch RecentAppsIntent", e);
641 }
642 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800643 }
Patrick Dubroyece94522011-02-23 18:35:01 -0800644
645 /**
Jeff Brown54875002011-04-06 15:33:01 -0700646 * Create (if necessary) and launch the recent apps dialog, or hide it if it is
647 * already shown.
Patrick Dubroyece94522011-02-23 18:35:01 -0800648 */
Jeff Brown54875002011-04-06 15:33:01 -0700649 void showOrHideRecentAppsDialog(final int heldModifiers, final boolean dismissIfShown) {
Jeff Brownda3d5a92011-03-29 15:11:34 -0700650 mHandler.post(new Runnable() {
651 @Override
652 public void run() {
653 if (mRecentAppsDialog == null) {
Jeff Brown54875002011-04-06 15:33:01 -0700654 mRecentAppsDialog = new RecentApplicationsDialog(mContext);
Jeff Brownda3d5a92011-03-29 15:11:34 -0700655 }
Jeff Brown54875002011-04-06 15:33:01 -0700656 if (mRecentAppsDialog.isShowing()) {
657 if (dismissIfShown) {
658 mRecentAppsDialog.dismiss();
659 }
660 } else {
661 mRecentAppsDialog.setHeldModifiers(heldModifiers);
662 mRecentAppsDialog.show();
663 }
Jeff Brownda3d5a92011-03-29 15:11:34 -0700664 }
665 });
Patrick Dubroyece94522011-02-23 18:35:01 -0800666 }
Jeff Brownda3d5a92011-03-29 15:11:34 -0700667
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800668 /** {@inheritDoc} */
669 public void init(Context context, IWindowManager windowManager,
670 LocalPowerManager powerManager) {
671 mContext = context;
672 mWindowManager = windowManager;
673 mPowerManager = powerManager;
674 mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
675 mHandler = new Handler();
676 mOrientationListener = new MyOrientationListener(mContext);
677 SettingsObserver settingsObserver = new SettingsObserver(mHandler);
678 settingsObserver.observe();
679 mShortcutManager = new ShortcutManager(context, mHandler);
680 mShortcutManager.observe();
681 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
682 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
683 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
684 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700685 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
686 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
687 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
688 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
689 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
690 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
691 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
692 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Jim Millere6ad1a82010-08-20 19:25:39 -0700693
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800694 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
695 mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
696 "PhoneWindowManager.mBroadcastWakeLock");
697 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700698 mLidOpenRotation = readRotation(
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400699 com.android.internal.R.integer.config_lidOpenRotation);
700 mCarDockRotation = readRotation(
701 com.android.internal.R.integer.config_carDockRotation);
702 mDeskDockRotation = readRotation(
703 com.android.internal.R.integer.config_deskDockRotation);
Dianne Hackborna1111872010-11-23 20:55:11 -0800704 mAllowAllRotations = mContext.getResources().getBoolean(
705 com.android.internal.R.bool.config_allowAllRotations);
Mike Lockwoode9867d22009-09-20 01:59:02 -0400706 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
707 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
708 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
709 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700710 mLidKeyboardAccessibility = mContext.getResources().getInteger(
711 com.android.internal.R.integer.config_lidKeyboardAccessibility);
712 mLidNavigationAccessibility = mContext.getResources().getInteger(
713 com.android.internal.R.integer.config_lidNavigationAccessibility);
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700714 // register for dock events
Dianne Hackborn78968392010-03-04 20:47:56 -0800715 IntentFilter filter = new IntentFilter();
716 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
717 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
718 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
719 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700720 filter.addAction(Intent.ACTION_DOCK_EVENT);
721 Intent intent = context.registerReceiver(mDockReceiver, filter);
722 if (intent != null) {
723 // Retrieve current sticky dock event broadcast.
724 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
725 Intent.EXTRA_DOCK_STATE_UNDOCKED);
726 }
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700727 mVibrator = new Vibrator();
728 mLongPressVibePattern = getLongIntArray(mContext.getResources(),
729 com.android.internal.R.array.config_longPressVibePattern);
730 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
731 com.android.internal.R.array.config_virtualKeyVibePattern);
Amith Yamasanic33cb712010-02-10 15:21:49 -0800732 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
733 com.android.internal.R.array.config_keyboardTapVibePattern);
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700734 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
735 com.android.internal.R.array.config_safeModeDisabledVibePattern);
736 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
737 com.android.internal.R.array.config_safeModeEnabledVibePattern);
Daniel Sandler40427442010-07-16 11:44:52 -0400738
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800739 // watch for HDMI plug messages if the hdmi switch exists
740 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
741 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
742 }
Joe Onoratodc100302011-01-11 17:07:41 -0800743 mHdmiPlugged = !readHdmiState();
744 setHdmiPlugged(!mHdmiPlugged);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800745
Daniel Sandler40427442010-07-16 11:44:52 -0400746 // Note: the Configuration is not stable here, so we cannot load mStatusBarCanHide from
747 // config_statusBarCanHide because the latter depends on the screen size
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700748 }
749
Dianne Hackbornc777e072010-02-12 13:07:59 -0800750 public void updateSettings() {
751 ContentResolver resolver = mContext.getContentResolver();
752 boolean updateRotation = false;
753 View addView = null;
754 View removeView = null;
755 synchronized (mLock) {
756 mEndcallBehavior = Settings.System.getInt(resolver,
David Brownbaf8d092010-03-08 21:52:59 -0800757 Settings.System.END_BUTTON_BEHAVIOR,
758 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT);
759 mIncallPowerBehavior = Settings.Secure.getInt(resolver,
760 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
761 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
Dianne Hackbornc777e072010-02-12 13:07:59 -0800762 mFancyRotationAnimation = Settings.System.getInt(resolver,
763 "fancy_rotation_anim", 0) != 0 ? 0x80 : 0;
764 int accelerometerDefault = Settings.System.getInt(resolver,
765 Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400766
767 // set up rotation lock state
Daniel Sandler1b815d62010-11-05 10:24:27 -0400768 mUserRotationMode = (accelerometerDefault == 0)
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400769 ? WindowManagerPolicy.USER_ROTATION_LOCKED
770 : WindowManagerPolicy.USER_ROTATION_FREE;
771 mUserRotation = Settings.System.getInt(resolver,
772 Settings.System.USER_ROTATION,
773 Surface.ROTATION_0);
774
Dianne Hackbornc777e072010-02-12 13:07:59 -0800775 if (mAccelerometerDefault != accelerometerDefault) {
776 mAccelerometerDefault = accelerometerDefault;
777 updateOrientationListenerLp();
778 }
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400779
Jeff Brown4519f072011-01-23 13:16:01 -0800780 mOrientationListener.setLogEnabled(
781 Settings.System.getInt(resolver,
782 Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, 0) != 0);
783
Dianne Hackbornc777e072010-02-12 13:07:59 -0800784 if (mSystemReady) {
785 int pointerLocation = Settings.System.getInt(resolver,
786 Settings.System.POINTER_LOCATION, 0);
787 if (mPointerLocationMode != pointerLocation) {
788 mPointerLocationMode = pointerLocation;
789 if (pointerLocation != 0) {
790 if (mPointerLocationView == null) {
791 mPointerLocationView = new PointerLocationView(mContext);
792 mPointerLocationView.setPrintCoords(false);
793 addView = mPointerLocationView;
794 }
795 } else {
796 removeView = mPointerLocationView;
797 mPointerLocationView = null;
798 }
799 }
800 }
801 // use screen off timeout setting as the timeout for the lockscreen
802 mLockScreenTimeout = Settings.System.getInt(resolver,
803 Settings.System.SCREEN_OFF_TIMEOUT, 0);
804 String imId = Settings.Secure.getString(resolver,
805 Settings.Secure.DEFAULT_INPUT_METHOD);
806 boolean hasSoftInput = imId != null && imId.length() > 0;
807 if (mHasSoftInput != hasSoftInput) {
808 mHasSoftInput = hasSoftInput;
809 updateRotation = true;
810 }
811 }
812 if (updateRotation) {
813 updateRotation(0);
814 }
815 if (addView != null) {
816 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
817 WindowManager.LayoutParams.MATCH_PARENT,
818 WindowManager.LayoutParams.MATCH_PARENT);
Jeff Brown3b2b3542010-10-15 00:54:27 -0700819 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
Dianne Hackbornc777e072010-02-12 13:07:59 -0800820 lp.flags =
821 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
822 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
823 WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
824 lp.format = PixelFormat.TRANSLUCENT;
825 lp.setTitle("PointerLocation");
826 WindowManagerImpl wm = (WindowManagerImpl)
827 mContext.getSystemService(Context.WINDOW_SERVICE);
828 wm.addView(addView, lp);
Jeff Browna41ca772010-08-11 14:46:32 -0700829
830 if (mPointerLocationInputChannel == null) {
831 try {
832 mPointerLocationInputChannel =
833 mWindowManager.monitorInput("PointerLocationView");
834 InputQueue.registerInputChannel(mPointerLocationInputChannel,
835 mPointerLocationInputHandler, mHandler.getLooper().getQueue());
836 } catch (RemoteException ex) {
837 Slog.e(TAG, "Could not set up input monitoring channel for PointerLocation.",
838 ex);
839 }
840 }
Dianne Hackbornc777e072010-02-12 13:07:59 -0800841 }
842 if (removeView != null) {
Jeff Browna41ca772010-08-11 14:46:32 -0700843 if (mPointerLocationInputChannel != null) {
844 InputQueue.unregisterInputChannel(mPointerLocationInputChannel);
845 mPointerLocationInputChannel.dispose();
846 mPointerLocationInputChannel = null;
847 }
848
Dianne Hackbornc777e072010-02-12 13:07:59 -0800849 WindowManagerImpl wm = (WindowManagerImpl)
850 mContext.getSystemService(Context.WINDOW_SERVICE);
851 wm.removeView(removeView);
852 }
853 }
854
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400855 private int readRotation(int resID) {
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700856 try {
857 int rotation = mContext.getResources().getInteger(resID);
858 switch (rotation) {
859 case 0:
860 return Surface.ROTATION_0;
861 case 90:
862 return Surface.ROTATION_90;
863 case 180:
864 return Surface.ROTATION_180;
865 case 270:
866 return Surface.ROTATION_270;
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700867 }
868 } catch (Resources.NotFoundException e) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400869 // fall through
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700870 }
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400871 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800872 }
873
874 /** {@inheritDoc} */
875 public int checkAddPermission(WindowManager.LayoutParams attrs) {
876 int type = attrs.type;
Mitsuru Oshima831d0d92009-06-16 18:27:18 -0700877
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800878 if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
879 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
880 return WindowManagerImpl.ADD_OKAY;
881 }
882 String permission = null;
883 switch (type) {
884 case TYPE_TOAST:
885 // XXX right now the app process has complete control over
886 // this... should introduce a token to let the system
887 // monitor/control what they are doing.
888 break;
889 case TYPE_INPUT_METHOD:
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700890 case TYPE_WALLPAPER:
891 // The window manager will check these.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800892 break;
893 case TYPE_PHONE:
894 case TYPE_PRIORITY_PHONE:
895 case TYPE_SYSTEM_ALERT:
896 case TYPE_SYSTEM_ERROR:
897 case TYPE_SYSTEM_OVERLAY:
898 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
899 break;
900 default:
901 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
902 }
903 if (permission != null) {
904 if (mContext.checkCallingOrSelfPermission(permission)
905 != PackageManager.PERMISSION_GRANTED) {
906 return WindowManagerImpl.ADD_PERMISSION_DENIED;
907 }
908 }
909 return WindowManagerImpl.ADD_OKAY;
910 }
911
912 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
913 switch (attrs.type) {
914 case TYPE_SYSTEM_OVERLAY:
Jeff Brown3b2b3542010-10-15 00:54:27 -0700915 case TYPE_SECURE_SYSTEM_OVERLAY:
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800916 case TYPE_TOAST:
917 // These types of windows can't receive input events.
918 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
919 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
920 break;
921 }
922 }
923
924 void readLidState() {
925 try {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700926 int sw = mWindowManager.getSwitchState(SW_LID);
Jeff Brown4aed78b2011-01-14 17:36:55 -0800927 if (sw > 0) {
928 mLidOpen = LID_OPEN;
929 } else if (sw == 0) {
930 mLidOpen = LID_CLOSED;
931 } else {
932 mLidOpen = LID_ABSENT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800933 }
934 } catch (RemoteException e) {
935 // Ignore
936 }
937 }
938
Jeff Brown4aed78b2011-01-14 17:36:55 -0800939 private int determineHiddenState(int mode, int hiddenValue, int visibleValue) {
Jeff Brownd04a88c2011-01-16 14:05:47 -0800940 if (mLidOpen != LID_ABSENT) {
941 switch (mode) {
942 case 1:
943 return mLidOpen == LID_OPEN ? visibleValue : hiddenValue;
944 case 2:
945 return mLidOpen == LID_OPEN ? hiddenValue : visibleValue;
946 }
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700947 }
948 return visibleValue;
949 }
Jeff Brownd04a88c2011-01-16 14:05:47 -0800950
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800951 /** {@inheritDoc} */
952 public void adjustConfigurationLw(Configuration config) {
953 readLidState();
Jeff Brownd04a88c2011-01-16 14:05:47 -0800954
Jeff Brown4aed78b2011-01-14 17:36:55 -0800955 mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN);
Jeff Brownd04a88c2011-01-16 14:05:47 -0800956
957 if (config.keyboard == Configuration.KEYBOARD_NOKEYS) {
958 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
959 } else {
960 config.hardKeyboardHidden = determineHiddenState(mLidKeyboardAccessibility,
961 Configuration.HARDKEYBOARDHIDDEN_YES, Configuration.HARDKEYBOARDHIDDEN_NO);
962 }
963
964 if (config.navigation == Configuration.NAVIGATION_NONAV) {
965 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
966 } else {
967 config.navigationHidden = determineHiddenState(mLidNavigationAccessibility,
968 Configuration.NAVIGATIONHIDDEN_YES, Configuration.NAVIGATIONHIDDEN_NO);
969 }
970
971 if (mHasSoftInput || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
972 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
973 } else {
974 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
975 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800976 }
Jeff Brownd04a88c2011-01-16 14:05:47 -0800977
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800978 /** {@inheritDoc} */
979 public int windowTypeToLayerLw(int type) {
980 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
981 return APPLICATION_LAYER;
982 }
983 switch (type) {
984 case TYPE_STATUS_BAR:
985 return STATUS_BAR_LAYER;
986 case TYPE_STATUS_BAR_PANEL:
987 return STATUS_BAR_PANEL_LAYER;
Joe Onorato29fc2c92010-11-24 10:26:50 -0800988 case TYPE_STATUS_BAR_SUB_PANEL:
989 return STATUS_BAR_SUB_PANEL_LAYER;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800990 case TYPE_SYSTEM_DIALOG:
991 return SYSTEM_DIALOG_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800992 case TYPE_SEARCH_BAR:
993 return SEARCH_BAR_LAYER;
994 case TYPE_PHONE:
995 return PHONE_LAYER;
996 case TYPE_KEYGUARD:
997 return KEYGUARD_LAYER;
998 case TYPE_KEYGUARD_DIALOG:
999 return KEYGUARD_DIALOG_LAYER;
1000 case TYPE_SYSTEM_ALERT:
1001 return SYSTEM_ALERT_LAYER;
1002 case TYPE_SYSTEM_ERROR:
1003 return SYSTEM_ERROR_LAYER;
1004 case TYPE_INPUT_METHOD:
1005 return INPUT_METHOD_LAYER;
1006 case TYPE_INPUT_METHOD_DIALOG:
1007 return INPUT_METHOD_DIALOG_LAYER;
1008 case TYPE_SYSTEM_OVERLAY:
1009 return SYSTEM_OVERLAY_LAYER;
Jeff Brown3b2b3542010-10-15 00:54:27 -07001010 case TYPE_SECURE_SYSTEM_OVERLAY:
1011 return SECURE_SYSTEM_OVERLAY_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001012 case TYPE_PRIORITY_PHONE:
1013 return PRIORITY_PHONE_LAYER;
1014 case TYPE_TOAST:
1015 return TOAST_LAYER;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -07001016 case TYPE_WALLPAPER:
1017 return WALLPAPER_LAYER;
Christopher Tatea53146c2010-09-07 11:57:52 -07001018 case TYPE_DRAG:
1019 return DRAG_LAYER;
Jeff Brown83c09682010-12-23 17:50:18 -08001020 case TYPE_POINTER:
1021 return POINTER_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001022 }
1023 Log.e(TAG, "Unknown window type: " + type);
1024 return APPLICATION_LAYER;
1025 }
1026
1027 /** {@inheritDoc} */
1028 public int subWindowTypeToLayerLw(int type) {
1029 switch (type) {
1030 case TYPE_APPLICATION_PANEL:
1031 case TYPE_APPLICATION_ATTACHED_DIALOG:
1032 return APPLICATION_PANEL_SUBLAYER;
1033 case TYPE_APPLICATION_MEDIA:
1034 return APPLICATION_MEDIA_SUBLAYER;
Dianne Hackborn5cb8d792009-05-21 17:34:15 -07001035 case TYPE_APPLICATION_MEDIA_OVERLAY:
1036 return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001037 case TYPE_APPLICATION_SUB_PANEL:
1038 return APPLICATION_SUB_PANEL_SUBLAYER;
1039 }
1040 Log.e(TAG, "Unknown sub-window type: " + type);
1041 return 0;
1042 }
1043
Dianne Hackbornabe0da02009-09-18 01:55:39 -07001044 public int getMaxWallpaperLayer() {
1045 return STATUS_BAR_LAYER;
1046 }
1047
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001048 public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
1049 return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
1050 }
1051
1052 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
1053 return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
1054 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
1055 }
1056
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001057 /** {@inheritDoc} */
1058 public View addStartingWindow(IBinder appToken, String packageName,
1059 int theme, CharSequence nonLocalizedLabel,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001060 int labelRes, int icon, int windowFlags) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001061 if (!SHOW_STARTING_ANIMATIONS) {
1062 return null;
1063 }
1064 if (packageName == null) {
1065 return null;
1066 }
1067
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001068 try {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001069 Context context = mContext;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001070 //Log.i(TAG, "addStartingWindow " + packageName + ": nonLocalizedLabel="
1071 // + nonLocalizedLabel + " theme=" + Integer.toHexString(theme));
Dianne Hackborn247fe742011-01-08 17:25:57 -08001072 if (theme != context.getThemeResId() || labelRes != 0) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001073 try {
1074 context = context.createPackageContext(packageName, 0);
Dianne Hackborn247fe742011-01-08 17:25:57 -08001075 context.setTheme(theme);
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001076 } catch (PackageManager.NameNotFoundException e) {
1077 // Ignore
1078 }
1079 }
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001080
1081 Window win = PolicyManager.makeNewWindow(context);
1082 if (win.getWindowStyle().getBoolean(
1083 com.android.internal.R.styleable.Window_windowDisablePreview, false)) {
1084 return null;
1085 }
1086
1087 Resources r = context.getResources();
1088 win.setTitle(r.getText(labelRes, nonLocalizedLabel));
1089
1090 win.setType(
1091 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
1092 // Force the window flags: this is a fake window, so it is not really
1093 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
1094 // flag because we do know that the next window will take input
1095 // focus, so we want to get the IME window up on top of us right away.
1096 win.setFlags(
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001097 windowFlags|
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001098 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
1099 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
1100 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001101 windowFlags|
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001102 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
1103 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
1104 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
1105
1106 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
1107 WindowManager.LayoutParams.MATCH_PARENT);
1108
1109 final WindowManager.LayoutParams params = win.getAttributes();
1110 params.token = appToken;
1111 params.packageName = packageName;
1112 params.windowAnimations = win.getWindowStyle().getResourceId(
1113 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
1114 params.setTitle("Starting " + packageName);
1115
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001116 WindowManagerImpl wm = (WindowManagerImpl)
1117 context.getSystemService(Context.WINDOW_SERVICE);
1118 View view = win.getDecorView();
1119
1120 if (win.isFloating()) {
1121 // Whoops, there is no way to display an animation/preview
1122 // of such a thing! After all that work... let's skip it.
1123 // (Note that we must do this here because it is in
1124 // getDecorView() where the theme is evaluated... maybe
1125 // we should peek the floating attribute from the theme
1126 // earlier.)
1127 return null;
1128 }
1129
1130 if (localLOGV) Log.v(
1131 TAG, "Adding starting window for " + packageName
1132 + " / " + appToken + ": "
1133 + (view.getParent() != null ? view : null));
1134
1135 wm.addView(view, params);
1136
1137 // Only return the view if it was successfully added to the
1138 // window manager... which we can tell by it having a parent.
1139 return view.getParent() != null ? view : null;
1140 } catch (WindowManagerImpl.BadTokenException e) {
1141 // ignore
1142 Log.w(TAG, appToken + " already running, starting window not displayed");
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001143 } catch (RuntimeException e) {
1144 // don't crash if something else bad happens, for example a
1145 // failure loading resources because we are loading from an app
1146 // on external storage that has been unmounted.
1147 Log.w(TAG, appToken + " failed creating starting window", e);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001148 }
1149
1150 return null;
1151 }
1152
1153 /** {@inheritDoc} */
1154 public void removeStartingWindow(IBinder appToken, View window) {
1155 // RuntimeException e = new RuntimeException();
1156 // Log.i(TAG, "remove " + appToken + " " + window, e);
1157
1158 if (localLOGV) Log.v(
1159 TAG, "Removing starting window for " + appToken + ": " + window);
1160
1161 if (window != null) {
1162 WindowManagerImpl wm = (WindowManagerImpl) mContext.getSystemService(Context.WINDOW_SERVICE);
1163 wm.removeView(window);
1164 }
1165 }
1166
1167 /**
1168 * Preflight adding a window to the system.
1169 *
1170 * Currently enforces that three window types are singletons:
1171 * <ul>
1172 * <li>STATUS_BAR_TYPE</li>
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001173 * <li>KEYGUARD_TYPE</li>
1174 * </ul>
1175 *
1176 * @param win The window to be added
1177 * @param attrs Information about the window to be added
1178 *
1179 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON
1180 */
1181 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
1182 switch (attrs.type) {
1183 case TYPE_STATUS_BAR:
Joe Onorato8bc6c512010-06-04 16:21:12 -04001184 mContext.enforceCallingOrSelfPermission(
1185 android.Manifest.permission.STATUS_BAR_SERVICE,
1186 "PhoneWindowManager");
1187 // TODO: Need to handle the race condition of the status bar proc
1188 // dying and coming back before the removeWindowLw cleanup has happened.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001189 if (mStatusBar != null) {
1190 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1191 }
1192 mStatusBar = win;
Daniel Sandler40427442010-07-16 11:44:52 -04001193
1194 // The Configuration will be stable by now, so we can load this
1195 mStatusBarCanHide = mContext.getResources().getBoolean(
1196 com.android.internal.R.bool.config_statusBarCanHide);
1197
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001198 break;
Dianne Hackborn08743722009-12-21 12:16:51 -08001199 case TYPE_STATUS_BAR_PANEL:
Joe Onorato8bc6c512010-06-04 16:21:12 -04001200 mContext.enforceCallingOrSelfPermission(
1201 android.Manifest.permission.STATUS_BAR_SERVICE,
1202 "PhoneWindowManager");
Dianne Hackborn08743722009-12-21 12:16:51 -08001203 mStatusBarPanels.add(win);
1204 break;
Joe Onorato29fc2c92010-11-24 10:26:50 -08001205 case TYPE_STATUS_BAR_SUB_PANEL:
1206 mContext.enforceCallingOrSelfPermission(
1207 android.Manifest.permission.STATUS_BAR_SERVICE,
1208 "PhoneWindowManager");
1209 mStatusBarPanels.add(win);
1210 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001211 case TYPE_KEYGUARD:
1212 if (mKeyguard != null) {
1213 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1214 }
1215 mKeyguard = win;
1216 break;
1217 }
1218 return WindowManagerImpl.ADD_OKAY;
1219 }
1220
1221 /** {@inheritDoc} */
1222 public void removeWindowLw(WindowState win) {
1223 if (mStatusBar == win) {
1224 mStatusBar = null;
1225 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001226 else if (mKeyguard == win) {
1227 mKeyguard = null;
Dianne Hackborn08743722009-12-21 12:16:51 -08001228 } else {
1229 mStatusBarPanels.remove(win);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001230 }
1231 }
1232
1233 static final boolean PRINT_ANIM = false;
1234
1235 /** {@inheritDoc} */
1236 public int selectAnimationLw(WindowState win, int transit) {
1237 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
1238 + ": transit=" + transit);
1239 if (transit == TRANSIT_PREVIEW_DONE) {
1240 if (win.hasAppShownWindows()) {
1241 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
1242 return com.android.internal.R.anim.app_starting_exit;
1243 }
1244 }
1245
1246 return 0;
1247 }
1248
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001249 public Animation createForceHideEnterAnimation() {
1250 return AnimationUtils.loadAnimation(mContext,
1251 com.android.internal.R.anim.lock_screen_behind_enter);
1252 }
1253
Jeff Brown4d396052010-10-29 21:50:21 -07001254 static ITelephony getTelephonyService() {
1255 ITelephony telephonyService = ITelephony.Stub.asInterface(
1256 ServiceManager.checkService(Context.TELEPHONY_SERVICE));
1257 if (telephonyService == null) {
1258 Log.w(TAG, "Unable to find ITelephony interface.");
1259 }
1260 return telephonyService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001261 }
1262
Jeff Brown4d396052010-10-29 21:50:21 -07001263 static IAudioService getAudioService() {
1264 IAudioService audioService = IAudioService.Stub.asInterface(
1265 ServiceManager.checkService(Context.AUDIO_SERVICE));
1266 if (audioService == null) {
1267 Log.w(TAG, "Unable to find IAudioService interface.");
1268 }
1269 return audioService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001270 }
1271
1272 boolean keyguardOn() {
1273 return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
1274 }
1275
1276 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
1277 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
1278 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
1279 };
1280
1281 /** {@inheritDoc} */
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001282 @Override
Jeff Brown1f245102010-11-18 20:53:46 -08001283 public boolean interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001284 final boolean keyguardOn = keyguardOn();
Jeff Brown1f245102010-11-18 20:53:46 -08001285 final int keyCode = event.getKeyCode();
1286 final int repeatCount = event.getRepeatCount();
1287 final int metaState = event.getMetaState();
1288 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
1289 final boolean canceled = event.isCanceled();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001290
1291 if (false) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001292 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001293 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
1294 }
1295
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001296 // First we always handle the home key here, so applications
1297 // can never break it, although if keyguard is on, we do let
1298 // it handle it, because that gives us the correct 5 second
1299 // timeout.
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001300 if (keyCode == KeyEvent.KEYCODE_HOME) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001301 // Clear a pending HOME longpress if the user releases Home
1302 if (!down) {
1303 mHandler.removeCallbacks(mHomeLongPress);
1304 }
1305
1306 // If we have released the home key, and didn't do anything else
1307 // while it was pressed, then it is time to go home!
1308 if (mHomePressed && !down) {
1309 mHomePressed = false;
1310 if (!canceled) {
1311 // If an incoming call is ringing, HOME is totally disabled.
1312 // (The user is already on the InCallScreen at this point,
1313 // and his ONLY options are to answer or reject the call.)
1314 boolean incomingRinging = false;
1315 try {
1316 ITelephony telephonyService = getTelephonyService();
1317 if (telephonyService != null) {
1318 incomingRinging = telephonyService.isRinging();
1319 }
1320 } catch (RemoteException ex) {
1321 Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
1322 }
1323
1324 if (incomingRinging) {
1325 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
1326 } else {
1327 launchHomeFromHotKey();
1328 }
1329 } else {
1330 Log.i(TAG, "Ignoring HOME; event canceled.");
1331 }
1332 return true;
1333 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001334
1335 // If a system window has focus, then it doesn't make sense
1336 // right now to interact with applications.
1337 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
1338 if (attrs != null) {
1339 final int type = attrs.type;
1340 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
1341 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
1342 // the "app" is keyguard, so give it the key
1343 return false;
1344 }
1345 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
1346 for (int i=0; i<typeCount; i++) {
1347 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
1348 // don't do anything, but also don't pass it to the app
1349 return true;
1350 }
1351 }
1352 }
1353
1354 if (down && repeatCount == 0) {
1355 if (!keyguardOn) {
1356 mHandler.postDelayed(mHomeLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
1357 }
1358 mHomePressed = true;
1359 }
1360 return true;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001361 } else if (keyCode == KeyEvent.KEYCODE_MENU) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001362 // Hijack modified menu keys for debugging features
1363 final int chordBug = KeyEvent.META_SHIFT_ON;
1364
1365 if (down && repeatCount == 0) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001366 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001367 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
1368 mContext.sendOrderedBroadcast(intent, null);
1369 return true;
1370 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001371 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001372 Intent service = new Intent();
1373 service.setClassName(mContext, "com.android.server.LoadAverageService");
1374 ContentResolver res = mContext.getContentResolver();
1375 boolean shown = Settings.System.getInt(
1376 res, Settings.System.SHOW_PROCESSES, 0) != 0;
1377 if (!shown) {
1378 mContext.startService(service);
1379 } else {
1380 mContext.stopService(service);
1381 }
1382 Settings.System.putInt(
1383 res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
1384 return true;
1385 }
1386 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001387 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001388 if (down) {
1389 if (repeatCount == 0) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001390 mShortcutKeyPressed = keyCode;
1391 mConsumeShortcutKeyUp = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001392 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001393 } else if (keyCode == mShortcutKeyPressed) {
1394 mShortcutKeyPressed = -1;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001395 if (mConsumeShortcutKeyUp) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001396 mConsumeShortcutKeyUp = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001397 return true;
1398 }
1399 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001400 return false;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001401 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
Jeff Brownda3d5a92011-03-29 15:11:34 -07001402 if (down && repeatCount == 0) {
Jeff Brown54875002011-04-06 15:33:01 -07001403 showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
Jeff Brown49ed71d2010-12-06 17:13:33 -08001404 }
1405 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001406 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001407
Jeff Brownc1fb48d2010-12-08 16:52:09 -08001408 // Shortcuts are invoked through Search+key, so intercept those here
Jeff Browncaab4d02010-12-09 22:13:41 -08001409 // Any printing key that is chorded with Search should be consumed
1410 // even if no shortcut was invoked. This prevents text from being
1411 // inadvertently inserted when using a keyboard that has built-in macro
1412 // shortcut keys (that emit Search+x) and some of them are not registered.
1413 if (mShortcutKeyPressed != -1) {
1414 final KeyCharacterMap kcm = event.getKeyCharacterMap();
1415 if (kcm.isPrintingKey(keyCode)) {
1416 mConsumeShortcutKeyUp = true;
1417 if (down && repeatCount == 0 && !keyguardOn) {
1418 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
1419 if (shortcutIntent != null) {
1420 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Jeff Brownf0a3cc52011-01-26 18:42:46 -08001421 try {
1422 mContext.startActivity(shortcutIntent);
1423 } catch (ActivityNotFoundException ex) {
1424 Slog.w(TAG, "Dropping shortcut key combination because "
1425 + "the activity to which it is registered was not found: "
1426 + KeyEvent.keyCodeToString(mShortcutKeyPressed)
1427 + "+" + KeyEvent.keyCodeToString(keyCode), ex);
1428 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001429 } else {
1430 Slog.i(TAG, "Dropping unregistered shortcut key combination: "
1431 + KeyEvent.keyCodeToString(mShortcutKeyPressed)
1432 + "+" + KeyEvent.keyCodeToString(keyCode));
Jeff Brown49ed71d2010-12-06 17:13:33 -08001433 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001434 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001435 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001436 }
1437 }
1438
1439 return false;
1440 }
1441
Jeff Brown3915bb82010-11-05 15:02:16 -07001442 /** {@inheritDoc} */
1443 @Override
Jeff Brown49ed71d2010-12-06 17:13:33 -08001444 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
Jeff Brown54875002011-04-06 15:33:01 -07001445 // Note: This method is only called if the initial down was unhandled.
Jeff Brown49ed71d2010-12-06 17:13:33 -08001446 if (DEBUG_FALLBACK) {
Jeff Brown1f245102010-11-18 20:53:46 -08001447 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
1448 + ", flags=" + event.getFlags()
1449 + ", keyCode=" + event.getKeyCode()
1450 + ", scanCode=" + event.getScanCode()
1451 + ", metaState=" + event.getMetaState()
1452 + ", repeatCount=" + event.getRepeatCount()
1453 + ", policyFlags=" + policyFlags);
Jeff Brown3915bb82010-11-05 15:02:16 -07001454 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001455
1456 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1457 final KeyCharacterMap kcm = event.getKeyCharacterMap();
Jeff Brownc1fb48d2010-12-08 16:52:09 -08001458 final int keyCode = event.getKeyCode();
1459 final int metaState = event.getMetaState();
Jeff Brown54875002011-04-06 15:33:01 -07001460 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
1461 && event.getRepeatCount() == 0;
1462
1463 if (initialDown) {
1464 // Invoke shortcuts using Meta as a fallback.
1465 if ((metaState & KeyEvent.META_META_ON) != 0) {
1466 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
1467 metaState & ~(KeyEvent.META_META_ON
1468 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
1469 if (shortcutIntent != null) {
1470 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1471 try {
1472 mContext.startActivity(shortcutIntent);
1473 } catch (ActivityNotFoundException ex) {
1474 Slog.w(TAG, "Dropping shortcut key combination because "
1475 + "the activity to which it is registered was not found: "
1476 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
1477 }
1478 return null;
Jeff Brownbfaf3b92011-02-22 15:00:50 -08001479 }
Jeff Brown54875002011-04-06 15:33:01 -07001480 }
1481
1482 // Display task switcher for ALT-TAB or Meta-TAB.
1483 if (keyCode == KeyEvent.KEYCODE_TAB) {
1484 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
1485 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
1486 || KeyEvent.metaStateHasModifiers(
1487 shiftlessModifiers, KeyEvent.META_META_ON)) {
1488 showOrHideRecentAppsDialog(shiftlessModifiers, false /*dismissIfShown*/);
1489 return null;
1490 }
Jeff Brownc1fb48d2010-12-08 16:52:09 -08001491 }
1492 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001493
Jeff Brown54875002011-04-06 15:33:01 -07001494 // Check for fallback actions specified by the key character map.
Jeff Brown6f2fba42011-02-19 01:08:02 -08001495 if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001496 if (DEBUG_FALLBACK) {
1497 Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
1498 + " metaState=" + Integer.toHexString(mFallbackAction.metaState));
1499 }
1500
1501 int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
1502 KeyEvent fallbackEvent = KeyEvent.obtain(
1503 event.getDownTime(), event.getEventTime(),
1504 event.getAction(), mFallbackAction.keyCode,
1505 event.getRepeatCount(), mFallbackAction.metaState,
1506 event.getDeviceId(), event.getScanCode(),
1507 flags, event.getSource(), null);
1508 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
1509 if ((actions & ACTION_PASS_TO_USER) != 0) {
1510 if (!interceptKeyBeforeDispatching(win, fallbackEvent, policyFlags)) {
1511 if (DEBUG_FALLBACK) {
1512 Slog.d(TAG, "Performing fallback.");
1513 }
1514 return fallbackEvent;
1515 }
1516 }
1517 fallbackEvent.recycle();
1518 }
1519 }
1520
1521 if (DEBUG_FALLBACK) {
1522 Slog.d(TAG, "No fallback.");
1523 }
1524 return null;
Jeff Brown3915bb82010-11-05 15:02:16 -07001525 }
1526
Jeff Brown6f2fba42011-02-19 01:08:02 -08001527 private boolean getFallbackAction(KeyCharacterMap kcm, int keyCode, int metaState,
1528 FallbackAction outFallbackAction) {
1529 // Consult the key character map for specific fallback actions.
1530 // For example, map NUMPAD_1 to MOVE_HOME when NUMLOCK is not pressed.
Jeff Browncc0c1592011-02-19 05:07:28 -08001531 return kcm.getFallbackAction(keyCode, metaState, outFallbackAction);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001532 }
1533
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001534 /**
1535 * A home key -> launch home action was detected. Take the appropriate action
1536 * given the situation with the keyguard.
1537 */
1538 void launchHomeFromHotKey() {
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08001539 if (mKeyguardMediator.isShowingAndNotHidden()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001540 // don't launch home if keyguard showing
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001541 } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001542 // when in keyguard restricted mode, must first verify unlock
1543 // before launching home
1544 mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
1545 public void onKeyguardExitResult(boolean success) {
1546 if (success) {
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07001547 try {
1548 ActivityManagerNative.getDefault().stopAppSwitches();
1549 } catch (RemoteException e) {
1550 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05001551 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001552 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001553 }
1554 }
1555 });
1556 } else {
1557 // no keyguard stuff to worry about, just launch home!
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07001558 try {
1559 ActivityManagerNative.getDefault().stopAppSwitches();
1560 } catch (RemoteException e) {
1561 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05001562 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001563 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001564 }
1565 }
1566
1567 public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
1568 final int fl = attrs.flags;
1569
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07001570 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001571 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07001572 contentInset.set(mCurLeft, mCurTop,
Joe Onorato29fc2c92010-11-24 10:26:50 -08001573 (mRestrictedScreenLeft+mRestrictedScreenWidth) - mCurRight,
1574 (mRestrictedScreenTop+mRestrictedScreenHeight) - mCurBottom);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001575 } else {
1576 contentInset.setEmpty();
1577 }
1578 }
1579
1580 /** {@inheritDoc} */
1581 public void beginLayoutLw(int displayWidth, int displayHeight) {
Joe Onorato29fc2c92010-11-24 10:26:50 -08001582 mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
1583 mUnrestrictedScreenWidth = displayWidth;
1584 mUnrestrictedScreenHeight = displayHeight;
1585 mRestrictedScreenLeft = mRestrictedScreenTop = 0;
1586 mRestrictedScreenWidth = displayWidth;
1587 mRestrictedScreenHeight = displayHeight;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001588 mDockLeft = mContentLeft = mCurLeft = 0;
1589 mDockTop = mContentTop = mCurTop = 0;
1590 mDockRight = mContentRight = mCurRight = displayWidth;
1591 mDockBottom = mContentBottom = mCurBottom = displayHeight;
1592 mDockLayer = 0x10000000;
1593
1594 // decide where the status bar goes ahead of time
1595 if (mStatusBar != null) {
1596 final Rect pf = mTmpParentFrame;
1597 final Rect df = mTmpDisplayFrame;
1598 final Rect vf = mTmpVisibleFrame;
1599 pf.left = df.left = vf.left = 0;
1600 pf.top = df.top = vf.top = 0;
1601 pf.right = df.right = vf.right = displayWidth;
1602 pf.bottom = df.bottom = vf.bottom = displayHeight;
1603
1604 mStatusBar.computeFrameLw(pf, df, vf, vf);
1605 if (mStatusBar.isVisibleLw()) {
1606 // If the status bar is hidden, we don't want to cause
1607 // windows behind it to scroll.
Joe Onorato34bcebc2010-07-07 18:05:01 -04001608 final Rect r = mStatusBar.getFrameLw();
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07001609 if (mStatusBarCanHide) {
1610 // Status bar may go away, so the screen area it occupies
1611 // is available to apps but just covering them when the
1612 // status bar is visible.
1613 if (mDockTop == r.top) mDockTop = r.bottom;
1614 else if (mDockBottom == r.bottom) mDockBottom = r.top;
1615 mContentTop = mCurTop = mDockTop;
1616 mContentBottom = mCurBottom = mDockBottom;
1617 if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockTop=" + mDockTop
1618 + " mContentTop=" + mContentTop
1619 + " mCurTop=" + mCurTop
1620 + " mDockBottom=" + mDockBottom
1621 + " mContentBottom=" + mContentBottom
1622 + " mCurBottom=" + mCurBottom);
1623 } else {
1624 // Status bar can't go away; the part of the screen it
1625 // covers does not exist for anything behind it.
Joe Onorato29fc2c92010-11-24 10:26:50 -08001626 if (mRestrictedScreenTop == r.top) {
1627 mRestrictedScreenTop = r.bottom;
1628 mRestrictedScreenHeight -= (r.bottom-r.top);
1629 } else if ((mRestrictedScreenHeight-mRestrictedScreenTop) == r.bottom) {
1630 mRestrictedScreenHeight -= (r.bottom-r.top);
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07001631 }
Joe Onorato29fc2c92010-11-24 10:26:50 -08001632 mContentTop = mCurTop = mDockTop = mRestrictedScreenTop;
1633 mContentBottom = mCurBottom = mDockBottom
1634 = mRestrictedScreenTop + mRestrictedScreenHeight;
1635 if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mRestrictedScreenTop="
1636 + mRestrictedScreenTop
1637 + " mRestrictedScreenHeight=" + mRestrictedScreenHeight);
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07001638 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001639 }
1640 }
1641 }
1642
Dianne Hackborndea3ef72010-10-28 14:24:22 -07001643 void setAttachedWindowFrames(WindowState win, int fl, int adjust,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001644 WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
1645 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
1646 // Here's a special case: if this attached window is a panel that is
1647 // above the dock window, and the window it is attached to is below
1648 // the dock window, then the frames we computed for the window it is
1649 // attached to can not be used because the dock is effectively part
1650 // of the underlying window and the attached window is floating on top
1651 // of the whole thing. So, we ignore the attached window and explicitly
1652 // compute the frames that would be appropriate without the dock.
1653 df.left = cf.left = vf.left = mDockLeft;
1654 df.top = cf.top = vf.top = mDockTop;
1655 df.right = cf.right = vf.right = mDockRight;
1656 df.bottom = cf.bottom = vf.bottom = mDockBottom;
1657 } else {
1658 // The effective display frame of the attached window depends on
1659 // whether it is taking care of insetting its content. If not,
1660 // we need to use the parent's content frame so that the entire
1661 // window is positioned within that content. Otherwise we can use
1662 // the display frame and let the attached window take care of
1663 // positioning its content appropriately.
Dianne Hackborndea3ef72010-10-28 14:24:22 -07001664 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001665 cf.set(attached.getDisplayFrameLw());
1666 } else {
1667 // If the window is resizing, then we want to base the content
1668 // frame on our attached content frame to resize... however,
1669 // things can be tricky if the attached window is NOT in resize
1670 // mode, in which case its content frame will be larger.
1671 // Ungh. So to deal with that, make sure the content frame
1672 // we end up using is not covering the IM dock.
1673 cf.set(attached.getContentFrameLw());
1674 if (attached.getSurfaceLayer() < mDockLayer) {
1675 if (cf.left < mContentLeft) cf.left = mContentLeft;
1676 if (cf.top < mContentTop) cf.top = mContentTop;
1677 if (cf.right > mContentRight) cf.right = mContentRight;
1678 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
1679 }
1680 }
1681 df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
1682 vf.set(attached.getVisibleFrameLw());
1683 }
1684 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
1685 // window should be positioned relative to its parent or the entire
1686 // screen.
1687 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
1688 ? attached.getFrameLw() : df);
1689 }
1690
1691 /** {@inheritDoc} */
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001692 public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
1693 WindowState attached) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001694 // we've already done the status bar
1695 if (win == mStatusBar) {
1696 return;
1697 }
1698
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001699 final int fl = attrs.flags;
1700 final int sim = attrs.softInputMode;
1701
1702 final Rect pf = mTmpParentFrame;
1703 final Rect df = mTmpDisplayFrame;
1704 final Rect cf = mTmpContentFrame;
1705 final Rect vf = mTmpVisibleFrame;
1706
1707 if (attrs.type == TYPE_INPUT_METHOD) {
1708 pf.left = df.left = cf.left = vf.left = mDockLeft;
1709 pf.top = df.top = cf.top = vf.top = mDockTop;
1710 pf.right = df.right = cf.right = vf.right = mDockRight;
1711 pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
1712 // IM dock windows always go to the bottom of the screen.
1713 attrs.gravity = Gravity.BOTTOM;
1714 mDockLayer = win.getSurfaceLayer();
1715 } else {
Dianne Hackborndea3ef72010-10-28 14:24:22 -07001716 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
1717
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07001718 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001719 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
1720 // This is the case for a normal activity window: we want it
1721 // to cover all of the screen space, and it can take care of
1722 // moving its contents to account for screen decorations that
1723 // intrude into that space.
1724 if (attached != null) {
1725 // If this window is attached to another, our display
1726 // frame is the same as the one we are attached to.
1727 setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
1728 } else {
Joe Onorato29fc2c92010-11-24 10:26:50 -08001729 if (attrs.type == TYPE_STATUS_BAR_PANEL) {
1730 // Status bar panels are the only windows who can go on top of
1731 // the status bar. They are protected by the STATUS_BAR_SERVICE
1732 // permission, so they have the same privileges as the status
1733 // bar itself.
1734 pf.left = df.left = mUnrestrictedScreenLeft;
1735 pf.top = df.top = mUnrestrictedScreenTop;
1736 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
1737 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
1738 } else {
1739 pf.left = df.left = mRestrictedScreenLeft;
1740 pf.top = df.top = mRestrictedScreenTop;
1741 pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
1742 pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
1743 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07001744 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001745 cf.left = mDockLeft;
1746 cf.top = mDockTop;
1747 cf.right = mDockRight;
1748 cf.bottom = mDockBottom;
1749 } else {
1750 cf.left = mContentLeft;
1751 cf.top = mContentTop;
1752 cf.right = mContentRight;
1753 cf.bottom = mContentBottom;
1754 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07001755 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
1756 vf.left = mCurLeft;
1757 vf.top = mCurTop;
1758 vf.right = mCurRight;
1759 vf.bottom = mCurBottom;
1760 } else {
1761 vf.set(cf);
1762 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001763 }
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07001764 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001765 // A window that has requested to fill the entire screen just
1766 // gets everything, period.
Joe Onorato29fc2c92010-11-24 10:26:50 -08001767 if (attrs.type == TYPE_STATUS_BAR_PANEL) {
1768 pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
1769 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
1770 pf.right = df.right = cf.right
1771 = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
1772 pf.bottom = df.bottom = cf.bottom
1773 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
1774 } else {
1775 pf.left = df.left = cf.left = mRestrictedScreenLeft;
1776 pf.top = df.top = cf.top = mRestrictedScreenTop;
1777 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
1778 pf.bottom = df.bottom = cf.bottom
1779 = mRestrictedScreenTop+mRestrictedScreenHeight;
1780 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07001781 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
1782 vf.left = mCurLeft;
1783 vf.top = mCurTop;
1784 vf.right = mCurRight;
1785 vf.bottom = mCurBottom;
1786 } else {
1787 vf.set(cf);
1788 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001789 } else if (attached != null) {
1790 // A child window should be placed inside of the same visible
1791 // frame that its parent had.
Dianne Hackborndea3ef72010-10-28 14:24:22 -07001792 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001793 } else {
1794 // Otherwise, a normal window must be placed inside the content
1795 // of all screen decorations.
1796 pf.left = mContentLeft;
1797 pf.top = mContentTop;
1798 pf.right = mContentRight;
1799 pf.bottom = mContentBottom;
Dianne Hackborndea3ef72010-10-28 14:24:22 -07001800 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001801 df.left = cf.left = mDockLeft;
1802 df.top = cf.top = mDockTop;
1803 df.right = cf.right = mDockRight;
1804 df.bottom = cf.bottom = mDockBottom;
1805 } else {
1806 df.left = cf.left = mContentLeft;
1807 df.top = cf.top = mContentTop;
1808 df.right = cf.right = mContentRight;
1809 df.bottom = cf.bottom = mContentBottom;
1810 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07001811 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
1812 vf.left = mCurLeft;
1813 vf.top = mCurTop;
1814 vf.right = mCurRight;
1815 vf.bottom = mCurBottom;
1816 } else {
1817 vf.set(cf);
1818 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001819 }
1820 }
1821
1822 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
1823 df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
1824 df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
1825 }
1826
The Android Open Source Project11267662009-03-18 17:39:47 -07001827 if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
1828 + ": sim=#" + Integer.toHexString(sim)
1829 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
1830 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
1831
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001832 win.computeFrameLw(pf, df, cf, vf);
1833
1834 // Dock windows carve out the bottom of the screen, so normal windows
1835 // can't appear underneath them.
1836 if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
1837 int top = win.getContentFrameLw().top;
1838 top += win.getGivenContentInsetsLw().top;
1839 if (mContentBottom > top) {
1840 mContentBottom = top;
1841 }
1842 top = win.getVisibleFrameLw().top;
1843 top += win.getGivenVisibleInsetsLw().top;
1844 if (mCurBottom > top) {
1845 mCurBottom = top;
1846 }
The Android Open Source Project11267662009-03-18 17:39:47 -07001847 if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom="
1848 + mDockBottom + " mContentBottom="
1849 + mContentBottom + " mCurBottom=" + mCurBottom);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001850 }
1851 }
1852
1853 /** {@inheritDoc} */
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001854 public int finishLayoutLw() {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08001855 return 0;
1856 }
1857
1858 /** {@inheritDoc} */
1859 public void beginAnimationLw(int displayWidth, int displayHeight) {
1860 mTopFullscreenOpaqueWindowState = null;
1861 mForceStatusBar = false;
1862
1863 mHideLockScreen = false;
1864 mAllowLockscreenWhenOn = false;
1865 mDismissKeyguard = false;
1866 }
1867
1868 /** {@inheritDoc} */
1869 public void animatingWindowLw(WindowState win,
1870 WindowManager.LayoutParams attrs) {
1871 if (mTopFullscreenOpaqueWindowState == null &&
1872 win.isVisibleOrBehindKeyguardLw()) {
1873 if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
1874 mForceStatusBar = true;
1875 }
1876 if (attrs.type >= FIRST_APPLICATION_WINDOW
1877 && attrs.type <= LAST_APPLICATION_WINDOW
Dianne Hackborn6493e642010-10-01 13:06:30 -07001878 && attrs.x == 0 && attrs.y == 0
1879 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
1880 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08001881 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win);
1882 mTopFullscreenOpaqueWindowState = win;
1883 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
1884 if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
1885 mHideLockScreen = true;
1886 }
1887 if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
1888 if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win);
1889 mDismissKeyguard = true;
1890 }
1891 if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
1892 mAllowLockscreenWhenOn = true;
1893 }
1894 }
1895 }
1896 }
1897
1898 /** {@inheritDoc} */
1899 public int finishAnimationLw() {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001900 int changes = 0;
Joe Onorato93056472010-09-10 10:30:46 -04001901 boolean topIsFullscreen = false;
Daniel Sandlere02d8082010-10-08 15:13:22 -04001902
1903 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
1904 ? mTopFullscreenOpaqueWindowState.getAttrs()
1905 : null;
1906
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001907 if (mStatusBar != null) {
Dianne Hackbornd70bc2f2009-10-06 23:25:51 -07001908 if (localLOGV) Log.i(TAG, "force=" + mForceStatusBar
1909 + " top=" + mTopFullscreenOpaqueWindowState);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001910 if (mForceStatusBar) {
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001911 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001912 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001913 } else if (mTopFullscreenOpaqueWindowState != null) {
Joe Onorato93056472010-09-10 10:30:46 -04001914 if (localLOGV) {
1915 Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
1916 + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
1917 Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
1918 + " lp.flags=0x" + Integer.toHexString(lp.flags));
1919 }
1920 topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
1921 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
1922 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
1923 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
1924 // case though.
1925 if (topIsFullscreen) {
Daniel Sandler40427442010-07-16 11:44:52 -04001926 if (mStatusBarCanHide) {
1927 if (DEBUG_LAYOUT) Log.v(TAG, "Hiding status bar");
1928 if (mStatusBar.hideLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
Daniel Sandler40427442010-07-16 11:44:52 -04001929 } else if (localLOGV) {
1930 Log.v(TAG, "Preventing status bar from hiding by policy");
1931 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001932 } else {
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001933 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001934 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001935 }
1936 }
1937 }
Daniel Sandlere02d8082010-10-08 15:13:22 -04001938
1939 boolean topNeedsMenu = mShowMenuKey;
1940 if (lp != null) {
1941 topNeedsMenu = (lp.flags & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0;
1942 }
1943
1944 if (DEBUG_LAYOUT) Log.v(TAG, "Top window "
1945 + (topNeedsMenu ? "needs" : "does not need")
1946 + " the MENU key");
1947
Joe Onorato644f9c32011-01-25 12:06:23 -08001948 mTopIsFullscreen = topIsFullscreen;
Daniel Sandlere02d8082010-10-08 15:13:22 -04001949 final boolean changedMenu = (topNeedsMenu != mShowMenuKey);
1950
Joe Onorato644f9c32011-01-25 12:06:23 -08001951 if (changedMenu) {
Daniel Sandlere02d8082010-10-08 15:13:22 -04001952 final boolean topNeedsMenuF = topNeedsMenu;
1953
Daniel Sandlere02d8082010-10-08 15:13:22 -04001954 mShowMenuKey = topNeedsMenu;
1955
Joe Onorato93056472010-09-10 10:30:46 -04001956 mHandler.post(new Runnable() {
1957 public void run() {
1958 if (mStatusBarService == null) {
1959 // This is the one that can not go away, but it doesn't come up
1960 // before the window manager does, so don't fail if it doesn't
1961 // exist. This works as long as no fullscreen windows come up
1962 // before the status bar service does.
1963 mStatusBarService = IStatusBarService.Stub.asInterface(
1964 ServiceManager.getService("statusbar"));
1965 }
1966 final IStatusBarService sbs = mStatusBarService;
1967 if (mStatusBarService != null) {
1968 try {
Daniel Sandlere02d8082010-10-08 15:13:22 -04001969 if (changedMenu) {
1970 sbs.setMenuKeyVisible(topNeedsMenuF);
1971 }
Joe Onorato93056472010-09-10 10:30:46 -04001972 } catch (RemoteException e) {
1973 // This should be impossible because we're in the same process.
1974 mStatusBarService = null;
1975 }
1976 }
1977 }
1978 });
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08001979 }
1980
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07001981 // Hide the key guard if a visible window explicitly specifies that it wants to be displayed
1982 // when the screen is locked
1983 if (mKeyguard != null) {
Joe Onorato93056472010-09-10 10:30:46 -04001984 if (localLOGV) Log.v(TAG, "finishAnimationLw::mHideKeyguard="+mHideLockScreen);
Dianne Hackborn05726582009-09-22 17:28:24 -07001985 if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
Dianne Hackborn08743722009-12-21 12:16:51 -08001986 if (mKeyguard.hideLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001987 changes |= FINISH_LAYOUT_REDO_LAYOUT
1988 | FINISH_LAYOUT_REDO_CONFIG
1989 | FINISH_LAYOUT_REDO_WALLPAPER;
1990 }
Dianne Hackborn05726582009-09-22 17:28:24 -07001991 if (mKeyguardMediator.isShowing()) {
Dianne Hackbornb446e972009-09-20 15:23:25 -07001992 mHandler.post(new Runnable() {
1993 public void run() {
Dianne Hackborn05726582009-09-22 17:28:24 -07001994 mKeyguardMediator.keyguardDone(false, false);
Dianne Hackbornb446e972009-09-20 15:23:25 -07001995 }
1996 });
1997 }
Dianne Hackborn05726582009-09-22 17:28:24 -07001998 } else if (mHideLockScreen) {
Dianne Hackborn08743722009-12-21 12:16:51 -08001999 if (mKeyguard.hideLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002000 changes |= FINISH_LAYOUT_REDO_LAYOUT
2001 | FINISH_LAYOUT_REDO_CONFIG
2002 | FINISH_LAYOUT_REDO_WALLPAPER;
2003 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05002004 mKeyguardMediator.setHidden(true);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002005 } else {
Dianne Hackborn08743722009-12-21 12:16:51 -08002006 if (mKeyguard.showLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002007 changes |= FINISH_LAYOUT_REDO_LAYOUT
2008 | FINISH_LAYOUT_REDO_CONFIG
2009 | FINISH_LAYOUT_REDO_WALLPAPER;
2010 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05002011 mKeyguardMediator.setHidden(false);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002012 }
2013 }
Joe Onorato664644d2011-01-23 17:53:23 -08002014
2015 updateSystemUiVisibility();
2016
Mike Lockwood28569302010-01-28 11:54:40 -05002017 // update since mAllowLockscreenWhenOn might have changed
2018 updateLockScreenTimeout();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002019 return changes;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002020 }
2021
Dianne Hackborn08743722009-12-21 12:16:51 -08002022 public boolean allowAppAnimationsLw() {
2023 if (mKeyguard != null && mKeyguard.isVisibleLw()) {
2024 // If keyguard is currently visible, no reason to animate
2025 // behind it.
2026 return false;
2027 }
Dianne Hackborn08121bc2011-01-17 17:54:31 -08002028 if (false) {
2029 // Don't do this on the tablet, since the system bar never completely
2030 // covers the screen, and with all its transparency this will
2031 // incorrectly think it does cover it when it doesn't. We'll revisit
2032 // this later when we re-do the phone status bar.
2033 if (mStatusBar != null && mStatusBar.isVisibleLw()) {
2034 Rect rect = new Rect(mStatusBar.getShownFrameLw());
2035 for (int i=mStatusBarPanels.size()-1; i>=0; i--) {
2036 WindowState w = mStatusBarPanels.get(i);
2037 if (w.isVisibleLw()) {
2038 rect.union(w.getShownFrameLw());
2039 }
Dianne Hackborn08743722009-12-21 12:16:51 -08002040 }
Dianne Hackborn08121bc2011-01-17 17:54:31 -08002041 final int insetw = mRestrictedScreenWidth/10;
2042 final int inseth = mRestrictedScreenHeight/10;
2043 if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw,
2044 mRestrictedScreenHeight-inseth)) {
2045 // All of the status bar windows put together cover the
2046 // screen, so the app can't be seen. (Note this test doesn't
2047 // work if the rects of these windows are at off offsets or
2048 // sizes, causing gaps in the rect union we have computed.)
2049 return false;
2050 }
Dianne Hackborn08743722009-12-21 12:16:51 -08002051 }
2052 }
2053 return true;
2054 }
2055
Joe Onorato664644d2011-01-23 17:53:23 -08002056 public void focusChanged(WindowState lastFocus, WindowState newFocus) {
2057 mFocusedWindow = newFocus;
2058 updateSystemUiVisibility();
2059 }
2060
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07002061 /** {@inheritDoc} */
Jeff Brown46b9ac02010-04-22 18:58:52 -07002062 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
2063 // lid changed state
Jeff Brown4aed78b2011-01-14 17:36:55 -08002064 mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED;
2065 boolean awakeNow = mKeyguardMediator.doLidChangeTq(lidOpen);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002066 updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
2067 if (awakeNow) {
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002068 // If the lid is opening and we don't have to keep the
Jeff Brown46b9ac02010-04-22 18:58:52 -07002069 // keyguard up, then we can turn on the screen
2070 // immediately.
2071 mKeyguardMediator.pokeWakelock();
2072 } else if (keyguardIsShowingTq()) {
Jeff Brown4aed78b2011-01-14 17:36:55 -08002073 if (lidOpen) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002074 // If we are opening the lid and not hiding the
2075 // keyguard, then we need to have it turn on the
2076 // screen once it is shown.
2077 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
2078 KeyEvent.KEYCODE_POWER);
2079 }
2080 } else {
2081 // Light up the keyboard if we are sliding up.
Jeff Brown4aed78b2011-01-14 17:36:55 -08002082 if (lidOpen) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002083 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
2084 LocalPowerManager.BUTTON_EVENT);
2085 } else {
2086 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
2087 LocalPowerManager.OTHER_EVENT);
2088 }
2089 }
2090 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002091
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002092 void setHdmiPlugged(boolean plugged) {
2093 if (mHdmiPlugged != plugged) {
2094 mHdmiPlugged = plugged;
2095 updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
2096 Intent intent = new Intent(ACTION_HDMI_PLUGGED);
Joe Onoratodc100302011-01-11 17:07:41 -08002097 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002098 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
2099 mContext.sendStickyBroadcast(intent);
2100 }
2101 }
2102
Joe Onoratodc100302011-01-11 17:07:41 -08002103 boolean readHdmiState() {
2104 final String filename = "/sys/class/switch/hdmi/state";
2105 FileReader reader = null;
2106 try {
2107 reader = new FileReader(filename);
2108 char[] buf = new char[15];
2109 int n = reader.read(buf);
2110 if (n > 1) {
2111 return 0 != Integer.parseInt(new String(buf, 0, n-1));
2112 } else {
2113 return false;
2114 }
2115 } catch (IOException ex) {
2116 Slog.d(TAG, "couldn't read hdmi state from " + filename + ": " + ex);
2117 return false;
2118 } catch (NumberFormatException ex) {
2119 Slog.d(TAG, "couldn't read hdmi state from " + filename + ": " + ex);
2120 return false;
2121 } finally {
2122 if (reader != null) {
2123 try {
2124 reader.close();
2125 } catch (IOException ex) {
2126 }
2127 }
2128 }
2129 }
2130
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002131 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002132 * @return Whether music is being played right now.
2133 */
2134 boolean isMusicActive() {
Eric Laurent413cb9d2009-07-17 11:52:43 -07002135 final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
2136 if (am == null) {
2137 Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002138 return false;
2139 }
Eric Laurent413cb9d2009-07-17 11:52:43 -07002140 return am.isMusicActive();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002141 }
2142
2143 /**
2144 * Tell the audio service to adjust the volume appropriate to the event.
2145 * @param keycode
2146 */
Mike Lockwooda53e3812009-09-25 10:51:39 -04002147 void handleVolumeKey(int stream, int keycode) {
Jeff Brown4d396052010-10-29 21:50:21 -07002148 IAudioService audioService = getAudioService();
2149 if (audioService == null) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002150 return;
2151 }
2152 try {
2153 // since audio is playing, we shouldn't have to hold a wake lock
2154 // during the call, but we do it as a precaution for the rare possibility
2155 // that the music stops right before we call this
Jeff Brownb0418da2010-11-01 15:24:01 -07002156 // TODO: Actually handle MUTE.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002157 mBroadcastWakeLock.acquire();
Jeff Brown4d396052010-10-29 21:50:21 -07002158 audioService.adjustStreamVolume(stream,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002159 keycode == KeyEvent.KEYCODE_VOLUME_UP
2160 ? AudioManager.ADJUST_RAISE
2161 : AudioManager.ADJUST_LOWER,
2162 0);
2163 } catch (RemoteException e) {
2164 Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e);
2165 } finally {
2166 mBroadcastWakeLock.release();
2167 }
2168 }
Jeff Brown4d396052010-10-29 21:50:21 -07002169
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002170 /** {@inheritDoc} */
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002171 @Override
Jeff Brown1f245102010-11-18 20:53:46 -08002172 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
2173 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
2174 final boolean canceled = event.isCanceled();
2175 final int keyCode = event.getKeyCode();
Jeff Browne20c9e02010-10-11 14:20:19 -07002176
Jeff Brown3122e442010-10-11 23:32:49 -07002177 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
Jeff Brown3122e442010-10-11 23:32:49 -07002178
Mike Lockwoodc72b15f2009-11-28 20:58:22 -05002179 // If screen is off then we treat the case where the keyguard is open but hidden
2180 // the same as if it were open and in front.
2181 // This will prevent any keys other than the power button from waking the screen
2182 // when the keyguard is hidden by another activity.
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002183 final boolean keyguardActive = (isScreenOn ?
Mike Lockwoodc72b15f2009-11-28 20:58:22 -05002184 mKeyguardMediator.isShowingAndNotHidden() :
2185 mKeyguardMediator.isShowing());
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002186
2187 if (false) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002188 Log.d(TAG, "interceptKeyTq keycode=" + keyCode
2189 + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002190 }
2191
Jeff Brown4d396052010-10-29 21:50:21 -07002192 if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0) {
2193 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
2194 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002195
Jeff Brown4d396052010-10-29 21:50:21 -07002196 // Basic policy based on screen state and keyguard.
2197 // FIXME: This policy isn't quite correct. We shouldn't care whether the screen
2198 // is on or off, really. We should care about whether the device is in an
2199 // interactive state or is in suspend pretending to be "off".
2200 // The primary screen might be turned off due to proximity sensor or
2201 // because we are presenting media on an auxiliary screen or remotely controlling
2202 // the device some other way (which is why we have an exemption here for injected
2203 // events).
2204 int result;
2205 if (isScreenOn || isInjected) {
2206 // When the screen is on or if the key is injected pass the key to the application.
2207 result = ACTION_PASS_TO_USER;
2208 } else {
2209 // When the screen is off and the key is not injected, determine whether
2210 // to wake the device but don't pass the key to the application.
2211 result = 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002212
Jeff Brown4d396052010-10-29 21:50:21 -07002213 final boolean isWakeKey = (policyFlags
2214 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
2215 if (down && isWakeKey) {
2216 if (keyguardActive) {
2217 // If the keyguard is showing, let it decide what to do with the wake key.
2218 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode);
2219 } else {
2220 // Otherwise, wake the device ourselves.
2221 result |= ACTION_POKE_USER_ACTIVITY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002222 }
2223 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002224 }
2225
Jeff Brown4d396052010-10-29 21:50:21 -07002226 // Handle special keys.
2227 switch (keyCode) {
2228 case KeyEvent.KEYCODE_VOLUME_DOWN:
Jeff Brownb0418da2010-11-01 15:24:01 -07002229 case KeyEvent.KEYCODE_VOLUME_UP:
2230 case KeyEvent.KEYCODE_VOLUME_MUTE: {
Jeff Brown4d396052010-10-29 21:50:21 -07002231 if (down) {
2232 ITelephony telephonyService = getTelephonyService();
2233 if (telephonyService != null) {
2234 try {
2235 if (telephonyService.isRinging()) {
2236 // If an incoming call is ringing, either VOLUME key means
2237 // "silence ringer". We handle these keys here, rather than
2238 // in the InCallScreen, to make sure we'll respond to them
2239 // even if the InCallScreen hasn't come to the foreground yet.
2240 // Look for the DOWN event here, to agree with the "fallback"
2241 // behavior in the InCallScreen.
2242 Log.i(TAG, "interceptKeyBeforeQueueing:"
2243 + " VOLUME key-down while ringing: Silence ringer!");
2244
2245 // Silence the ringer. (It's safe to call this
2246 // even if the ringer has already been silenced.)
2247 telephonyService.silenceRinger();
2248
2249 // And *don't* pass this key thru to the current activity
2250 // (which is probably the InCallScreen.)
2251 result &= ~ACTION_PASS_TO_USER;
2252 break;
2253 }
2254 if (telephonyService.isOffhook()
2255 && (result & ACTION_PASS_TO_USER) == 0) {
2256 // If we are in call but we decided not to pass the key to
2257 // the application, handle the volume change here.
2258 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
2259 break;
2260 }
2261 } catch (RemoteException ex) {
2262 Log.w(TAG, "ITelephony threw RemoteException", ex);
2263 }
2264 }
2265
2266 if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) {
2267 // If music is playing but we decided not to pass the key to the
2268 // application, handle the volume change here.
2269 handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
2270 break;
2271 }
2272 }
2273 break;
2274 }
2275
2276 case KeyEvent.KEYCODE_ENDCALL: {
2277 result &= ~ACTION_PASS_TO_USER;
2278 if (down) {
2279 ITelephony telephonyService = getTelephonyService();
2280 boolean hungUp = false;
2281 if (telephonyService != null) {
2282 try {
2283 hungUp = telephonyService.endCall();
2284 } catch (RemoteException ex) {
2285 Log.w(TAG, "ITelephony threw RemoteException", ex);
2286 }
2287 }
2288 interceptPowerKeyDown(!isScreenOn || hungUp);
2289 } else {
2290 if (interceptPowerKeyUp(canceled)) {
2291 if ((mEndcallBehavior
2292 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
2293 if (goHome()) {
2294 break;
Dianne Hackborn0041e972009-07-24 17:14:43 -07002295 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002296 }
Jeff Brown4d396052010-10-29 21:50:21 -07002297 if ((mEndcallBehavior
2298 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
2299 result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
2300 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002301 }
Jeff Brown4d396052010-10-29 21:50:21 -07002302 }
2303 break;
2304 }
2305
2306 case KeyEvent.KEYCODE_POWER: {
2307 result &= ~ACTION_PASS_TO_USER;
2308 if (down) {
2309 ITelephony telephonyService = getTelephonyService();
2310 boolean hungUp = false;
2311 if (telephonyService != null) {
2312 try {
2313 if (telephonyService.isRinging()) {
2314 // Pressing Power while there's a ringing incoming
2315 // call should silence the ringer.
2316 telephonyService.silenceRinger();
2317 } else if ((mIncallPowerBehavior
2318 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
2319 && telephonyService.isOffhook()) {
2320 // Otherwise, if "Power button ends call" is enabled,
2321 // the Power button will hang up any current active call.
2322 hungUp = telephonyService.endCall();
2323 }
2324 } catch (RemoteException ex) {
2325 Log.w(TAG, "ITelephony threw RemoteException", ex);
2326 }
2327 }
2328 interceptPowerKeyDown(!isScreenOn || hungUp);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002329 } else {
Jeff Brown4d396052010-10-29 21:50:21 -07002330 if (interceptPowerKeyUp(canceled)) {
2331 result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002332 }
Jeff Brown4d396052010-10-29 21:50:21 -07002333 }
2334 break;
2335 }
2336
2337 case KeyEvent.KEYCODE_MEDIA_PLAY:
2338 case KeyEvent.KEYCODE_MEDIA_PAUSE:
2339 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
2340 if (down) {
2341 ITelephony telephonyService = getTelephonyService();
2342 if (telephonyService != null) {
2343 try {
2344 if (!telephonyService.isIdle()) {
2345 // Suppress PLAY/PAUSE toggle when phone is ringing or in-call
2346 // to avoid music playback.
2347 break;
2348 }
2349 } catch (RemoteException ex) {
2350 Log.w(TAG, "ITelephony threw RemoteException", ex);
Jeff Brown3122e442010-10-11 23:32:49 -07002351 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002352 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002353 }
Jeff Brown4d396052010-10-29 21:50:21 -07002354 case KeyEvent.KEYCODE_HEADSETHOOK:
2355 case KeyEvent.KEYCODE_MUTE:
2356 case KeyEvent.KEYCODE_MEDIA_STOP:
2357 case KeyEvent.KEYCODE_MEDIA_NEXT:
2358 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
2359 case KeyEvent.KEYCODE_MEDIA_REWIND:
2360 case KeyEvent.KEYCODE_MEDIA_RECORD:
2361 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
2362 if ((result & ACTION_PASS_TO_USER) == 0) {
2363 // Only do this if we would otherwise not pass it to the user. In that
2364 // case, the PhoneWindow class will do the same thing, except it will
2365 // only do it if the showing app doesn't process the key on its own.
Jeff Brown4d396052010-10-29 21:50:21 -07002366 mBroadcastWakeLock.acquire();
Jeff Brown1f245102010-11-18 20:53:46 -08002367 mHandler.post(new PassHeadsetKey(new KeyEvent(event)));
Jeff Brown4d396052010-10-29 21:50:21 -07002368 }
2369 break;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002370 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002371
Jeff Brown4d396052010-10-29 21:50:21 -07002372 case KeyEvent.KEYCODE_CALL: {
2373 if (down) {
2374 ITelephony telephonyService = getTelephonyService();
2375 if (telephonyService != null) {
2376 try {
2377 if (telephonyService.isRinging()) {
2378 Log.i(TAG, "interceptKeyBeforeQueueing:"
2379 + " CALL key-down while ringing: Answer the call!");
2380 telephonyService.answerRingingCall();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002381
Jeff Brown4d396052010-10-29 21:50:21 -07002382 // And *don't* pass this key thru to the current activity
2383 // (which is presumably the InCallScreen.)
2384 result &= ~ACTION_PASS_TO_USER;
2385 }
2386 } catch (RemoteException ex) {
2387 Log.w(TAG, "ITelephony threw RemoteException", ex);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002388 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002389 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002390 }
Jeff Brown4d396052010-10-29 21:50:21 -07002391 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002392 }
2393 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002394 return result;
2395 }
2396
Jeff Brown56194eb2011-03-02 19:23:13 -08002397 /** {@inheritDoc} */
2398 @Override
2399 public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
2400 int result = 0;
2401
2402 final boolean isWakeMotion = (policyFlags
2403 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
2404 if (isWakeMotion) {
2405 if (mKeyguardMediator.isShowing()) {
2406 // If the keyguard is showing, let it decide what to do with the wake motion.
2407 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
2408 } else {
2409 // Otherwise, wake the device ourselves.
2410 result |= ACTION_POKE_USER_ACTIVITY;
2411 }
2412 }
2413 return result;
2414 }
2415
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002416 class PassHeadsetKey implements Runnable {
2417 KeyEvent mKeyEvent;
2418
2419 PassHeadsetKey(KeyEvent keyEvent) {
2420 mKeyEvent = keyEvent;
2421 }
2422
2423 public void run() {
2424 if (ActivityManagerNative.isSystemReady()) {
2425 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
2426 intent.putExtra(Intent.EXTRA_KEY_EVENT, mKeyEvent);
2427 mContext.sendOrderedBroadcast(intent, null, mBroadcastDone,
2428 mHandler, Activity.RESULT_OK, null, null);
2429 }
2430 }
2431 }
2432
2433 BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
2434 public void onReceive(Context context, Intent intent) {
2435 mBroadcastWakeLock.release();
2436 }
2437 };
Mike Lockwood1753f7f2009-08-24 14:49:07 -07002438
2439 BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
2440 public void onReceive(Context context, Intent intent) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07002441 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
2442 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
2443 Intent.EXTRA_DOCK_STATE_UNDOCKED);
2444 } else {
2445 try {
2446 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
2447 ServiceManager.getService(Context.UI_MODE_SERVICE));
2448 mUiMode = uiModeService.getCurrentModeType();
2449 } catch (RemoteException e) {
2450 }
Dianne Hackborn80fa1662009-10-07 14:02:10 -07002451 }
Mike Lockwood1753f7f2009-08-24 14:49:07 -07002452 updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
Mike Lockwoode9867d22009-09-20 01:59:02 -04002453 updateOrientationListenerLp();
Mike Lockwood1753f7f2009-08-24 14:49:07 -07002454 }
2455 };
2456
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002457 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002458 public void screenTurnedOff(int why) {
Dianne Hackborn74489012009-03-24 20:50:09 -07002459 EventLog.writeEvent(70000, 0);
2460 mKeyguardMediator.onScreenTurnedOff(why);
The Android Open Source Project0727d222009-03-11 12:11:58 -07002461 synchronized (mLock) {
The Android Open Source Project0727d222009-03-11 12:11:58 -07002462 mScreenOn = false;
2463 updateOrientationListenerLp();
Mike Lockwood28569302010-01-28 11:54:40 -05002464 updateLockScreenTimeout();
The Android Open Source Project0727d222009-03-11 12:11:58 -07002465 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002466 }
2467
2468 /** {@inheritDoc} */
2469 public void screenTurnedOn() {
Dianne Hackborn74489012009-03-24 20:50:09 -07002470 EventLog.writeEvent(70000, 1);
2471 mKeyguardMediator.onScreenTurnedOn();
The Android Open Source Project0727d222009-03-11 12:11:58 -07002472 synchronized (mLock) {
The Android Open Source Project0727d222009-03-11 12:11:58 -07002473 mScreenOn = true;
2474 updateOrientationListenerLp();
Mike Lockwood28569302010-01-28 11:54:40 -05002475 updateLockScreenTimeout();
The Android Open Source Project0727d222009-03-11 12:11:58 -07002476 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002477 }
2478
2479 /** {@inheritDoc} */
Dianne Hackborn08743722009-12-21 12:16:51 -08002480 public boolean isScreenOn() {
2481 return mScreenOn;
2482 }
2483
2484 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002485 public void enableKeyguard(boolean enabled) {
2486 mKeyguardMediator.setKeyguardEnabled(enabled);
2487 }
2488
2489 /** {@inheritDoc} */
2490 public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
2491 mKeyguardMediator.verifyUnlock(callback);
2492 }
2493
Mike Lockwoodf7913302009-11-28 22:27:10 -05002494 private boolean keyguardIsShowingTq() {
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08002495 return mKeyguardMediator.isShowingAndNotHidden();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002496 }
2497
Mike Lockwood520d8bc2011-02-18 13:23:13 -05002498
2499 /** {@inheritDoc} */
2500 public boolean isKeyguardLocked() {
2501 return keyguardOn();
2502 }
2503
2504 /** {@inheritDoc} */
2505 public boolean isKeyguardSecure() {
2506 return mKeyguardMediator.isSecure();
2507 }
2508
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002509 /** {@inheritDoc} */
2510 public boolean inKeyguardRestrictedKeyInputMode() {
2511 return mKeyguardMediator.isInputRestricted();
2512 }
2513
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002514 void sendCloseSystemWindows() {
2515 sendCloseSystemWindows(mContext, null);
2516 }
2517
2518 void sendCloseSystemWindows(String reason) {
2519 sendCloseSystemWindows(mContext, reason);
2520 }
2521
2522 static void sendCloseSystemWindows(Context context, String reason) {
2523 if (ActivityManagerNative.isSystemReady()) {
Dianne Hackborn94a679d2009-07-28 17:51:07 -07002524 try {
2525 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
2526 } catch (RemoteException e) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002527 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002528 }
2529 }
2530
The Android Open Source Project0727d222009-03-11 12:11:58 -07002531 public int rotationForOrientationLw(int orientation, int lastRotation,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002532 boolean displayEnabled) {
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07002533
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05002534 if (false) {
2535 Slog.v(TAG, "rotationForOrientationLw(orient="
2536 + orientation + ", last=" + lastRotation
2537 + "); user=" + mUserRotation + " "
2538 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
2539 ? "USER_ROTATION_LOCKED" : "")
2540 );
2541 }
2542
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07002543 if (mPortraitRotation < 0) {
2544 // Initialize the rotation angles for each orientation once.
2545 Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
2546 .getDefaultDisplay();
2547 if (d.getWidth() > d.getHeight()) {
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07002548 mLandscapeRotation = Surface.ROTATION_0;
Steve Howarda7bfe6a2010-09-23 16:47:49 -07002549 mSeascapeRotation = Surface.ROTATION_180;
Dianne Hackborn07f3d662010-12-22 12:31:31 -08002550 if (mContext.getResources().getBoolean(
2551 com.android.internal.R.bool.config_reverseDefaultRotation)) {
2552 mPortraitRotation = Surface.ROTATION_90;
2553 mUpsideDownRotation = Surface.ROTATION_270;
2554 } else {
2555 mPortraitRotation = Surface.ROTATION_270;
2556 mUpsideDownRotation = Surface.ROTATION_90;
2557 }
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07002558 } else {
2559 mPortraitRotation = Surface.ROTATION_0;
Dianne Hackborne5439f22010-10-02 16:53:50 -07002560 mUpsideDownRotation = Surface.ROTATION_180;
Dianne Hackborn07f3d662010-12-22 12:31:31 -08002561 if (mContext.getResources().getBoolean(
2562 com.android.internal.R.bool.config_reverseDefaultRotation)) {
2563 mLandscapeRotation = Surface.ROTATION_270;
2564 mSeascapeRotation = Surface.ROTATION_90;
2565 } else {
2566 mLandscapeRotation = Surface.ROTATION_90;
2567 mSeascapeRotation = Surface.ROTATION_270;
2568 }
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07002569 }
2570 }
2571
The Android Open Source Project0727d222009-03-11 12:11:58 -07002572 synchronized (mLock) {
Dianne Hackborne5439f22010-10-02 16:53:50 -07002573 switch (orientation) {
2574 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
2575 //always return portrait if orientation set to portrait
2576 return mPortraitRotation;
2577 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
2578 //always return landscape if orientation set to landscape
2579 return mLandscapeRotation;
2580 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
2581 //always return portrait if orientation set to portrait
2582 return mUpsideDownRotation;
2583 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
2584 //always return seascape if orientation set to reverse landscape
2585 return mSeascapeRotation;
2586 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
2587 //return either landscape rotation based on the sensor
Dianne Hackborne5439f22010-10-02 16:53:50 -07002588 return getCurrentLandscapeRotation(lastRotation);
2589 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
Dianne Hackborne5439f22010-10-02 16:53:50 -07002590 return getCurrentPortraitRotation(lastRotation);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002591 }
Dianne Hackborne5439f22010-10-02 16:53:50 -07002592
The Android Open Source Project0727d222009-03-11 12:11:58 -07002593 // case for nosensor meaning ignore sensor and consider only lid
2594 // or orientation sensor disabled
2595 //or case.unspecified
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002596 if (mHdmiPlugged) {
2597 return Surface.ROTATION_0;
Jeff Brown4aed78b2011-01-14 17:36:55 -08002598 } else if (mLidOpen == LID_OPEN) {
Mike Lockwood1753f7f2009-08-24 14:49:07 -07002599 return mLidOpenRotation;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07002600 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04002601 return mCarDockRotation;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07002602 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04002603 return mDeskDockRotation;
Daniel Sandlerb73617d2010-08-17 00:41:00 -04002604 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
2605 return mUserRotation;
The Android Open Source Project0727d222009-03-11 12:11:58 -07002606 } else {
Dianne Hackborn03759ed2009-03-27 16:04:08 -07002607 if (useSensorForOrientationLp(orientation)) {
Jeff Brown4519f072011-01-23 13:16:01 -08002608 // Disable 180 degree rotation unless allowed by default for the device
2609 // or explicitly requested by the application.
2610 int rotation = mOrientationListener.getCurrentRotation(lastRotation);
2611 if (rotation == Surface.ROTATION_180
2612 && !mAllowAllRotations
2613 && orientation != ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) {
2614 return lastRotation;
2615 }
2616 return rotation;
The Android Open Source Project0727d222009-03-11 12:11:58 -07002617 }
2618 return Surface.ROTATION_0;
2619 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002620 }
2621 }
2622
Steve Howarda7bfe6a2010-09-23 16:47:49 -07002623 private int getCurrentLandscapeRotation(int lastRotation) {
Daniel Sandlere7e5ac22011-02-22 16:10:21 -05002624 // if the user has locked rotation, we ignore the sensor
2625 if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
2626 if (isLandscapeOrSeascape(mUserRotation)) {
2627 return mUserRotation;
2628 } else {
2629 // it seems odd to obey the sensor at all if rotation lock is enabled
2630 return mLandscapeRotation;
2631 }
2632 }
2633
Dianne Hackborne5439f22010-10-02 16:53:50 -07002634 int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
2635 if (isLandscapeOrSeascape(sensorRotation)) {
2636 return sensorRotation;
Steve Howarda7bfe6a2010-09-23 16:47:49 -07002637 }
2638 // try to preserve the old rotation if it was landscape
2639 if (isLandscapeOrSeascape(lastRotation)) {
2640 return lastRotation;
2641 }
Dianne Hackborne5439f22010-10-02 16:53:50 -07002642 // default to one of the primary landscape rotation
Steve Howarda7bfe6a2010-09-23 16:47:49 -07002643 return mLandscapeRotation;
2644 }
2645
2646 private boolean isLandscapeOrSeascape(int sensorRotation) {
2647 return sensorRotation == mLandscapeRotation || sensorRotation == mSeascapeRotation;
2648 }
2649
Dianne Hackborne5439f22010-10-02 16:53:50 -07002650 private int getCurrentPortraitRotation(int lastRotation) {
Daniel Sandlere7e5ac22011-02-22 16:10:21 -05002651 // if the user has locked rotation, we ignore the sensor
2652 if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
2653 if (isAnyPortrait(mUserRotation)) {
2654 return mUserRotation;
2655 } else {
2656 // it seems odd to obey the sensor at all if rotation lock is enabled
2657 return mPortraitRotation;
2658 }
2659 }
2660
Dianne Hackborne5439f22010-10-02 16:53:50 -07002661 int sensorRotation = mOrientationListener.getCurrentRotation(lastRotation);
2662 if (isAnyPortrait(sensorRotation)) {
2663 return sensorRotation;
2664 }
2665 // try to preserve the old rotation if it was portrait
2666 if (isAnyPortrait(lastRotation)) {
2667 return lastRotation;
2668 }
2669 // default to one of the primary portrait rotations
2670 return mPortraitRotation;
2671 }
2672
2673 private boolean isAnyPortrait(int sensorRotation) {
2674 return sensorRotation == mPortraitRotation || sensorRotation == mUpsideDownRotation;
2675 }
2676
Daniel Sandlerb73617d2010-08-17 00:41:00 -04002677
2678 // User rotation: to be used when all else fails in assigning an orientation to the device
2679 public void setUserRotationMode(int mode, int rot) {
2680 ContentResolver res = mContext.getContentResolver();
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05002681
2682 // mUserRotationMode and mUserRotation will be assigned by the content observer
Daniel Sandlerb73617d2010-08-17 00:41:00 -04002683 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
Daniel Sandlerb73617d2010-08-17 00:41:00 -04002684 Settings.System.putInt(res,
2685 Settings.System.USER_ROTATION,
2686 rot);
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05002687 Settings.System.putInt(res,
2688 Settings.System.ACCELEROMETER_ROTATION,
2689 0);
Daniel Sandlerb73617d2010-08-17 00:41:00 -04002690 } else {
2691 Settings.System.putInt(res,
2692 Settings.System.ACCELEROMETER_ROTATION,
2693 1);
2694 }
2695 }
2696
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002697 public boolean detectSafeMode() {
2698 try {
2699 int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002700 int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S);
Dianne Hackborna8730f92009-11-17 15:53:36 -08002701 int dpadState = mWindowManager.getDPadKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER);
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002702 int trackballState = mWindowManager.getTrackballScancodeState(BTN_MOUSE);
Jeff Brownb09abc12011-01-13 21:08:27 -08002703 int volumeDownState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_VOLUME_DOWN);
2704 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0
2705 || volumeDownState > 0;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002706 performHapticFeedbackLw(null, mSafeMode
2707 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
2708 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
Dianne Hackborn73b1ec82009-10-04 13:33:00 -07002709 if (mSafeMode) {
2710 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
2711 + " dpad=" + dpadState + " trackball=" + trackballState + ")");
2712 } else {
2713 Log.i(TAG, "SAFE MODE not enabled");
2714 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002715 return mSafeMode;
2716 } catch (RemoteException e) {
2717 // Doom! (it's also local)
2718 throw new RuntimeException("window manager dead");
2719 }
2720 }
2721
Dianne Hackborn181ceb52009-08-27 22:16:40 -07002722 static long[] getLongIntArray(Resources r, int resid) {
2723 int[] ar = r.getIntArray(resid);
2724 if (ar == null) {
2725 return null;
2726 }
2727 long[] out = new long[ar.length];
2728 for (int i=0; i<ar.length; i++) {
2729 out[i] = ar[i];
2730 }
2731 return out;
2732 }
2733
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002734 /** {@inheritDoc} */
2735 public void systemReady() {
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002736 // tell the keyguard
2737 mKeyguardMediator.onSystemReady();
2738 android.os.SystemProperties.set("dev.bootcomplete", "1");
2739 synchronized (mLock) {
2740 updateOrientationListenerLp();
Dianne Hackbornc777e072010-02-12 13:07:59 -08002741 mSystemReady = true;
2742 mHandler.post(new Runnable() {
2743 public void run() {
2744 updateSettings();
2745 }
2746 });
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002747 }
2748 }
2749
Mike Lockwood28569302010-01-28 11:54:40 -05002750 /** {@inheritDoc} */
2751 public void userActivity() {
2752 synchronized (mScreenLockTimeout) {
2753 if (mLockScreenTimerActive) {
2754 // reset the timer
2755 mHandler.removeCallbacks(mScreenLockTimeout);
2756 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
2757 }
2758 }
2759 }
2760
2761 Runnable mScreenLockTimeout = new Runnable() {
2762 public void run() {
2763 synchronized (this) {
2764 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
2765 mKeyguardMediator.doKeyguardTimeout();
2766 mLockScreenTimerActive = false;
2767 }
2768 }
2769 };
2770
2771 private void updateLockScreenTimeout() {
2772 synchronized (mScreenLockTimeout) {
2773 boolean enable = (mAllowLockscreenWhenOn && mScreenOn && mKeyguardMediator.isSecure());
2774 if (mLockScreenTimerActive != enable) {
2775 if (enable) {
2776 if (localLOGV) Log.v(TAG, "setting lockscreen timer");
2777 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
2778 } else {
2779 if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
2780 mHandler.removeCallbacks(mScreenLockTimeout);
2781 }
2782 mLockScreenTimerActive = enable;
2783 }
2784 }
2785 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002786
2787 /** {@inheritDoc} */
2788 public void enableScreenAfterBoot() {
2789 readLidState();
Dianne Hackborn32bc91d2009-03-27 16:16:03 -07002790 updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002791 }
Dianne Hackbornf54c8f92009-09-19 14:03:57 -07002792
Dianne Hackborn03759ed2009-03-27 16:04:08 -07002793 void updateRotation(int animFlags) {
Jeff Brown4aed78b2011-01-14 17:36:55 -08002794 mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN);
Mike Lockwood1753f7f2009-08-24 14:49:07 -07002795 int rotation = Surface.ROTATION_0;
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002796 if (mHdmiPlugged) {
2797 rotation = Surface.ROTATION_0;
Jeff Brown4aed78b2011-01-14 17:36:55 -08002798 } else if (mLidOpen == LID_OPEN) {
Mike Lockwood1753f7f2009-08-24 14:49:07 -07002799 rotation = mLidOpenRotation;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07002800 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04002801 rotation = mCarDockRotation;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07002802 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04002803 rotation = mDeskDockRotation;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002804 }
2805 //if lid is closed orientation will be portrait
2806 try {
2807 //set orientation on WindowManager
Dianne Hackborn32bc91d2009-03-27 16:16:03 -07002808 mWindowManager.setRotation(rotation, true,
2809 mFancyRotationAnimation | animFlags);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002810 } catch (RemoteException e) {
2811 // Ignore
2812 }
2813 }
2814
2815 /**
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002816 * Return an Intent to launch the currently active dock as home. Returns
2817 * null if the standard home should be launched.
2818 * @return
2819 */
2820 Intent createHomeDockIntent() {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002821 Intent intent;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07002822
2823 // What home does is based on the mode, not the dock state. That
2824 // is, when in car mode you should be taken to car home regardless
2825 // of whether we are actually in a car dock.
Dianne Hackborn78968392010-03-04 20:47:56 -08002826 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002827 intent = mCarDockIntent;
Dianne Hackborn78968392010-03-04 20:47:56 -08002828 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002829 intent = mDeskDockIntent;
2830 } else {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002831 return null;
2832 }
2833
2834 ActivityInfo ai = intent.resolveActivityInfo(
2835 mContext.getPackageManager(), PackageManager.GET_META_DATA);
2836 if (ai == null) {
2837 return null;
2838 }
2839
2840 if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
2841 intent = new Intent(intent);
2842 intent.setClassName(ai.packageName, ai.name);
2843 return intent;
2844 }
2845
2846 return null;
2847 }
2848
2849 void startDockOrHome() {
2850 Intent dock = createHomeDockIntent();
2851 if (dock != null) {
2852 try {
2853 mContext.startActivity(dock);
2854 return;
2855 } catch (ActivityNotFoundException e) {
2856 }
2857 }
2858 mContext.startActivity(mHomeIntent);
2859 }
2860
2861 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002862 * goes to the home screen
2863 * @return whether it did anything
2864 */
2865 boolean goHome() {
2866 if (false) {
2867 // This code always brings home to the front.
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07002868 try {
2869 ActivityManagerNative.getDefault().stopAppSwitches();
2870 } catch (RemoteException e) {
2871 }
Dianne Hackborn94a679d2009-07-28 17:51:07 -07002872 sendCloseSystemWindows();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002873 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002874 } else {
2875 // This code brings home to the front or, if it is already
2876 // at the front, puts the device to sleep.
2877 try {
Wink Savilled2e6a332010-02-12 12:12:06 -08002878 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
2879 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
2880 Log.d(TAG, "UTS-TEST-MODE");
2881 } else {
2882 ActivityManagerNative.getDefault().stopAppSwitches();
2883 sendCloseSystemWindows();
2884 Intent dock = createHomeDockIntent();
2885 if (dock != null) {
2886 int result = ActivityManagerNative.getDefault()
2887 .startActivity(null, dock,
2888 dock.resolveTypeIfNeeded(mContext.getContentResolver()),
2889 null, 0, null, null, 0, true /* onlyIfNeeded*/, false);
2890 if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
2891 return false;
2892 }
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002893 }
2894 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002895 int result = ActivityManagerNative.getDefault()
2896 .startActivity(null, mHomeIntent,
2897 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
2898 null, 0, null, null, 0, true /* onlyIfNeeded*/, false);
2899 if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
2900 return false;
2901 }
2902 } catch (RemoteException ex) {
2903 // bummer, the activity manager, which is in this process, is dead
2904 }
2905 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002906 return true;
2907 }
2908
The Android Open Source Project0727d222009-03-11 12:11:58 -07002909 public void setCurrentOrientationLw(int newOrientation) {
2910 synchronized (mLock) {
2911 if (newOrientation != mCurrentAppOrientation) {
2912 mCurrentAppOrientation = newOrientation;
2913 updateOrientationListenerLp();
2914 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002915 }
2916 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08002917
The Android Open Source Project0727d222009-03-11 12:11:58 -07002918 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
Jim Miller89b17222009-10-27 14:54:09 -07002919 final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
2920 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08002921 if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002922 return false;
2923 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08002924 long[] pattern = null;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002925 switch (effectId) {
2926 case HapticFeedbackConstants.LONG_PRESS:
Amith Yamasanic33cb712010-02-10 15:21:49 -08002927 pattern = mLongPressVibePattern;
2928 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002929 case HapticFeedbackConstants.VIRTUAL_KEY:
Amith Yamasanic33cb712010-02-10 15:21:49 -08002930 pattern = mVirtualKeyVibePattern;
2931 break;
2932 case HapticFeedbackConstants.KEYBOARD_TAP:
2933 pattern = mKeyboardTapVibePattern;
2934 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002935 case HapticFeedbackConstants.SAFE_MODE_DISABLED:
Amith Yamasanic33cb712010-02-10 15:21:49 -08002936 pattern = mSafeModeDisabledVibePattern;
2937 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002938 case HapticFeedbackConstants.SAFE_MODE_ENABLED:
Amith Yamasanic33cb712010-02-10 15:21:49 -08002939 pattern = mSafeModeEnabledVibePattern;
2940 break;
Amith Yamasanic33cb712010-02-10 15:21:49 -08002941 default:
2942 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002943 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08002944 if (pattern.length == 1) {
2945 // One-shot vibration
2946 mVibrator.vibrate(pattern[0]);
2947 } else {
2948 // Pattern vibration
2949 mVibrator.vibrate(pattern, -1);
2950 }
2951 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002952 }
2953
The Android Open Source Project0727d222009-03-11 12:11:58 -07002954 public void screenOnStoppedLw() {
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08002955 if (!mKeyguardMediator.isShowingAndNotHidden() && mPowerManager.isScreenOn()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002956 long curTime = SystemClock.uptimeMillis();
2957 mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
2958 }
2959 }
Mike Lockwoodfcb39242009-10-21 23:01:07 -04002960
2961 public boolean allowKeyRepeat() {
2962 // disable key repeat when screen is off
2963 return mScreenOn;
2964 }
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08002965
Joe Onorato664644d2011-01-23 17:53:23 -08002966 private void updateSystemUiVisibility() {
2967 // If there is no window focused, there will be nobody to handle the events
2968 // anyway, so just hang on in whatever state we're in until things settle down.
2969 if (mFocusedWindow != null) {
Joe Onorato14782f72011-01-25 19:53:17 -08002970 final WindowManager.LayoutParams params = mFocusedWindow.getAttrs();
2971 final int visibility = params.systemUiVisibility | params.subtreeSystemUiVisibility;
Joe Onorato664644d2011-01-23 17:53:23 -08002972 mHandler.post(new Runnable() {
2973 public void run() {
2974 if (mStatusBarService == null) {
2975 mStatusBarService = IStatusBarService.Stub.asInterface(
2976 ServiceManager.getService("statusbar"));
2977 }
2978 if (mStatusBarService != null) {
2979 // need to assume status bar privileges to invoke lights on
2980 long origId = Binder.clearCallingIdentity();
2981 try {
2982 mStatusBarService.setSystemUiVisibility(visibility);
2983 } catch (RemoteException e) {
2984 // not much to be done
2985 mStatusBarService = null;
2986 } finally {
2987 Binder.restoreCallingIdentity(origId);
2988 }
2989 }
2990 }
2991 });
2992 }
2993 }
2994
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08002995 public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
2996 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
2997 pw.print(" mSystemRead="); pw.println(mSystemReady);
2998 pw.print(prefix); pw.print("mLidOpen="); pw.print(mLidOpen);
2999 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
3000 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
3001 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
3002 pw.print(" mDockMode="); pw.print(mDockMode);
3003 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
3004 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
3005 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
3006 pw.print(" mUserRotation="); pw.print(mUserRotation);
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003007 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08003008 pw.print(prefix); pw.print("mAccelerometerDefault="); pw.print(mAccelerometerDefault);
3009 pw.print(" mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
3010 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
3011 pw.print(mCarDockEnablesAccelerometer);
3012 pw.print(" mDeskDockEnablesAccelerometer=");
3013 pw.println(mDeskDockEnablesAccelerometer);
3014 pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
3015 pw.print(mLidKeyboardAccessibility);
3016 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
3017 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
3018 pw.print(prefix); pw.print("mScreenOn="); pw.print(mScreenOn);
3019 pw.print(" mOrientationSensorEnabled="); pw.print(mOrientationSensorEnabled);
3020 pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
3021 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
3022 pw.print(","); pw.print(mUnrestrictedScreenTop);
3023 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
3024 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
3025 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
3026 pw.print(","); pw.print(mRestrictedScreenTop);
3027 pw.print(") "); pw.print(mRestrictedScreenWidth);
3028 pw.print("x"); pw.println(mRestrictedScreenHeight);
3029 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
3030 pw.print(","); pw.print(mCurTop);
3031 pw.print(")-("); pw.print(mCurRight);
3032 pw.print(","); pw.print(mCurBottom); pw.println(")");
3033 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
3034 pw.print(","); pw.print(mContentTop);
3035 pw.print(")-("); pw.print(mContentRight);
3036 pw.print(","); pw.print(mContentBottom); pw.println(")");
3037 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
3038 pw.print(","); pw.print(mDockTop);
3039 pw.print(")-("); pw.print(mDockRight);
3040 pw.print(","); pw.print(mDockBottom); pw.println(")");
3041 pw.print(prefix); pw.print("mDockLayer="); pw.println(mDockLayer);
3042 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
3043 pw.println(mTopFullscreenOpaqueWindowState);
3044 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
3045 pw.print(" mForceStatusBar="); pw.print(mForceStatusBar);
3046 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
3047 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
3048 pw.print(" mHomePressed="); pw.println(mHomePressed);
3049 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
3050 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
3051 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
3052 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
3053 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
3054 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
3055 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
3056 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
3057 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
3058 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
3059 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003060}