blob: 116492dbb2603e1f537f004960922b55ee7e6184 [file] [log] [blame]
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001/*
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16package com.android.internal.policy.impl;
17
Dianne Hackborna4972e92012-03-14 10:38:05 -070018import android.app.ActivityManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080019import android.app.ActivityManagerNative;
Dianne Hackborn78968392010-03-04 20:47:56 -080020import android.app.IUiModeManager;
Dianne Hackborn661cd522011-08-22 00:26:20 -070021import android.app.ProgressDialog;
Jeff Brownde7a8ea2012-06-13 18:28:57 -070022import android.app.SearchManager;
Dianne Hackborn78968392010-03-04 20:47:56 -080023import 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;
Daniel Sandler0601eb72011-04-13 01:01:32 -040026import android.content.ComponentName;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080027import android.content.ContentResolver;
28import android.content.Context;
29import android.content.Intent;
Mike Lockwood1753f7f2009-08-24 14:49:07 -070030import android.content.IntentFilter;
Winson Chung9112ec32011-06-27 13:15:32 -070031import android.content.ServiceConnection;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080032import android.content.pm.ActivityInfo;
33import android.content.pm.PackageManager;
Dianne Hackborn2f0b1752011-05-31 17:59:49 -070034import android.content.res.CompatibilityInfo;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080035import android.content.res.Configuration;
36import android.content.res.Resources;
Craig Mautner8e4df6c2012-05-23 16:57:23 -070037import android.content.res.TypedArray;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080038import android.database.ContentObserver;
Dianne Hackbornc777e072010-02-12 13:07:59 -080039import android.graphics.PixelFormat;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080040import android.graphics.Rect;
Michael Jurka7a348952012-02-27 13:07:58 -080041import android.media.AudioManager;
42import android.media.IAudioService;
Dianne Hackborn38e29a62011-09-18 14:43:08 -070043import android.os.Bundle;
Jeff Brown9a538ee2012-08-20 14:56:57 -070044import android.os.FactoryTest;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080045import android.os.Handler;
46import android.os.IBinder;
Dianne Hackborn38e29a62011-09-18 14:43:08 -070047import android.os.IRemoteCallback;
Jeff Brown32cbc38552011-12-01 14:01:49 -080048import android.os.Looper;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -070049import android.os.Message;
50import android.os.Messenger;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080051import android.os.PowerManager;
52import android.os.RemoteException;
53import android.os.ServiceManager;
54import android.os.SystemClock;
55import android.os.SystemProperties;
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -080056import android.os.UEventObserver;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070057import android.os.UserHandle;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080058import android.os.Vibrator;
59import android.provider.Settings;
60
Jim Millere6ad1a82010-08-20 19:25:39 -070061import com.android.internal.R;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080062import com.android.internal.policy.PolicyManager;
Jim Miller9c7e6302012-08-29 13:48:34 -070063import com.android.internal.policy.impl.keyguard.KeyguardViewManager;
64import com.android.internal.policy.impl.keyguard.KeyguardViewMediator;
Joe Onorato0cbda992010-05-02 16:28:15 -070065import com.android.internal.statusbar.IStatusBarService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080066import com.android.internal.telephony.ITelephony;
Dianne Hackborn6019c9d2010-03-01 21:43:11 -080067import com.android.internal.widget.PointerLocationView;
68
Dianne Hackborn81e56d52011-05-26 00:55:58 -070069import android.util.DisplayMetrics;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080070import android.util.EventLog;
71import android.util.Log;
Jeff Browna41ca772010-08-11 14:46:32 -070072import android.util.Slog;
Jeff Brown6651a632011-11-28 12:59:11 -080073import android.util.SparseArray;
Dianne Hackbornf87d1962012-04-04 12:48:24 -070074import android.view.Display;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080075import android.view.Gravity;
76import android.view.HapticFeedbackConstants;
Dianne Hackborne0f085d2011-11-30 18:41:15 -080077import android.view.IApplicationToken;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080078import android.view.IWindowManager;
Jeff Browna41ca772010-08-11 14:46:32 -070079import android.view.InputChannel;
Jeff Brown4d396052010-10-29 21:50:21 -070080import android.view.InputDevice;
Jeff Brown4952dfd2011-11-30 19:23:22 -080081import android.view.InputEvent;
Jeff Brown32cbc38552011-12-01 14:01:49 -080082import android.view.InputEventReceiver;
Jeff Brown6b53e8d2010-11-10 16:03:06 -080083import android.view.KeyCharacterMap;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080084import android.view.KeyEvent;
85import android.view.MotionEvent;
Jeff Brown98365d72012-08-19 20:30:52 -070086import android.view.WindowManagerGlobal;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080087import android.view.WindowOrientationListener;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080088import android.view.Surface;
89import android.view.View;
90import android.view.ViewConfiguration;
91import android.view.Window;
92import android.view.WindowManager;
93import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
94import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
95import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
96import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
97import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
98import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -070099import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700100import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
Mike Lockwood28569302010-01-28 11:54:40 -0500101import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800102import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
103import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
Dianne Hackborndea3ef72010-10-28 14:24:22 -0700104import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800105import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
106import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
Dianne Hackborn5cb8d792009-05-21 17:34:15 -0700107import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800108import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
109import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
110import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700111import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
Christopher Tatea53146c2010-09-07 11:57:52 -0700112import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
Daniel Sandler7d276c32012-01-30 14:33:52 -0500113import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700114import static android.view.WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800115import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
116import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
117import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
118import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
119import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
Jeff Brown3b2b3542010-10-15 00:54:27 -0700120import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800121import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
122import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
Joe Onorato29fc2c92010-11-24 10:26:50 -0800123import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800124import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800125import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
126import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
127import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
128import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
129import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
130import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700131import static android.view.WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700132import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700133import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Jeff Brown83c09682010-12-23 17:50:18 -0800134import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400135import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
Jim Millere898ac52012-04-06 17:10:57 -0700136import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -0700137import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800138import android.view.WindowManagerPolicy;
Jeff Brownac143512012-04-05 18:57:33 -0700139import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
140import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
141import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
Jeff Brown6f2fba42011-02-19 01:08:02 -0800142import android.view.KeyCharacterMap.FallbackAction;
Dianne Hackborn295e3c22011-08-25 13:19:08 -0700143import android.view.accessibility.AccessibilityEvent;
Dianne Hackborn01ad2f42009-09-24 19:24:56 -0700144import android.view.animation.Animation;
145import android.view.animation.AnimationUtils;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800146
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800147import java.io.File;
Joe Onoratodc100302011-01-11 17:07:41 -0800148import java.io.FileReader;
149import java.io.IOException;
Dianne Hackbornf99f9c52011-01-12 15:49:25 -0800150import java.io.PrintWriter;
Dianne Hackborn08743722009-12-21 12:16:51 -0800151
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800152/**
The Android Open Source Project0727d222009-03-11 12:11:58 -0700153 * WindowManagerPolicy implementation for the Android phone UI. This
154 * introduces a new method suffix, Lp, for an internal lock of the
155 * PhoneWindowManager. This is used to protect some internal state, and
156 * can be acquired with either thw Lw and Li lock held, so has the restrictions
157 * of both of those when held.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800158 */
159public class PhoneWindowManager implements WindowManagerPolicy {
160 static final String TAG = "WindowManager";
161 static final boolean DEBUG = false;
Joe Onorato43a17652011-04-06 19:22:23 -0700162 static final boolean localLOGV = false;
The Android Open Source Project11267662009-03-18 17:39:47 -0700163 static final boolean DEBUG_LAYOUT = false;
Jeff Brown40013652012-05-16 21:22:36 -0700164 static final boolean DEBUG_INPUT = false;
Craig Mautner6fbda632012-07-03 09:26:39 -0700165 static final boolean DEBUG_STARTING_WINDOW = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800166 static final boolean SHOW_STARTING_ANIMATIONS = true;
167 static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
Joe Onoratod208e702010-10-08 16:22:43 -0400168
Daniel Sandler11ddf532011-11-16 11:10:03 -0800169 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
170 // No longer recommended for desk docks; still useful in car docks.
171 static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
172 static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
173
Joe Onoratod208e702010-10-08 16:22:43 -0400174 static final int LONG_PRESS_POWER_NOTHING = 0;
175 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
176 static final int LONG_PRESS_POWER_SHUT_OFF = 2;
Jeff Brown9a538ee2012-08-20 14:56:57 -0700177 static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
Michael Jurka3b1fc472011-06-13 10:54:40 -0700178
179 // These need to match the documentation/constant in
180 // core/res/res/values/config.xml
Joe Onorato46b0d682010-11-22 17:37:27 -0800181 static final int LONG_PRESS_HOME_NOTHING = 0;
182 static final int LONG_PRESS_HOME_RECENT_DIALOG = 1;
Michael Jurka3b1fc472011-06-13 10:54:40 -0700183 static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 2;
Joe Onorato46b0d682010-11-22 17:37:27 -0800184
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700185 // wallpaper is at the bottom, though the window manager may move it.
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -0700186 static final int UNIVERSE_BACKGROUND_LAYER = 1;
Dianne Hackborn3c3bd442009-08-19 17:09:46 -0700187 static final int WALLPAPER_LAYER = 2;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700188 static final int APPLICATION_LAYER = 2;
189 static final int PHONE_LAYER = 3;
190 static final int SEARCH_BAR_LAYER = 4;
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700191 static final int SYSTEM_DIALOG_LAYER = 5;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800192 // toasts and the plugged-in battery thing
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700193 static final int TOAST_LAYER = 6;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800194 // SIM errors and unlock. Not sure if this really should be in a high layer.
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700195 static final int PRIORITY_PHONE_LAYER = 7;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800196 // like the ANR / app crashed dialogs
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700197 static final int SYSTEM_ALERT_LAYER = 8;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800198 // on-screen keyboards and other such input method user interfaces go here.
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700199 static final int INPUT_METHOD_LAYER = 9;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800200 // on-screen keyboards and other such input method user interfaces go here.
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700201 static final int INPUT_METHOD_DIALOG_LAYER = 10;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800202 // the keyguard; nothing on top of these can take focus, since they are
203 // responsible for power management when displayed.
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700204 static final int KEYGUARD_LAYER = 11;
205 static final int KEYGUARD_DIALOG_LAYER = 12;
Daniel Sandler7d276c32012-01-30 14:33:52 -0500206 // used for Dreams (screensavers with TYPE_DREAM windows)
207 static final int SCREENSAVER_LAYER = 13;
208 static final int STATUS_BAR_SUB_PANEL_LAYER = 14;
209 static final int STATUS_BAR_LAYER = 15;
210 static final int STATUS_BAR_PANEL_LAYER = 16;
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700211 // the on-screen volume indicator and controller shown when the user
212 // changes the device volume
Daniel Sandler7d276c32012-01-30 14:33:52 -0500213 static final int VOLUME_OVERLAY_LAYER = 17;
Jeff Brownbfcb60a2011-09-08 18:51:14 -0700214 // things in here CAN NOT take focus, but are shown on top of everything else.
Daniel Sandler7d276c32012-01-30 14:33:52 -0500215 static final int SYSTEM_OVERLAY_LAYER = 18;
Jeff Brownbfcb60a2011-09-08 18:51:14 -0700216 // the navigation bar, if available, shows atop most things
Daniel Sandler7d276c32012-01-30 14:33:52 -0500217 static final int NAVIGATION_BAR_LAYER = 19;
Jim Millere898ac52012-04-06 17:10:57 -0700218 // some panels (e.g. search) need to show on top of the navigation bar
219 static final int NAVIGATION_BAR_PANEL_LAYER = 20;
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700220 // system-level error dialogs
Jim Millere898ac52012-04-06 17:10:57 -0700221 static final int SYSTEM_ERROR_LAYER = 21;
Jeff Brownbd6e1502012-08-28 03:27:37 -0700222 // used to simulate secondary display devices
223 static final int DISPLAY_OVERLAY_LAYER = 22;
Christopher Tatea53146c2010-09-07 11:57:52 -0700224 // the drag layer: input for drag-and-drop is associated with this window,
225 // which sits above all other focusable windows
Jeff Brownbd6e1502012-08-28 03:27:37 -0700226 static final int DRAG_LAYER = 23;
227 static final int SECURE_SYSTEM_OVERLAY_LAYER = 24;
228 static final int BOOT_PROGRESS_LAYER = 25;
Jeff Brown83c09682010-12-23 17:50:18 -0800229 // the (mouse) pointer layer
Jeff Brownbd6e1502012-08-28 03:27:37 -0700230 static final int POINTER_LAYER = 26;
231 static final int HIDDEN_NAV_CONSUMER_LAYER = 27;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800232
Dianne Hackborn5cb8d792009-05-21 17:34:15 -0700233 static final int APPLICATION_MEDIA_SUBLAYER = -2;
234 static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800235 static final int APPLICATION_PANEL_SUBLAYER = 1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800236 static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800237
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800238 static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
239 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
240 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
Joe Onoratof275f0c2009-11-24 16:11:13 -0500241 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
Jeff Brownde7a8ea2012-06-13 18:28:57 -0700242 static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800243
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700244 /**
245 * These are the system UI flags that, when changing, can cause the layout
246 * of the screen to change.
247 */
248 static final int SYSTEM_UI_CHANGING_LAYOUT =
249 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
250
Jeff Brown6651a632011-11-28 12:59:11 -0800251 /* Table of Application Launch keys. Maps from key codes to intent categories.
252 *
253 * These are special keys that are used to launch particular kinds of applications,
254 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C)
255 * usage page. We don't support quite that many yet...
256 */
257 static SparseArray<String> sApplicationLaunchKeyCategories;
258 static {
259 sApplicationLaunchKeyCategories = new SparseArray<String>();
260 sApplicationLaunchKeyCategories.append(
261 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
262 sApplicationLaunchKeyCategories.append(
263 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
264 sApplicationLaunchKeyCategories.append(
265 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
266 sApplicationLaunchKeyCategories.append(
267 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
268 sApplicationLaunchKeyCategories.append(
269 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
270 sApplicationLaunchKeyCategories.append(
271 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
272 }
273
Dianne Hackborndf89e652011-10-06 22:35:11 -0700274 /**
275 * Lock protecting internal state. Must not call out into window
276 * manager with lock held. (This lock will be acquired in places
277 * where the window manager is calling in with its own lock held.)
278 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700279 final Object mLock = new Object();
Dianne Hackborndf89e652011-10-06 22:35:11 -0700280
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800281 Context mContext;
282 IWindowManager mWindowManager;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700283 WindowManagerFuncs mWindowManagerFuncs;
Jeff Brown96307042012-07-27 15:51:34 -0700284 PowerManager mPowerManager;
Joe Onorato93056472010-09-10 10:30:46 -0400285 IStatusBarService mStatusBarService;
Dianne Hackborn42e620c2012-06-24 13:20:51 -0700286 final Object mServiceAquireLock = new Object();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800287 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
Jeff Brownde7a8ea2012-06-13 18:28:57 -0700288 SearchManager mSearchManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800289
Dianne Hackborn181ceb52009-08-27 22:16:40 -0700290 // Vibrator pattern for haptic feedback of a long press.
291 long[] mLongPressVibePattern;
292
293 // Vibrator pattern for haptic feedback of virtual key press.
294 long[] mVirtualKeyVibePattern;
295
Amith Yamasanic33cb712010-02-10 15:21:49 -0800296 // Vibrator pattern for a short vibration.
297 long[] mKeyboardTapVibePattern;
298
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700299 // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
300 long[] mSafeModeDisabledVibePattern;
301
302 // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
303 long[] mSafeModeEnabledVibePattern;
Romain Guy8154cd32010-03-29 14:41:15 -0700304
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800305 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
306 boolean mEnableShiftMenuBugReports = false;
Mike Lockwoodd747dc82011-09-13 16:28:22 -0400307
308 boolean mHeadless;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800309 boolean mSafeMode;
310 WindowState mStatusBar = null;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700311 boolean mHasSystemNavBar;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700312 int mStatusBarHeight;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400313 WindowState mNavigationBar = null;
Daniel Sandler36412a72011-08-04 09:35:13 -0400314 boolean mHasNavigationBar = false;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700315 boolean mCanHideNavigationBar = false;
Daniel Sandler4a066c52012-04-20 14:49:13 -0400316 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
317 boolean mNavigationBarOnBottom = true; // is the navigation bar on the bottom *right now*?
318 int[] mNavigationBarHeightForRotation = new int[4];
319 int[] mNavigationBarWidthForRotation = new int[4];
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400320
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800321 WindowState mKeyguard = null;
322 KeyguardViewMediator mKeyguardMediator;
323 GlobalActions mGlobalActions;
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700324 volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
325 boolean mPendingPowerKeyUpCanceled;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800326 Handler mHandler;
satok1bc0a492012-04-25 22:47:12 +0900327 WindowState mLastInputMethodWindow = null;
328 WindowState mLastInputMethodTargetWindow = null;
Jeff Brown4aed78b2011-01-14 17:36:55 -0800329
Jeff Brown68b909d2011-12-07 16:36:01 -0800330 static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0;
331 static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1;
Jeff Brown602ab322012-05-16 13:33:47 -0700332 static final int RECENT_APPS_BEHAVIOR_DISMISS = 2;
333 static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 3;
Jeff Brown68b909d2011-12-07 16:36:01 -0800334
335 RecentApplicationsDialog mRecentAppsDialog;
336 int mRecentAppsDialogHeldModifiers;
Jeff Browncf39bdf2012-05-18 14:41:19 -0700337 boolean mLanguageSwitchKeyPressed;
Jeff Brown68b909d2011-12-07 16:36:01 -0800338
Jeff Brown2e7760e2012-04-11 15:14:55 -0700339 int mLidState = LID_ABSENT;
Jeff Browndaa37532012-05-01 15:54:03 -0700340 boolean mHaveBuiltInKeyboard;
Jeff Brown4aed78b2011-01-14 17:36:55 -0800341
Dianne Hackbornc777e072010-02-12 13:07:59 -0800342 boolean mSystemReady;
Dianne Hackbornba24e4d2011-09-01 11:17:06 -0700343 boolean mSystemBooted;
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800344 boolean mHdmiPlugged;
Joe Onorato44fcb832011-12-14 20:59:30 -0800345 int mUiMode;
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700346 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700347 int mLidOpenRotation;
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400348 int mCarDockRotation;
349 int mDeskDockRotation;
Erik Gilling9a41ef82011-09-26 19:21:03 -0700350 int mHdmiRotation;
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400351
352 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
353 int mUserRotation = Surface.ROTATION_0;
Jeff Brown207673cd2012-06-05 17:47:11 -0700354 boolean mAccelerometerDefault;
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400355
Jeff Brownd3187e32011-09-21 19:26:44 -0700356 int mAllowAllRotations = -1;
Mike Lockwoode9867d22009-09-20 01:59:02 -0400357 boolean mCarDockEnablesAccelerometer;
358 boolean mDeskDockEnablesAccelerometer;
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700359 int mLidKeyboardAccessibility;
360 int mLidNavigationAccessibility;
Jeff Brownc458ce92012-04-30 14:58:40 -0700361 boolean mLidControlsSleep;
Joe Onoratod208e702010-10-08 16:22:43 -0400362 int mLongPressOnPowerBehavior = -1;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700363 boolean mScreenOnEarly = false;
364 boolean mScreenOnFully = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800365 boolean mOrientationSensorEnabled = false;
Craig Mautner4bd149e2012-08-03 13:54:02 -0700366 int mLastSensorRotation = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800367 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800368 boolean mHasSoftInput = false;
369
Jeff Brown70825162012-03-28 17:27:48 -0700370 int mPointerLocationMode = 0; // guarded by mLock
Joe Onorato664644d2011-01-23 17:53:23 -0800371
372 // The last window we were told about in focusChanged.
373 WindowState mFocusedWindow;
Dianne Hackborne0f085d2011-11-30 18:41:15 -0800374 IApplicationToken mFocusedApp;
Joe Onorato664644d2011-01-23 17:53:23 -0800375
Jeff Brown70825162012-03-28 17:27:48 -0700376 private static final class PointerLocationInputEventReceiver extends InputEventReceiver {
377 private final PointerLocationView mView;
378
379 public PointerLocationInputEventReceiver(InputChannel inputChannel, Looper looper,
380 PointerLocationView view) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800381 super(inputChannel, looper);
Jeff Brown70825162012-03-28 17:27:48 -0700382 mView = view;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800383 }
384
Jeff Browna41ca772010-08-11 14:46:32 -0700385 @Override
Jeff Brown32cbc38552011-12-01 14:01:49 -0800386 public void onInputEvent(InputEvent event) {
Jeff Brown3915bb82010-11-05 15:02:16 -0700387 boolean handled = false;
388 try {
Jeff Brown4952dfd2011-11-30 19:23:22 -0800389 if (event instanceof MotionEvent
390 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
391 final MotionEvent motionEvent = (MotionEvent)event;
Jeff Brown70825162012-03-28 17:27:48 -0700392 mView.addPointerEvent(motionEvent);
393 handled = true;
Jeff Brown93ed4e32010-09-23 13:51:48 -0700394 }
Jeff Brown3915bb82010-11-05 15:02:16 -0700395 } finally {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800396 finishInputEvent(event, handled);
Jeff Browna41ca772010-08-11 14:46:32 -0700397 }
398 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800399 }
Jeff Brown70825162012-03-28 17:27:48 -0700400
401 // Pointer location view state, only modified on the mHandler Looper.
Jeff Brown32cbc38552011-12-01 14:01:49 -0800402 PointerLocationInputEventReceiver mPointerLocationInputEventReceiver;
Jeff Brown70825162012-03-28 17:27:48 -0700403 PointerLocationView mPointerLocationView;
404 InputChannel mPointerLocationInputChannel;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800405
Joe Onorato29fc2c92010-11-24 10:26:50 -0800406 // The current size of the screen; really; (ir)regardless of whether the status
407 // bar can be hidden or not
408 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
409 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
Dianne Hackborn82de1ae2010-10-28 11:28:39 -0700410 // The current size of the screen; these may be different than (0,0)-(dw,dh)
411 // if the status bar can't be hidden; in that case it effectively carves out
412 // that area of the display from all other windows.
Joe Onorato29fc2c92010-11-24 10:26:50 -0800413 int mRestrictedScreenLeft, mRestrictedScreenTop;
414 int mRestrictedScreenWidth, mRestrictedScreenHeight;
Dianne Hackborn5c58de32012-04-28 19:52:37 -0700415 // During layout, the current screen borders accounting for any currently
416 // visible system UI elements.
417 int mSystemLeft, mSystemTop, mSystemRight, mSystemBottom;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700418 // For applications requesting stable content insets, these are them.
419 int mStableLeft, mStableTop, mStableRight, mStableBottom;
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -0700420 // For applications requesting stable content insets but have also set the
421 // fullscreen window flag, these are the stable dimensions without the status bar.
422 int mStableFullscreenLeft, mStableFullscreenTop;
423 int mStableFullscreenRight, mStableFullscreenBottom;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800424 // During layout, the current screen borders with all outer decoration
425 // (status bar, input method dock) accounted for.
426 int mCurLeft, mCurTop, mCurRight, mCurBottom;
427 // During layout, the frame in which content should be displayed
428 // to the user, accounting for all screen decoration except for any
429 // space they deem as available for other content. This is usually
430 // the same as mCur*, but may be larger if the screen decor has supplied
431 // content insets.
432 int mContentLeft, mContentTop, mContentRight, mContentBottom;
Dianne Hackborn8e11ef02010-11-18 19:47:42 -0800433 // During layout, the current screen borders along which input method
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800434 // windows are placed.
435 int mDockLeft, mDockTop, mDockRight, mDockBottom;
436 // During layout, the layer at which the doc window is placed.
437 int mDockLayer;
Dianne Hackborn5c58de32012-04-28 19:52:37 -0700438 // During layout, this is the layer of the status bar.
439 int mStatusBarLayer;
Dianne Hackborne26ab702011-10-16 13:21:33 -0700440 int mLastSystemUiFlags;
441 // Bits that we are in the process of clearing, so we want to prevent
442 // them from being set by applications until everything has been updated
443 // to have them clear.
444 int mResettingSystemUiFlags = 0;
445 // Bits that we are currently always keeping cleared.
446 int mForceClearedSystemUiFlags = 0;
Dianne Hackborn4eff8d32011-11-10 19:38:40 -0800447 // What we last reported to system UI about whether the compatibility
448 // menu needs to be displayed.
449 boolean mLastFocusNeedsMenu = false;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700450
451 FakeWindow mHideNavFakeWindow = null;
452
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800453 static final Rect mTmpParentFrame = new Rect();
454 static final Rect mTmpDisplayFrame = new Rect();
455 static final Rect mTmpContentFrame = new Rect();
456 static final Rect mTmpVisibleFrame = new Rect();
Dianne Hackborn1f903c32011-09-13 19:18:06 -0700457 static final Rect mTmpNavigationFrame = new Rect();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800458
459 WindowState mTopFullscreenOpaqueWindowState;
Joe Onorato93056472010-09-10 10:30:46 -0400460 boolean mTopIsFullscreen;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800461 boolean mForceStatusBar;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700462 boolean mHideLockScreen;
463 boolean mDismissKeyguard;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800464 boolean mHomePressed;
Michael Jurka7f2668c2012-03-27 07:49:52 -0700465 boolean mHomeLongPressed;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800466 Intent mHomeIntent;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700467 Intent mCarDockIntent;
468 Intent mDeskDockIntent;
Jeff Brownfd23e3e2012-05-09 13:34:28 -0700469 boolean mSearchKeyShortcutPending;
470 boolean mConsumeSearchKeyUp;
Jeff Brownde7a8ea2012-06-13 18:28:57 -0700471 boolean mAssistKeyLongPressed;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800472
Mike Lockwood28569302010-01-28 11:54:40 -0500473 // support for activating the lock screen while the screen is on
474 boolean mAllowLockscreenWhenOn;
475 int mLockScreenTimeout;
476 boolean mLockScreenTimerActive;
477
David Brownbaf8d092010-03-08 21:52:59 -0800478 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800479 int mEndcallBehavior;
David Brownbaf8d092010-03-08 21:52:59 -0800480
481 // Behavior of POWER button while in-call and screen on.
482 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
483 int mIncallPowerBehavior;
484
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700485 Display mDisplay;
486
Dianne Hackborn9d132642011-04-21 17:26:39 -0700487 int mLandscapeRotation = 0; // default landscape rotation
488 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation
489 int mPortraitRotation = 0; // default portrait rotation
490 int mUpsideDownRotation = 0; // "other" portrait rotation
Mitsuru Oshima831d0d92009-06-16 18:27:18 -0700491
Joe Onorato46b0d682010-11-22 17:37:27 -0800492 // What we do when the user long presses on home
493 private int mLongPressOnHomeBehavior = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800494
Winson Chung9112ec32011-06-27 13:15:32 -0700495 // Screenshot trigger states
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700496 // Time to volume and power must be pressed within this interval of each other.
497 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
Christopher Tatee90585f2012-03-05 18:56:25 -0800498 private boolean mScreenshotChordEnabled;
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700499 private boolean mVolumeDownKeyTriggered;
500 private long mVolumeDownKeyTime;
501 private boolean mVolumeDownKeyConsumedByScreenshotChord;
502 private boolean mVolumeUpKeyTriggered;
503 private boolean mPowerKeyTriggered;
504 private long mPowerKeyTime;
Winson Chung9112ec32011-06-27 13:15:32 -0700505
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800506 ShortcutManager mShortcutManager;
507 PowerManager.WakeLock mBroadcastWakeLock;
Jeff Brown40013652012-05-16 21:22:36 -0700508 boolean mHavePendingMediaKeyRepeatWithWakeLock;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800509
Jeff Brownfd23e3e2012-05-09 13:34:28 -0700510 // Fallback actions by key code.
511 private final SparseArray<KeyCharacterMap.FallbackAction> mFallbackActions =
512 new SparseArray<KeyCharacterMap.FallbackAction>();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800513
Jeff Brown70825162012-03-28 17:27:48 -0700514 private static final int MSG_ENABLE_POINTER_LOCATION = 1;
515 private static final int MSG_DISABLE_POINTER_LOCATION = 2;
Jeff Brown40013652012-05-16 21:22:36 -0700516 private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
517 private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
Jeff Brown70825162012-03-28 17:27:48 -0700518
519 private class PolicyHandler extends Handler {
520 @Override
521 public void handleMessage(Message msg) {
522 switch (msg.what) {
523 case MSG_ENABLE_POINTER_LOCATION:
524 enablePointerLocation();
525 break;
526 case MSG_DISABLE_POINTER_LOCATION:
527 disablePointerLocation();
528 break;
Jeff Brown40013652012-05-16 21:22:36 -0700529 case MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK:
530 dispatchMediaKeyWithWakeLock((KeyEvent)msg.obj);
531 break;
532 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
533 dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
534 break;
Jeff Brown70825162012-03-28 17:27:48 -0700535 }
536 }
537 }
538
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800539 private UEventObserver mHDMIObserver = new UEventObserver() {
540 @Override
541 public void onUEvent(UEventObserver.UEvent event) {
542 setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
543 }
544 };
545
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800546 class SettingsObserver extends ContentObserver {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800547 SettingsObserver(Handler handler) {
548 super(handler);
549 }
David Brownbaf8d092010-03-08 21:52:59 -0800550
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800551 void observe() {
552 ContentResolver resolver = mContext.getContentResolver();
553 resolver.registerContentObserver(Settings.System.getUriFor(
554 Settings.System.END_BUTTON_BEHAVIOR), false, this);
David Brownbaf8d092010-03-08 21:52:59 -0800555 resolver.registerContentObserver(Settings.Secure.getUriFor(
556 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800557 resolver.registerContentObserver(Settings.System.getUriFor(
558 Settings.System.ACCELEROMETER_ROTATION), false, this);
Mike Lockwood28569302010-01-28 11:54:40 -0500559 resolver.registerContentObserver(Settings.System.getUriFor(
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400560 Settings.System.USER_ROTATION), false, this);
561 resolver.registerContentObserver(Settings.System.getUriFor(
Mike Lockwood28569302010-01-28 11:54:40 -0500562 Settings.System.SCREEN_OFF_TIMEOUT), false, this);
Dianne Hackbornc777e072010-02-12 13:07:59 -0800563 resolver.registerContentObserver(Settings.System.getUriFor(
564 Settings.System.POINTER_LOCATION), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800565 resolver.registerContentObserver(Settings.Secure.getUriFor(
566 Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700567 resolver.registerContentObserver(Settings.System.getUriFor(
568 "fancy_rotation_anim"), false, this);
Dianne Hackbornc777e072010-02-12 13:07:59 -0800569 updateSettings();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800570 }
571
572 @Override public void onChange(boolean selfChange) {
Dianne Hackbornc777e072010-02-12 13:07:59 -0800573 updateSettings();
Jeff Brown01a98dd2011-09-20 15:08:29 -0700574 updateRotation(false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800575 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800576 }
577
578 class MyOrientationListener extends WindowOrientationListener {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800579 MyOrientationListener(Context context) {
580 super(context);
581 }
582
583 @Override
Jeff Brownc0347aa2011-09-23 17:26:09 -0700584 public void onProposedRotationChanged(int rotation) {
585 if (localLOGV) Log.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
Jeff Brown01a98dd2011-09-20 15:08:29 -0700586 updateRotation(false);
587 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800588 }
589 MyOrientationListener mOrientationListener;
590
Dianne Hackborn42e620c2012-06-24 13:20:51 -0700591 IStatusBarService getStatusBarService() {
592 synchronized (mServiceAquireLock) {
593 if (mStatusBarService == null) {
594 mStatusBarService = IStatusBarService.Stub.asInterface(
595 ServiceManager.getService("statusbar"));
596 }
597 return mStatusBarService;
598 }
599 }
600
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700601 /*
602 * We always let the sensor be switched on by default except when
603 * the user has explicitly disabled sensor based rotation or when the
604 * screen is switched off.
605 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700606 boolean needSensorRunningLp() {
Dianne Hackborne5439f22010-10-02 16:53:50 -0700607 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
608 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
609 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
610 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800611 // If the application has explicitly requested to follow the
612 // orientation, then we need to turn the sensor or.
613 return true;
614 }
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700615 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
Jeff Brown1a693182011-11-08 14:44:16 -0800616 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
617 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
618 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
Mike Lockwoode9867d22009-09-20 01:59:02 -0400619 // enable accelerometer if we are docked in a dock that enables accelerometer
620 // orientation management,
621 return true;
622 }
Jeff Brown207673cd2012-06-05 17:47:11 -0700623 if (mUserRotationMode == USER_ROTATION_LOCKED) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800624 // If the setting for using the sensor by default is enabled, then
625 // we will always leave it on. Note that the user could go to
626 // a window that forces an orientation that does not use the
627 // sensor and in theory we could turn it off... however, when next
628 // turning it on we won't have a good value for the current
629 // orientation for a little bit, which can cause orientation
630 // changes to lag, so we'd like to keep it always on. (It will
631 // still be turned off when the screen is off.)
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700632 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800633 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700634 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800635 }
636
637 /*
638 * Various use cases for invoking this function
639 * screen turning off, should always disable listeners if already enabled
640 * screen turned on and current app has sensor based orientation, enable listeners
641 * if not already enabled
642 * screen turned on and current app does not have sensor orientation, disable listeners if
643 * already enabled
644 * screen turning on and current app has sensor based orientation, enable listeners if needed
645 * screen turning on and current app has nosensor based orientation, do nothing
646 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700647 void updateOrientationListenerLp() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800648 if (!mOrientationListener.canDetectOrientation()) {
649 // If sensor is turned off or nonexistent for some reason
650 return;
651 }
652 //Could have been invoked due to screen turning on or off or
653 //change of the currently visible window's orientation
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700654 if (localLOGV) Log.v(TAG, "Screen status="+mScreenOnEarly+
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800655 ", current orientation="+mCurrentAppOrientation+
656 ", SensorEnabled="+mOrientationSensorEnabled);
657 boolean disable = true;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700658 if (mScreenOnEarly) {
The Android Open Source Project0727d222009-03-11 12:11:58 -0700659 if (needSensorRunningLp()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800660 disable = false;
661 //enable listener if not already enabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700662 if (!mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800663 mOrientationListener.enable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700664 if(localLOGV) Log.v(TAG, "Enabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800665 mOrientationSensorEnabled = true;
666 }
667 }
668 }
669 //check if sensors need to be disabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700670 if (disable && mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800671 mOrientationListener.disable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700672 if(localLOGV) Log.v(TAG, "Disabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800673 mOrientationSensorEnabled = false;
674 }
675 }
676
Jeff Brown4d396052010-10-29 21:50:21 -0700677 private void interceptPowerKeyDown(boolean handled) {
678 mPowerKeyHandled = handled;
679 if (!handled) {
680 mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
681 }
682 }
683
684 private boolean interceptPowerKeyUp(boolean canceled) {
685 if (!mPowerKeyHandled) {
686 mHandler.removeCallbacks(mPowerLongPress);
687 return !canceled;
Jeff Brown4d396052010-10-29 21:50:21 -0700688 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700689 return false;
690 }
691
692 private void cancelPendingPowerKeyAction() {
693 if (!mPowerKeyHandled) {
694 mHandler.removeCallbacks(mPowerLongPress);
695 }
Jeff Brownff204712011-10-25 21:27:54 -0700696 if (mPowerKeyTriggered) {
697 mPendingPowerKeyUpCanceled = true;
698 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700699 }
700
701 private void interceptScreenshotChord() {
Christopher Tatee90585f2012-03-05 18:56:25 -0800702 if (mScreenshotChordEnabled
703 && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700704 final long now = SystemClock.uptimeMillis();
705 if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
706 && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
707 mVolumeDownKeyConsumedByScreenshotChord = true;
708 cancelPendingPowerKeyAction();
709
710 mHandler.postDelayed(mScreenshotChordLongPress,
711 ViewConfiguration.getGlobalActionKeyTimeout());
712 }
713 }
714 }
715
716 private void cancelPendingScreenshotChordAction() {
717 mHandler.removeCallbacks(mScreenshotChordLongPress);
Jeff Brown4d396052010-10-29 21:50:21 -0700718 }
719
720 private final Runnable mPowerLongPress = new Runnable() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800721 public void run() {
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700722 // The context isn't read
723 if (mLongPressOnPowerBehavior < 0) {
Jeff Brown9a538ee2012-08-20 14:56:57 -0700724 if (FactoryTest.isLongPressOnPowerOffEnabled()) {
725 mLongPressOnPowerBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
726 } else {
727 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
728 com.android.internal.R.integer.config_longPressOnPowerBehavior);
729 }
Joe Onoratod208e702010-10-08 16:22:43 -0400730 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700731 switch (mLongPressOnPowerBehavior) {
732 case LONG_PRESS_POWER_NOTHING:
733 break;
734 case LONG_PRESS_POWER_GLOBAL_ACTIONS:
735 mPowerKeyHandled = true;
736 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
737 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
738 showGlobalActionsDialog();
739 break;
740 case LONG_PRESS_POWER_SHUT_OFF:
Jeff Brown9a538ee2012-08-20 14:56:57 -0700741 case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700742 mPowerKeyHandled = true;
743 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
744 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
Jeff Brown9a538ee2012-08-20 14:56:57 -0700745 mWindowManagerFuncs.shutdown(
746 mLongPressOnPowerBehavior == LONG_PRESS_POWER_SHUT_OFF);
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700747 break;
748 }
749 }
750 };
751
752 private final Runnable mScreenshotChordLongPress = new Runnable() {
753 public void run() {
754 takeScreenshot();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800755 }
756 };
757
758 void showGlobalActionsDialog() {
759 if (mGlobalActions == null) {
Jeff Brown7304c342012-05-11 18:42:42 -0700760 mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800761 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -0700762 final boolean keyguardShowing = keyguardIsShowingTq();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800763 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
764 if (keyguardShowing) {
765 // since it took two seconds of long press to bring this up,
766 // poke the wake lock so they have some time to see the dialog.
767 mKeyguardMediator.pokeWakelock();
768 }
769 }
770
771 boolean isDeviceProvisioned() {
772 return Settings.Secure.getInt(
773 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
774 }
775
Patrick Dubroyece94522011-02-23 18:35:01 -0800776 private void handleLongPressOnHome() {
Jim Milleree969aa2010-08-26 20:17:43 -0700777 // We can't initialize this in init() since the configuration hasn't been loaded yet.
Joe Onorato46b0d682010-11-22 17:37:27 -0800778 if (mLongPressOnHomeBehavior < 0) {
779 mLongPressOnHomeBehavior
Joe Onorato50262e52010-11-26 14:04:54 -0800780 = mContext.getResources().getInteger(R.integer.config_longPressOnHomeBehavior);
Joe Onorato46b0d682010-11-22 17:37:27 -0800781 if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
Michael Jurka3b1fc472011-06-13 10:54:40 -0700782 mLongPressOnHomeBehavior > LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
Joe Onorato46b0d682010-11-22 17:37:27 -0800783 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
784 }
785 }
786
787 if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
788 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
789 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
Patrick Dubroyece94522011-02-23 18:35:01 -0800790
791 // Eat the longpress so it won't dismiss the recent apps dialog when
792 // the user lets go of the home key
Michael Jurka7f2668c2012-03-27 07:49:52 -0700793 mHomeLongPressed = true;
Jim Milleree969aa2010-08-26 20:17:43 -0700794 }
Patrick Dubroyece94522011-02-23 18:35:01 -0800795
Joe Onorato46b0d682010-11-22 17:37:27 -0800796 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
Jeff Brown68b909d2011-12-07 16:36:01 -0800797 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
Michael Jurka3b1fc472011-06-13 10:54:40 -0700798 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
Jim Millere6ad1a82010-08-20 19:25:39 -0700799 try {
Dianne Hackborn42e620c2012-06-24 13:20:51 -0700800 IStatusBarService statusbar = getStatusBarService();
801 if (statusbar != null) {
802 statusbar.toggleRecentApps();
803 }
Michael Jurka3b1fc472011-06-13 10:54:40 -0700804 } catch (RemoteException e) {
805 Slog.e(TAG, "RemoteException when showing recent apps", e);
Dianne Hackborn42e620c2012-06-24 13:20:51 -0700806 // re-acquire status bar service next time it is needed.
807 mStatusBarService = null;
Jim Millere6ad1a82010-08-20 19:25:39 -0700808 }
809 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800810 }
Patrick Dubroyece94522011-02-23 18:35:01 -0800811
812 /**
Jeff Brown68b909d2011-12-07 16:36:01 -0800813 * Create (if necessary) and show or dismiss the recent apps dialog according
814 * according to the requested behavior.
Patrick Dubroyece94522011-02-23 18:35:01 -0800815 */
Jeff Brown68b909d2011-12-07 16:36:01 -0800816 void showOrHideRecentAppsDialog(final int behavior) {
Jeff Brownda3d5a92011-03-29 15:11:34 -0700817 mHandler.post(new Runnable() {
818 @Override
819 public void run() {
820 if (mRecentAppsDialog == null) {
Jeff Brown54875002011-04-06 15:33:01 -0700821 mRecentAppsDialog = new RecentApplicationsDialog(mContext);
Jeff Brownda3d5a92011-03-29 15:11:34 -0700822 }
Jeff Brown54875002011-04-06 15:33:01 -0700823 if (mRecentAppsDialog.isShowing()) {
Jeff Brown68b909d2011-12-07 16:36:01 -0800824 switch (behavior) {
825 case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
Jeff Brown602ab322012-05-16 13:33:47 -0700826 case RECENT_APPS_BEHAVIOR_DISMISS:
Jeff Brown68b909d2011-12-07 16:36:01 -0800827 mRecentAppsDialog.dismiss();
828 break;
829 case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
830 mRecentAppsDialog.dismissAndSwitch();
831 break;
832 case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
833 default:
834 break;
Jeff Brown54875002011-04-06 15:33:01 -0700835 }
836 } else {
Jeff Brown68b909d2011-12-07 16:36:01 -0800837 switch (behavior) {
838 case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
839 mRecentAppsDialog.show();
840 break;
841 case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
842 try {
843 mWindowManager.setInTouchMode(false);
844 } catch (RemoteException e) {
845 }
846 mRecentAppsDialog.show();
847 break;
Jeff Brown602ab322012-05-16 13:33:47 -0700848 case RECENT_APPS_BEHAVIOR_DISMISS:
Jeff Brown68b909d2011-12-07 16:36:01 -0800849 case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
850 default:
851 break;
852 }
Jeff Brown54875002011-04-06 15:33:01 -0700853 }
Jeff Brownda3d5a92011-03-29 15:11:34 -0700854 }
855 });
Patrick Dubroyece94522011-02-23 18:35:01 -0800856 }
Jeff Brownda3d5a92011-03-29 15:11:34 -0700857
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800858 /** {@inheritDoc} */
859 public void init(Context context, IWindowManager windowManager,
Jeff Brown96307042012-07-27 15:51:34 -0700860 WindowManagerFuncs windowManagerFuncs) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800861 mContext = context;
862 mWindowManager = windowManager;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700863 mWindowManagerFuncs = windowManagerFuncs;
Mike Lockwoodd747dc82011-09-13 16:28:22 -0400864 mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
865 if (!mHeadless) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -0700866 // don't create KeyguardViewMediator if headless
Jim Miller9c7e6302012-08-29 13:48:34 -0700867 mKeyguardMediator = new KeyguardViewMediator(context, null);
Mike Lockwood3a74bd32011-08-12 13:55:22 -0700868 }
Jeff Brown70825162012-03-28 17:27:48 -0700869 mHandler = new PolicyHandler();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800870 mOrientationListener = new MyOrientationListener(mContext);
Jeff Brownc0347aa2011-09-23 17:26:09 -0700871 try {
872 mOrientationListener.setCurrentRotation(windowManager.getRotation());
873 } catch (RemoteException ex) { }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800874 SettingsObserver settingsObserver = new SettingsObserver(mHandler);
875 settingsObserver.observe();
876 mShortcutManager = new ShortcutManager(context, mHandler);
877 mShortcutManager.observe();
Joe Onorato44fcb832011-12-14 20:59:30 -0800878 mUiMode = context.getResources().getInteger(
879 com.android.internal.R.integer.config_defaultUiModeType);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800880 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
881 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
882 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
883 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700884 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
885 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
886 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
887 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
888 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
889 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
890 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
891 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Jim Millere6ad1a82010-08-20 19:25:39 -0700892
Jeff Brown96307042012-07-27 15:51:34 -0700893 mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
894 mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800895 "PhoneWindowManager.mBroadcastWakeLock");
896 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700897 mLidOpenRotation = readRotation(
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400898 com.android.internal.R.integer.config_lidOpenRotation);
899 mCarDockRotation = readRotation(
900 com.android.internal.R.integer.config_carDockRotation);
901 mDeskDockRotation = readRotation(
902 com.android.internal.R.integer.config_deskDockRotation);
Mike Lockwoode9867d22009-09-20 01:59:02 -0400903 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
904 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
905 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
906 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700907 mLidKeyboardAccessibility = mContext.getResources().getInteger(
908 com.android.internal.R.integer.config_lidKeyboardAccessibility);
909 mLidNavigationAccessibility = mContext.getResources().getInteger(
910 com.android.internal.R.integer.config_lidNavigationAccessibility);
Jeff Brownc458ce92012-04-30 14:58:40 -0700911 mLidControlsSleep = mContext.getResources().getBoolean(
912 com.android.internal.R.bool.config_lidControlsSleep);
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700913 // register for dock events
Dianne Hackborn78968392010-03-04 20:47:56 -0800914 IntentFilter filter = new IntentFilter();
915 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
916 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
917 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
918 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700919 filter.addAction(Intent.ACTION_DOCK_EVENT);
920 Intent intent = context.registerReceiver(mDockReceiver, filter);
921 if (intent != null) {
922 // Retrieve current sticky dock event broadcast.
923 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
924 Intent.EXTRA_DOCK_STATE_UNDOCKED);
925 }
Daniel Sandler7e37df52011-11-16 22:08:23 -0800926
Jeff Brownc2346132012-04-13 01:55:38 -0700927 mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700928 mLongPressVibePattern = getLongIntArray(mContext.getResources(),
929 com.android.internal.R.array.config_longPressVibePattern);
930 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
931 com.android.internal.R.array.config_virtualKeyVibePattern);
Amith Yamasanic33cb712010-02-10 15:21:49 -0800932 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
933 com.android.internal.R.array.config_keyboardTapVibePattern);
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700934 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
935 com.android.internal.R.array.config_safeModeDisabledVibePattern);
936 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
937 com.android.internal.R.array.config_safeModeEnabledVibePattern);
Daniel Sandler40427442010-07-16 11:44:52 -0400938
Christopher Tatee90585f2012-03-05 18:56:25 -0800939 mScreenshotChordEnabled = mContext.getResources().getBoolean(
940 com.android.internal.R.bool.config_enableScreenshotChord);
941
Joe Onoratoea495d42011-04-06 11:41:11 -0700942 // Controls rotation and the like.
943 initializeHdmiState();
Dianne Hackborn40011092011-09-22 13:37:48 -0700944
945 // Match current screen state.
946 if (mPowerManager.isScreenOn()) {
947 screenTurningOn(null);
948 } else {
949 screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
950 }
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700951 }
952
Dianne Hackborndde331c2012-08-03 14:01:57 -0700953 public void setInitialDisplaySize(Display display, int width, int height, int density) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700954 mDisplay = display;
955
956 int shortSize, longSize;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700957 if (width > height) {
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700958 shortSize = height;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700959 longSize = width;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700960 mLandscapeRotation = Surface.ROTATION_0;
961 mSeascapeRotation = Surface.ROTATION_180;
962 if (mContext.getResources().getBoolean(
963 com.android.internal.R.bool.config_reverseDefaultRotation)) {
964 mPortraitRotation = Surface.ROTATION_90;
965 mUpsideDownRotation = Surface.ROTATION_270;
966 } else {
967 mPortraitRotation = Surface.ROTATION_270;
968 mUpsideDownRotation = Surface.ROTATION_90;
969 }
970 } else {
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700971 shortSize = width;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700972 longSize = height;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700973 mPortraitRotation = Surface.ROTATION_0;
974 mUpsideDownRotation = Surface.ROTATION_180;
975 if (mContext.getResources().getBoolean(
976 com.android.internal.R.bool.config_reverseDefaultRotation)) {
977 mLandscapeRotation = Surface.ROTATION_270;
978 mSeascapeRotation = Surface.ROTATION_90;
979 } else {
980 mLandscapeRotation = Surface.ROTATION_90;
981 mSeascapeRotation = Surface.ROTATION_270;
982 }
983 }
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700984
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700985 mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
986 com.android.internal.R.dimen.status_bar_height);
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700987
Daniel Sandler9f65c4c2012-04-26 01:35:35 -0400988 // Height of the navigation bar when presented horizontally at bottom
989 mNavigationBarHeightForRotation[mPortraitRotation] =
990 mNavigationBarHeightForRotation[mUpsideDownRotation] =
Daniel Sandler4a066c52012-04-20 14:49:13 -0400991 mContext.getResources().getDimensionPixelSize(
992 com.android.internal.R.dimen.navigation_bar_height);
Daniel Sandler9f65c4c2012-04-26 01:35:35 -0400993 mNavigationBarHeightForRotation[mLandscapeRotation] =
994 mNavigationBarHeightForRotation[mSeascapeRotation] =
995 mContext.getResources().getDimensionPixelSize(
996 com.android.internal.R.dimen.navigation_bar_height_landscape);
997
998 // Width of the navigation bar when presented vertically along one side
999 mNavigationBarWidthForRotation[mPortraitRotation] =
1000 mNavigationBarWidthForRotation[mUpsideDownRotation] =
1001 mNavigationBarWidthForRotation[mLandscapeRotation] =
1002 mNavigationBarWidthForRotation[mSeascapeRotation] =
Daniel Sandler4a066c52012-04-20 14:49:13 -04001003 mContext.getResources().getDimensionPixelSize(
1004 com.android.internal.R.dimen.navigation_bar_width);
1005
1006 // SystemUI (status bar) layout policy
Dianne Hackborndde331c2012-08-03 14:01:57 -07001007 int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / density;
Daniel Sandler4a066c52012-04-20 14:49:13 -04001008
1009 if (shortSizeDp < 600) {
1010 // 0-599dp: "phone" UI with a separate status & navigation bar
1011 mHasSystemNavBar = false;
1012 mNavigationBarCanMove = true;
1013 } else if (shortSizeDp < 720) {
Daniel Sandleref863702012-07-11 10:03:34 -04001014 // 600+dp: "phone" UI with modifications for larger screens
Daniel Sandler4a066c52012-04-20 14:49:13 -04001015 mHasSystemNavBar = false;
1016 mNavigationBarCanMove = false;
Daniel Sandler4a066c52012-04-20 14:49:13 -04001017 }
Daniel Sandler36412a72011-08-04 09:35:13 -04001018
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001019 if (!mHasSystemNavBar) {
1020 mHasNavigationBar = mContext.getResources().getBoolean(
1021 com.android.internal.R.bool.config_showNavigationBar);
1022 // Allow a system property to override this. Used by the emulator.
1023 // See also hasNavigationBar().
1024 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
1025 if (! "".equals(navBarOverride)) {
1026 if (navBarOverride.equals("1")) mHasNavigationBar = false;
1027 else if (navBarOverride.equals("0")) mHasNavigationBar = true;
1028 }
1029 } else {
1030 mHasNavigationBar = false;
Daniel Sandler0c4ccff2011-10-19 16:39:14 -04001031 }
1032
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001033 if (mHasSystemNavBar) {
1034 // The system bar is always at the bottom. If you are watching
1035 // a video in landscape, we don't need to hide it if we can still
1036 // show a 16:9 aspect ratio with it.
Dianne Hackborndde331c2012-08-03 14:01:57 -07001037 int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / density;
Daniel Sandler4a066c52012-04-20 14:49:13 -04001038 int barHeightDp = mNavigationBarHeightForRotation[mLandscapeRotation]
Dianne Hackborndde331c2012-08-03 14:01:57 -07001039 * DisplayMetrics.DENSITY_DEFAULT / density;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001040 int aspect = ((shortSizeDp-barHeightDp) * 16) / longSizeDp;
1041 // We have computed the aspect ratio with the bar height taken
1042 // out to be 16:aspect. If this is less than 9, then hiding
1043 // the navigation bar will provide more useful space for wide
1044 // screen movies.
1045 mCanHideNavigationBar = aspect < 9;
1046 } else if (mHasNavigationBar) {
1047 // The navigation bar is at the right in landscape; it seems always
1048 // useful to hide it for showing a video.
1049 mCanHideNavigationBar = true;
1050 } else {
1051 mCanHideNavigationBar = false;
1052 }
Erik Gilling9a41ef82011-09-26 19:21:03 -07001053
1054 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
1055 mHdmiRotation = mPortraitRotation;
1056 } else {
1057 mHdmiRotation = mLandscapeRotation;
1058 }
Dianne Hackborn9d132642011-04-21 17:26:39 -07001059 }
1060
Dianne Hackbornc777e072010-02-12 13:07:59 -08001061 public void updateSettings() {
1062 ContentResolver resolver = mContext.getContentResolver();
1063 boolean updateRotation = false;
Dianne Hackbornc777e072010-02-12 13:07:59 -08001064 synchronized (mLock) {
1065 mEndcallBehavior = Settings.System.getInt(resolver,
David Brownbaf8d092010-03-08 21:52:59 -08001066 Settings.System.END_BUTTON_BEHAVIOR,
1067 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT);
1068 mIncallPowerBehavior = Settings.Secure.getInt(resolver,
1069 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
1070 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001071
Jeff Brown207673cd2012-06-05 17:47:11 -07001072 // Configure rotation lock.
1073 int userRotation = Settings.System.getInt(resolver,
1074 Settings.System.USER_ROTATION, Surface.ROTATION_0);
1075 if (mUserRotation != userRotation) {
1076 mUserRotation = userRotation;
1077 updateRotation = true;
1078 }
1079 int userRotationMode = Settings.System.getInt(resolver,
1080 Settings.System.ACCELEROMETER_ROTATION, 0) != 0 ?
1081 WindowManagerPolicy.USER_ROTATION_FREE :
1082 WindowManagerPolicy.USER_ROTATION_LOCKED;
1083 if (mUserRotationMode != userRotationMode) {
1084 mUserRotationMode = userRotationMode;
1085 updateRotation = true;
Dianne Hackbornc777e072010-02-12 13:07:59 -08001086 updateOrientationListenerLp();
1087 }
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001088
Dianne Hackbornc777e072010-02-12 13:07:59 -08001089 if (mSystemReady) {
1090 int pointerLocation = Settings.System.getInt(resolver,
1091 Settings.System.POINTER_LOCATION, 0);
1092 if (mPointerLocationMode != pointerLocation) {
1093 mPointerLocationMode = pointerLocation;
Jeff Brown70825162012-03-28 17:27:48 -07001094 mHandler.sendEmptyMessage(pointerLocation != 0 ?
1095 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001096 }
1097 }
1098 // use screen off timeout setting as the timeout for the lockscreen
1099 mLockScreenTimeout = Settings.System.getInt(resolver,
1100 Settings.System.SCREEN_OFF_TIMEOUT, 0);
1101 String imId = Settings.Secure.getString(resolver,
1102 Settings.Secure.DEFAULT_INPUT_METHOD);
1103 boolean hasSoftInput = imId != null && imId.length() > 0;
1104 if (mHasSoftInput != hasSoftInput) {
1105 mHasSoftInput = hasSoftInput;
1106 updateRotation = true;
1107 }
1108 }
1109 if (updateRotation) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07001110 updateRotation(true);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001111 }
Jeff Brown70825162012-03-28 17:27:48 -07001112 }
1113
1114 private void enablePointerLocation() {
1115 if (mPointerLocationView == null) {
1116 mPointerLocationView = new PointerLocationView(mContext);
1117 mPointerLocationView.setPrintCoords(false);
1118
Dianne Hackbornc777e072010-02-12 13:07:59 -08001119 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
1120 WindowManager.LayoutParams.MATCH_PARENT,
1121 WindowManager.LayoutParams.MATCH_PARENT);
Jeff Brown3b2b3542010-10-15 00:54:27 -07001122 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
Jeff Brownbfcb60a2011-09-08 18:51:14 -07001123 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
1124 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
1125 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1126 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Dianne Hackbornc777e072010-02-12 13:07:59 -08001127 lp.format = PixelFormat.TRANSLUCENT;
1128 lp.setTitle("PointerLocation");
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001129 WindowManager wm = (WindowManager)
Dianne Hackbornc777e072010-02-12 13:07:59 -08001130 mContext.getSystemService(Context.WINDOW_SERVICE);
Jeff Browncc4f7db2011-08-30 20:34:48 -07001131 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
Jeff Brown70825162012-03-28 17:27:48 -07001132 wm.addView(mPointerLocationView, lp);
1133
Jeff Brownac143512012-04-05 18:57:33 -07001134 mPointerLocationInputChannel =
1135 mWindowManagerFuncs.monitorInput("PointerLocationView");
1136 mPointerLocationInputEventReceiver =
1137 new PointerLocationInputEventReceiver(mPointerLocationInputChannel,
1138 Looper.myLooper(), mPointerLocationView);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001139 }
Dianne Hackbornc777e072010-02-12 13:07:59 -08001140 }
Jeff Brown70825162012-03-28 17:27:48 -07001141
1142 private void disablePointerLocation() {
1143 if (mPointerLocationInputEventReceiver != null) {
1144 mPointerLocationInputEventReceiver.dispose();
1145 mPointerLocationInputEventReceiver = null;
1146 }
1147
1148 if (mPointerLocationInputChannel != null) {
1149 mPointerLocationInputChannel.dispose();
1150 mPointerLocationInputChannel = null;
1151 }
1152
1153 if (mPointerLocationView != null) {
1154 WindowManager wm = (WindowManager)
1155 mContext.getSystemService(Context.WINDOW_SERVICE);
1156 wm.removeView(mPointerLocationView);
1157 mPointerLocationView = null;
1158 }
1159 }
1160
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001161 private int readRotation(int resID) {
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001162 try {
1163 int rotation = mContext.getResources().getInteger(resID);
1164 switch (rotation) {
1165 case 0:
1166 return Surface.ROTATION_0;
1167 case 90:
1168 return Surface.ROTATION_90;
1169 case 180:
1170 return Surface.ROTATION_180;
1171 case 270:
1172 return Surface.ROTATION_270;
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001173 }
1174 } catch (Resources.NotFoundException e) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001175 // fall through
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001176 }
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001177 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001178 }
1179
1180 /** {@inheritDoc} */
1181 public int checkAddPermission(WindowManager.LayoutParams attrs) {
1182 int type = attrs.type;
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07001183
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001184 if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
1185 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
Jeff Brown98365d72012-08-19 20:30:52 -07001186 return WindowManagerGlobal.ADD_OKAY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001187 }
1188 String permission = null;
1189 switch (type) {
1190 case TYPE_TOAST:
1191 // XXX right now the app process has complete control over
1192 // this... should introduce a token to let the system
1193 // monitor/control what they are doing.
1194 break;
Daniel Sandler7d276c32012-01-30 14:33:52 -05001195 case TYPE_DREAM:
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001196 case TYPE_INPUT_METHOD:
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -07001197 case TYPE_WALLPAPER:
1198 // The window manager will check these.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001199 break;
1200 case TYPE_PHONE:
1201 case TYPE_PRIORITY_PHONE:
1202 case TYPE_SYSTEM_ALERT:
1203 case TYPE_SYSTEM_ERROR:
1204 case TYPE_SYSTEM_OVERLAY:
1205 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
1206 break;
1207 default:
1208 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
1209 }
1210 if (permission != null) {
1211 if (mContext.checkCallingOrSelfPermission(permission)
1212 != PackageManager.PERMISSION_GRANTED) {
Jeff Brown98365d72012-08-19 20:30:52 -07001213 return WindowManagerGlobal.ADD_PERMISSION_DENIED;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001214 }
1215 }
Jeff Brown98365d72012-08-19 20:30:52 -07001216 return WindowManagerGlobal.ADD_OKAY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001217 }
1218
1219 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
1220 switch (attrs.type) {
1221 case TYPE_SYSTEM_OVERLAY:
Jeff Brown3b2b3542010-10-15 00:54:27 -07001222 case TYPE_SECURE_SYSTEM_OVERLAY:
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001223 case TYPE_TOAST:
1224 // These types of windows can't receive input events.
1225 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1226 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Jeff Brownbfcb60a2011-09-08 18:51:14 -07001227 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001228 break;
1229 }
1230 }
1231
1232 void readLidState() {
Jeff Brown2e7760e2012-04-11 15:14:55 -07001233 mLidState = mWindowManagerFuncs.getLidState();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001234 }
1235
Jeff Browndaa37532012-05-01 15:54:03 -07001236 private boolean isHidden(int accessibilityMode) {
1237 switch (accessibilityMode) {
1238 case 1:
1239 return mLidState == LID_CLOSED;
1240 case 2:
1241 return mLidState == LID_OPEN;
1242 default:
1243 return false;
Dianne Hackborn2862fff2009-09-15 22:56:29 -07001244 }
Dianne Hackborn2862fff2009-09-15 22:56:29 -07001245 }
Jeff Brownd04a88c2011-01-16 14:05:47 -08001246
Jeff Browndaa37532012-05-01 15:54:03 -07001247 private boolean isBuiltInKeyboardVisible() {
1248 return mHaveBuiltInKeyboard && !isHidden(mLidKeyboardAccessibility);
Jeff Brownc458ce92012-04-30 14:58:40 -07001249 }
1250
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001251 /** {@inheritDoc} */
Jeff Browndaa37532012-05-01 15:54:03 -07001252 public void adjustConfigurationLw(Configuration config, int keyboardPresence,
1253 int navigationPresence) {
1254 mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
1255
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001256 readLidState();
Jeff Brownc458ce92012-04-30 14:58:40 -07001257 applyLidSwitchState();
Jeff Brownd04a88c2011-01-16 14:05:47 -08001258
Jeff Browndaa37532012-05-01 15:54:03 -07001259 if (config.keyboard == Configuration.KEYBOARD_NOKEYS
1260 || (keyboardPresence == PRESENCE_INTERNAL
1261 && isHidden(mLidKeyboardAccessibility))) {
Jeff Brownd04a88c2011-01-16 14:05:47 -08001262 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
Jeff Browndaa37532012-05-01 15:54:03 -07001263 if (!mHasSoftInput) {
1264 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
1265 }
Jeff Brownd04a88c2011-01-16 14:05:47 -08001266 }
1267
Jeff Browndaa37532012-05-01 15:54:03 -07001268 if (config.navigation == Configuration.NAVIGATION_NONAV
1269 || (navigationPresence == PRESENCE_INTERNAL
1270 && isHidden(mLidNavigationAccessibility))) {
Jeff Brownd04a88c2011-01-16 14:05:47 -08001271 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
Jeff Brownd04a88c2011-01-16 14:05:47 -08001272 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001273 }
Jeff Brownd04a88c2011-01-16 14:05:47 -08001274
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001275 /** {@inheritDoc} */
1276 public int windowTypeToLayerLw(int type) {
1277 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
1278 return APPLICATION_LAYER;
1279 }
1280 switch (type) {
1281 case TYPE_STATUS_BAR:
1282 return STATUS_BAR_LAYER;
1283 case TYPE_STATUS_BAR_PANEL:
1284 return STATUS_BAR_PANEL_LAYER;
Joe Onorato29fc2c92010-11-24 10:26:50 -08001285 case TYPE_STATUS_BAR_SUB_PANEL:
1286 return STATUS_BAR_SUB_PANEL_LAYER;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -08001287 case TYPE_SYSTEM_DIALOG:
1288 return SYSTEM_DIALOG_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001289 case TYPE_SEARCH_BAR:
1290 return SEARCH_BAR_LAYER;
1291 case TYPE_PHONE:
1292 return PHONE_LAYER;
1293 case TYPE_KEYGUARD:
1294 return KEYGUARD_LAYER;
1295 case TYPE_KEYGUARD_DIALOG:
1296 return KEYGUARD_DIALOG_LAYER;
1297 case TYPE_SYSTEM_ALERT:
1298 return SYSTEM_ALERT_LAYER;
1299 case TYPE_SYSTEM_ERROR:
1300 return SYSTEM_ERROR_LAYER;
1301 case TYPE_INPUT_METHOD:
1302 return INPUT_METHOD_LAYER;
1303 case TYPE_INPUT_METHOD_DIALOG:
1304 return INPUT_METHOD_DIALOG_LAYER;
Dianne Hackborne8ecde12011-08-03 18:55:19 -07001305 case TYPE_VOLUME_OVERLAY:
1306 return VOLUME_OVERLAY_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001307 case TYPE_SYSTEM_OVERLAY:
1308 return SYSTEM_OVERLAY_LAYER;
Jeff Brown3b2b3542010-10-15 00:54:27 -07001309 case TYPE_SECURE_SYSTEM_OVERLAY:
1310 return SECURE_SYSTEM_OVERLAY_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001311 case TYPE_PRIORITY_PHONE:
1312 return PRIORITY_PHONE_LAYER;
1313 case TYPE_TOAST:
1314 return TOAST_LAYER;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -07001315 case TYPE_WALLPAPER:
1316 return WALLPAPER_LAYER;
Christopher Tatea53146c2010-09-07 11:57:52 -07001317 case TYPE_DRAG:
1318 return DRAG_LAYER;
Jeff Brown83c09682010-12-23 17:50:18 -08001319 case TYPE_POINTER:
1320 return POINTER_LAYER;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001321 case TYPE_NAVIGATION_BAR:
1322 return NAVIGATION_BAR_LAYER;
Jim Millere898ac52012-04-06 17:10:57 -07001323 case TYPE_NAVIGATION_BAR_PANEL:
1324 return NAVIGATION_BAR_PANEL_LAYER;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07001325 case TYPE_BOOT_PROGRESS:
1326 return BOOT_PROGRESS_LAYER;
Dianne Hackborndf89e652011-10-06 22:35:11 -07001327 case TYPE_HIDDEN_NAV_CONSUMER:
1328 return HIDDEN_NAV_CONSUMER_LAYER;
Daniel Sandler7d276c32012-01-30 14:33:52 -05001329 case TYPE_DREAM:
1330 return SCREENSAVER_LAYER;
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -07001331 case TYPE_UNIVERSE_BACKGROUND:
1332 return UNIVERSE_BACKGROUND_LAYER;
Jeff Brownbd6e1502012-08-28 03:27:37 -07001333 case TYPE_DISPLAY_OVERLAY:
1334 return DISPLAY_OVERLAY_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001335 }
1336 Log.e(TAG, "Unknown window type: " + type);
1337 return APPLICATION_LAYER;
1338 }
1339
1340 /** {@inheritDoc} */
1341 public int subWindowTypeToLayerLw(int type) {
1342 switch (type) {
1343 case TYPE_APPLICATION_PANEL:
1344 case TYPE_APPLICATION_ATTACHED_DIALOG:
1345 return APPLICATION_PANEL_SUBLAYER;
1346 case TYPE_APPLICATION_MEDIA:
1347 return APPLICATION_MEDIA_SUBLAYER;
Dianne Hackborn5cb8d792009-05-21 17:34:15 -07001348 case TYPE_APPLICATION_MEDIA_OVERLAY:
1349 return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001350 case TYPE_APPLICATION_SUB_PANEL:
1351 return APPLICATION_SUB_PANEL_SUBLAYER;
1352 }
1353 Log.e(TAG, "Unknown sub-window type: " + type);
1354 return 0;
1355 }
1356
Dianne Hackbornabe0da02009-09-18 01:55:39 -07001357 public int getMaxWallpaperLayer() {
1358 return STATUS_BAR_LAYER;
1359 }
1360
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -07001361 public int getAboveUniverseLayer() {
1362 return SYSTEM_ERROR_LAYER;
1363 }
1364
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001365 public boolean hasSystemNavBar() {
1366 return mHasSystemNavBar;
Dianne Hackborn81e56d52011-05-26 00:55:58 -07001367 }
1368
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001369 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
Dianne Hackborn077ee852012-04-09 16:27:07 -07001370 if (mHasNavigationBar) {
1371 // For a basic navigation bar, when we are in landscape mode we place
1372 // the navigation bar to the side.
Daniel Sandler4a066c52012-04-20 14:49:13 -04001373 if (mNavigationBarCanMove && fullWidth > fullHeight) {
1374 return fullWidth - mNavigationBarWidthForRotation[rotation];
Dianne Hackborn077ee852012-04-09 16:27:07 -07001375 }
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001376 }
1377 return fullWidth;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001378 }
1379
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001380 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
Dianne Hackborn077ee852012-04-09 16:27:07 -07001381 if (mHasSystemNavBar) {
1382 // For the system navigation bar, we always place it at the bottom.
Daniel Sandler4a066c52012-04-20 14:49:13 -04001383 return fullHeight - mNavigationBarHeightForRotation[rotation];
Dianne Hackborn077ee852012-04-09 16:27:07 -07001384 }
1385 if (mHasNavigationBar) {
1386 // For a basic navigation bar, when we are in portrait mode we place
1387 // the navigation bar to the bottom.
Daniel Sandler4a066c52012-04-20 14:49:13 -04001388 if (!mNavigationBarCanMove || fullWidth < fullHeight) {
1389 return fullHeight - mNavigationBarHeightForRotation[rotation];
Dianne Hackborn077ee852012-04-09 16:27:07 -07001390 }
1391 }
1392 return fullHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001393 }
1394
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001395 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
1396 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation);
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001397 }
1398
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001399 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) {
Dianne Hackborn077ee852012-04-09 16:27:07 -07001400 // If we don't have a system nav bar, then there is a separate status
1401 // bar at the top of the display. We don't count that as part of the
1402 // fixed decor, since it can hide; however, for purposes of configurations,
1403 // we do want to exclude it since applications can't generally use that part
1404 // of the screen.
1405 if (!mHasSystemNavBar) {
1406 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) - mStatusBarHeight;
1407 }
1408 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001409 }
1410
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001411 public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
1412 return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
1413 }
1414
1415 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
1416 return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001417 && attrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -07001418 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER
1419 && attrs.type != WindowManager.LayoutParams.TYPE_UNIVERSE_BACKGROUND;
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001420 }
Craig Mautner8e4df6c2012-05-23 16:57:23 -07001421
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001422 /** {@inheritDoc} */
Craig Mautner8e4df6c2012-05-23 16:57:23 -07001423 @Override
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001424 public View addStartingWindow(IBinder appToken, String packageName, int theme,
1425 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
1426 int icon, int windowFlags) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001427 if (!SHOW_STARTING_ANIMATIONS) {
1428 return null;
1429 }
1430 if (packageName == null) {
1431 return null;
1432 }
Craig Mautner8e4df6c2012-05-23 16:57:23 -07001433
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001434 try {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001435 Context context = mContext;
Craig Mautner6fbda632012-07-03 09:26:39 -07001436 if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName
1437 + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
1438 + Integer.toHexString(theme));
Dianne Hackborn247fe742011-01-08 17:25:57 -08001439 if (theme != context.getThemeResId() || labelRes != 0) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001440 try {
1441 context = context.createPackageContext(packageName, 0);
Dianne Hackborn247fe742011-01-08 17:25:57 -08001442 context.setTheme(theme);
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001443 } catch (PackageManager.NameNotFoundException e) {
1444 // Ignore
1445 }
1446 }
Craig Mautner8e4df6c2012-05-23 16:57:23 -07001447
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001448 Window win = PolicyManager.makeNewWindow(context);
Craig Mautner8e4df6c2012-05-23 16:57:23 -07001449 final TypedArray ta = win.getWindowStyle();
1450 if (ta.getBoolean(
1451 com.android.internal.R.styleable.Window_windowDisablePreview, false)
1452 || ta.getBoolean(
1453 com.android.internal.R.styleable.Window_windowShowWallpaper,false)) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001454 return null;
1455 }
Craig Mautner8e4df6c2012-05-23 16:57:23 -07001456
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001457 Resources r = context.getResources();
1458 win.setTitle(r.getText(labelRes, nonLocalizedLabel));
Craig Mautner8e4df6c2012-05-23 16:57:23 -07001459
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001460 win.setType(
1461 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
1462 // Force the window flags: this is a fake window, so it is not really
1463 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
1464 // flag because we do know that the next window will take input
1465 // focus, so we want to get the IME window up on top of us right away.
1466 win.setFlags(
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001467 windowFlags|
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001468 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
1469 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
1470 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001471 windowFlags|
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001472 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
1473 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
1474 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
Craig Mautner8e4df6c2012-05-23 16:57:23 -07001475
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001476 if (!compatInfo.supportsScreen()) {
1477 win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW);
1478 }
1479
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001480 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001481 WindowManager.LayoutParams.MATCH_PARENT);
Craig Mautner8e4df6c2012-05-23 16:57:23 -07001482
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001483 final WindowManager.LayoutParams params = win.getAttributes();
1484 params.token = appToken;
1485 params.packageName = packageName;
1486 params.windowAnimations = win.getWindowStyle().getResourceId(
1487 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
Dianne Hackborn5d927c22011-09-02 12:22:18 -07001488 params.privateFlags |=
1489 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001490 params.setTitle("Starting " + packageName);
1491
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001492 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001493 View view = win.getDecorView();
1494
1495 if (win.isFloating()) {
1496 // Whoops, there is no way to display an animation/preview
1497 // of such a thing! After all that work... let's skip it.
1498 // (Note that we must do this here because it is in
1499 // getDecorView() where the theme is evaluated... maybe
1500 // we should peek the floating attribute from the theme
1501 // earlier.)
1502 return null;
1503 }
Craig Mautner8e4df6c2012-05-23 16:57:23 -07001504
Craig Mautner6fbda632012-07-03 09:26:39 -07001505 if (DEBUG_STARTING_WINDOW) Slog.d(
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001506 TAG, "Adding starting window for " + packageName
1507 + " / " + appToken + ": "
1508 + (view.getParent() != null ? view : null));
1509
1510 wm.addView(view, params);
1511
1512 // Only return the view if it was successfully added to the
1513 // window manager... which we can tell by it having a parent.
1514 return view.getParent() != null ? view : null;
Jeff Brown98365d72012-08-19 20:30:52 -07001515 } catch (WindowManager.BadTokenException e) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001516 // ignore
1517 Log.w(TAG, appToken + " already running, starting window not displayed");
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001518 } catch (RuntimeException e) {
1519 // don't crash if something else bad happens, for example a
1520 // failure loading resources because we are loading from an app
1521 // on external storage that has been unmounted.
1522 Log.w(TAG, appToken + " failed creating starting window", e);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001523 }
1524
1525 return null;
1526 }
1527
1528 /** {@inheritDoc} */
1529 public void removeStartingWindow(IBinder appToken, View window) {
Craig Mautner6fbda632012-07-03 09:26:39 -07001530 if (DEBUG_STARTING_WINDOW) {
1531 RuntimeException e = new RuntimeException("here");
1532 e.fillInStackTrace();
1533 Log.v(TAG, "Removing starting window for " + appToken + ": " + window, e);
1534 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001535
1536 if (window != null) {
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001537 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001538 wm.removeView(window);
1539 }
1540 }
1541
1542 /**
1543 * Preflight adding a window to the system.
1544 *
1545 * Currently enforces that three window types are singletons:
1546 * <ul>
1547 * <li>STATUS_BAR_TYPE</li>
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001548 * <li>KEYGUARD_TYPE</li>
1549 * </ul>
1550 *
1551 * @param win The window to be added
1552 * @param attrs Information about the window to be added
1553 *
Jeff Brown98365d72012-08-19 20:30:52 -07001554 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons,
1555 * WindowManagerImpl.ADD_MULTIPLE_SINGLETON
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001556 */
1557 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
1558 switch (attrs.type) {
1559 case TYPE_STATUS_BAR:
Joe Onorato8bc6c512010-06-04 16:21:12 -04001560 mContext.enforceCallingOrSelfPermission(
1561 android.Manifest.permission.STATUS_BAR_SERVICE,
1562 "PhoneWindowManager");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001563 if (mStatusBar != null) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001564 if (mStatusBar.isAlive()) {
Jeff Brown98365d72012-08-19 20:30:52 -07001565 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001566 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001567 }
1568 mStatusBar = win;
1569 break;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001570 case TYPE_NAVIGATION_BAR:
1571 mContext.enforceCallingOrSelfPermission(
1572 android.Manifest.permission.STATUS_BAR_SERVICE,
1573 "PhoneWindowManager");
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001574 if (mNavigationBar != null) {
1575 if (mNavigationBar.isAlive()) {
Jeff Brown98365d72012-08-19 20:30:52 -07001576 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001577 }
1578 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001579 mNavigationBar = win;
1580 if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
1581 break;
Jim Millere898ac52012-04-06 17:10:57 -07001582 case TYPE_NAVIGATION_BAR_PANEL:
1583 mContext.enforceCallingOrSelfPermission(
1584 android.Manifest.permission.STATUS_BAR_SERVICE,
1585 "PhoneWindowManager");
1586 break;
Dianne Hackborn08743722009-12-21 12:16:51 -08001587 case TYPE_STATUS_BAR_PANEL:
Joe Onorato8bc6c512010-06-04 16:21:12 -04001588 mContext.enforceCallingOrSelfPermission(
1589 android.Manifest.permission.STATUS_BAR_SERVICE,
1590 "PhoneWindowManager");
Dianne Hackborn08743722009-12-21 12:16:51 -08001591 break;
Joe Onorato29fc2c92010-11-24 10:26:50 -08001592 case TYPE_STATUS_BAR_SUB_PANEL:
1593 mContext.enforceCallingOrSelfPermission(
1594 android.Manifest.permission.STATUS_BAR_SERVICE,
1595 "PhoneWindowManager");
Joe Onorato29fc2c92010-11-24 10:26:50 -08001596 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001597 case TYPE_KEYGUARD:
1598 if (mKeyguard != null) {
Jeff Brown98365d72012-08-19 20:30:52 -07001599 return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001600 }
1601 mKeyguard = win;
1602 break;
1603 }
Jeff Brown98365d72012-08-19 20:30:52 -07001604 return WindowManagerGlobal.ADD_OKAY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001605 }
1606
1607 /** {@inheritDoc} */
1608 public void removeWindowLw(WindowState win) {
1609 if (mStatusBar == win) {
1610 mStatusBar = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001611 } else if (mKeyguard == win) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001612 mKeyguard = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001613 } else if (mNavigationBar == win) {
1614 mNavigationBar = null;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001615 }
1616 }
1617
1618 static final boolean PRINT_ANIM = false;
1619
1620 /** {@inheritDoc} */
1621 public int selectAnimationLw(WindowState win, int transit) {
1622 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
1623 + ": transit=" + transit);
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001624 if (win == mStatusBar) {
1625 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1626 return R.anim.dock_top_exit;
1627 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1628 return R.anim.dock_top_enter;
1629 }
1630 } else if (win == mNavigationBar) {
1631 // This can be on either the bottom or the right.
1632 if (mNavigationBarOnBottom) {
1633 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1634 return R.anim.dock_bottom_exit;
1635 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1636 return R.anim.dock_bottom_enter;
1637 }
1638 } else {
1639 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1640 return R.anim.dock_right_exit;
1641 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1642 return R.anim.dock_right_enter;
1643 }
1644 }
1645 } if (transit == TRANSIT_PREVIEW_DONE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001646 if (win.hasAppShownWindows()) {
1647 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
1648 return com.android.internal.R.anim.app_starting_exit;
1649 }
1650 }
1651
1652 return 0;
1653 }
1654
Dianne Hackborn0c2acff2012-04-12 15:17:07 -07001655 public Animation createForceHideEnterAnimation(boolean onWallpaper) {
1656 return AnimationUtils.loadAnimation(mContext, onWallpaper
1657 ? com.android.internal.R.anim.lock_screen_wallpaper_behind_enter
1658 : com.android.internal.R.anim.lock_screen_behind_enter);
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001659 }
1660
Jeff Brown4d396052010-10-29 21:50:21 -07001661 static ITelephony getTelephonyService() {
Mike Lockwoodf5f4ec92011-11-08 14:05:31 -08001662 return ITelephony.Stub.asInterface(
Jeff Brown4d396052010-10-29 21:50:21 -07001663 ServiceManager.checkService(Context.TELEPHONY_SERVICE));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001664 }
1665
Jeff Brown4d396052010-10-29 21:50:21 -07001666 static IAudioService getAudioService() {
1667 IAudioService audioService = IAudioService.Stub.asInterface(
1668 ServiceManager.checkService(Context.AUDIO_SERVICE));
1669 if (audioService == null) {
1670 Log.w(TAG, "Unable to find IAudioService interface.");
1671 }
1672 return audioService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001673 }
1674
1675 boolean keyguardOn() {
1676 return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
1677 }
1678
1679 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
1680 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
1681 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
1682 };
1683
1684 /** {@inheritDoc} */
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001685 @Override
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001686 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001687 final boolean keyguardOn = keyguardOn();
Jeff Brown1f245102010-11-18 20:53:46 -08001688 final int keyCode = event.getKeyCode();
1689 final int repeatCount = event.getRepeatCount();
1690 final int metaState = event.getMetaState();
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001691 final int flags = event.getFlags();
Jeff Brown1f245102010-11-18 20:53:46 -08001692 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
1693 final boolean canceled = event.isCanceled();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001694
Jeff Brown40013652012-05-16 21:22:36 -07001695 if (DEBUG_INPUT) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001696 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
Jeff Brownfd23e3e2012-05-09 13:34:28 -07001697 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed
1698 + " canceled=" + canceled);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001699 }
1700
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001701 // If we think we might have a volume down & power key chord on the way
1702 // but we're not sure, then tell the dispatcher to wait a little while and
1703 // try again later before dispatching.
Christopher Tatee90585f2012-03-05 18:56:25 -08001704 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001705 if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
1706 final long now = SystemClock.uptimeMillis();
1707 final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
1708 if (now < timeoutTime) {
1709 return timeoutTime - now;
1710 }
1711 }
1712 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
1713 && mVolumeDownKeyConsumedByScreenshotChord) {
1714 if (!down) {
1715 mVolumeDownKeyConsumedByScreenshotChord = false;
1716 }
1717 return -1;
1718 }
1719 }
1720
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001721 // First we always handle the home key here, so applications
1722 // can never break it, although if keyguard is on, we do let
1723 // it handle it, because that gives us the correct 5 second
1724 // timeout.
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001725 if (keyCode == KeyEvent.KEYCODE_HOME) {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001726
Jeff Brown49ed71d2010-12-06 17:13:33 -08001727 // If we have released the home key, and didn't do anything else
1728 // while it was pressed, then it is time to go home!
Michael Jurka7f2668c2012-03-27 07:49:52 -07001729 if (!down) {
1730 final boolean homeWasLongPressed = mHomeLongPressed;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001731 mHomePressed = false;
Michael Jurka7f2668c2012-03-27 07:49:52 -07001732 mHomeLongPressed = false;
1733 if (!homeWasLongPressed) {
Michael Jurka01de93d2012-04-13 09:32:47 -07001734 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
1735 try {
1736 IStatusBarService statusbar = getStatusBarService();
1737 if (statusbar != null) {
1738 statusbar.cancelPreloadRecentApps();
1739 }
1740 } catch (RemoteException e) {
1741 Slog.e(TAG, "RemoteException when showing recent apps", e);
1742 // re-acquire status bar service next time it is needed.
1743 mStatusBarService = null;
Dianne Hackborn42e620c2012-06-24 13:20:51 -07001744 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001745 }
1746
Michael Jurka7f2668c2012-03-27 07:49:52 -07001747 mHomePressed = false;
1748 if (!canceled) {
1749 // If an incoming call is ringing, HOME is totally disabled.
1750 // (The user is already on the InCallScreen at this point,
1751 // and his ONLY options are to answer or reject the call.)
1752 boolean incomingRinging = false;
1753 try {
1754 ITelephony telephonyService = getTelephonyService();
1755 if (telephonyService != null) {
1756 incomingRinging = telephonyService.isRinging();
1757 }
1758 } catch (RemoteException ex) {
1759 Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
1760 }
1761
1762 if (incomingRinging) {
1763 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
1764 } else {
1765 launchHomeFromHotKey();
1766 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001767 } else {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001768 Log.i(TAG, "Ignoring HOME; event canceled.");
Jeff Brown49ed71d2010-12-06 17:13:33 -08001769 }
Michael Jurka7f2668c2012-03-27 07:49:52 -07001770 return -1;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001771 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001772 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001773
1774 // If a system window has focus, then it doesn't make sense
1775 // right now to interact with applications.
1776 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
1777 if (attrs != null) {
1778 final int type = attrs.type;
1779 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
1780 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
1781 // the "app" is keyguard, so give it the key
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001782 return 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001783 }
1784 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
1785 for (int i=0; i<typeCount; i++) {
1786 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
1787 // don't do anything, but also don't pass it to the app
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001788 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001789 }
1790 }
1791 }
Jeff Brown98392ef2011-09-12 18:24:59 -07001792 if (down) {
Michael Jurka40040332012-05-29 08:25:32 -07001793 if (!mHomePressed && mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001794 try {
Dianne Hackborn42e620c2012-06-24 13:20:51 -07001795 IStatusBarService statusbar = getStatusBarService();
1796 if (statusbar != null) {
1797 statusbar.preloadRecentApps();
1798 }
Michael Jurka7f2668c2012-03-27 07:49:52 -07001799 } catch (RemoteException e) {
1800 Slog.e(TAG, "RemoteException when preloading recent apps", e);
Dianne Hackborn42e620c2012-06-24 13:20:51 -07001801 // re-acquire status bar service next time it is needed.
1802 mStatusBarService = null;
Michael Jurka7f2668c2012-03-27 07:49:52 -07001803 }
1804 }
Jeff Brown98392ef2011-09-12 18:24:59 -07001805 if (repeatCount == 0) {
1806 mHomePressed = true;
1807 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
1808 if (!keyguardOn) {
1809 handleLongPressOnHome();
1810 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001811 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001812 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001813 return -1;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001814 } else if (keyCode == KeyEvent.KEYCODE_MENU) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001815 // Hijack modified menu keys for debugging features
1816 final int chordBug = KeyEvent.META_SHIFT_ON;
1817
1818 if (down && repeatCount == 0) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001819 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001820 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001821 mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT,
1822 null, null, null, 0, null, null);
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001823 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001824 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001825 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001826 Intent service = new Intent();
1827 service.setClassName(mContext, "com.android.server.LoadAverageService");
1828 ContentResolver res = mContext.getContentResolver();
1829 boolean shown = Settings.System.getInt(
1830 res, Settings.System.SHOW_PROCESSES, 0) != 0;
1831 if (!shown) {
1832 mContext.startService(service);
1833 } else {
1834 mContext.stopService(service);
1835 }
1836 Settings.System.putInt(
1837 res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001838 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001839 }
1840 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001841 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001842 if (down) {
1843 if (repeatCount == 0) {
Jeff Brownfd23e3e2012-05-09 13:34:28 -07001844 mSearchKeyShortcutPending = true;
1845 mConsumeSearchKeyUp = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001846 }
Jeff Brownfd23e3e2012-05-09 13:34:28 -07001847 } else {
1848 mSearchKeyShortcutPending = false;
1849 if (mConsumeSearchKeyUp) {
1850 mConsumeSearchKeyUp = false;
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001851 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001852 }
1853 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001854 return 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001855 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
Jeff Brown602ab322012-05-16 13:33:47 -07001856 if (down && repeatCount == 0 && !keyguardOn) {
Jeff Brown68b909d2011-12-07 16:36:01 -08001857 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
Jeff Brown49ed71d2010-12-06 17:13:33 -08001858 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001859 return -1;
Jeff Brownde7a8ea2012-06-13 18:28:57 -07001860 } else if (keyCode == KeyEvent.KEYCODE_ASSIST) {
1861 if (down) {
1862 if (repeatCount == 0) {
1863 mAssistKeyLongPressed = false;
1864 } else if (repeatCount == 1) {
1865 mAssistKeyLongPressed = true;
1866 if (!keyguardOn) {
1867 launchAssistLongPressAction();
1868 }
1869 }
1870 } else {
1871 if (mAssistKeyLongPressed) {
1872 mAssistKeyLongPressed = false;
1873 } else {
1874 if (!keyguardOn) {
1875 launchAssistAction();
1876 }
1877 }
1878 }
1879 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001880 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001881
Jeff Brownc1fb48d2010-12-08 16:52:09 -08001882 // Shortcuts are invoked through Search+key, so intercept those here
Jeff Browncaab4d02010-12-09 22:13:41 -08001883 // Any printing key that is chorded with Search should be consumed
1884 // even if no shortcut was invoked. This prevents text from being
1885 // inadvertently inserted when using a keyboard that has built-in macro
1886 // shortcut keys (that emit Search+x) and some of them are not registered.
Jeff Brownfd23e3e2012-05-09 13:34:28 -07001887 if (mSearchKeyShortcutPending) {
Jeff Browncaab4d02010-12-09 22:13:41 -08001888 final KeyCharacterMap kcm = event.getKeyCharacterMap();
1889 if (kcm.isPrintingKey(keyCode)) {
Jeff Brownfd23e3e2012-05-09 13:34:28 -07001890 mConsumeSearchKeyUp = true;
1891 mSearchKeyShortcutPending = false;
Jeff Browncaab4d02010-12-09 22:13:41 -08001892 if (down && repeatCount == 0 && !keyguardOn) {
1893 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
1894 if (shortcutIntent != null) {
1895 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Jeff Brownf0a3cc52011-01-26 18:42:46 -08001896 try {
1897 mContext.startActivity(shortcutIntent);
1898 } catch (ActivityNotFoundException ex) {
1899 Slog.w(TAG, "Dropping shortcut key combination because "
1900 + "the activity to which it is registered was not found: "
Jeff Brownfd23e3e2012-05-09 13:34:28 -07001901 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode), ex);
Jeff Brownf0a3cc52011-01-26 18:42:46 -08001902 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001903 } else {
1904 Slog.i(TAG, "Dropping unregistered shortcut key combination: "
Jeff Brownfd23e3e2012-05-09 13:34:28 -07001905 + "SEARCH+" + KeyEvent.keyCodeToString(keyCode));
Jeff Brown49ed71d2010-12-06 17:13:33 -08001906 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001907 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001908 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001909 }
1910 }
1911
Jeff Brown68b909d2011-12-07 16:36:01 -08001912 // Invoke shortcuts using Meta.
Jeff Brown602ab322012-05-16 13:33:47 -07001913 if (down && repeatCount == 0 && !keyguardOn
Jeff Brown68b909d2011-12-07 16:36:01 -08001914 && (metaState & KeyEvent.META_META_ON) != 0) {
1915 final KeyCharacterMap kcm = event.getKeyCharacterMap();
Jeff Brown602ab322012-05-16 13:33:47 -07001916 if (kcm.isPrintingKey(keyCode)) {
1917 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
1918 metaState & ~(KeyEvent.META_META_ON
1919 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
1920 if (shortcutIntent != null) {
1921 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1922 try {
1923 mContext.startActivity(shortcutIntent);
1924 } catch (ActivityNotFoundException ex) {
1925 Slog.w(TAG, "Dropping shortcut key combination because "
1926 + "the activity to which it is registered was not found: "
1927 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
1928 }
1929 return -1;
Jeff Brown68b909d2011-12-07 16:36:01 -08001930 }
Jeff Brown68b909d2011-12-07 16:36:01 -08001931 }
1932 }
1933
Jeff Brown6651a632011-11-28 12:59:11 -08001934 // Handle application launch keys.
Jeff Brown602ab322012-05-16 13:33:47 -07001935 if (down && repeatCount == 0 && !keyguardOn) {
Jeff Brown6651a632011-11-28 12:59:11 -08001936 String category = sApplicationLaunchKeyCategories.get(keyCode);
1937 if (category != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -08001938 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
Jeff Brown6651a632011-11-28 12:59:11 -08001939 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1940 try {
1941 mContext.startActivity(intent);
1942 } catch (ActivityNotFoundException ex) {
1943 Slog.w(TAG, "Dropping application launch key because "
1944 + "the activity to which it is registered was not found: "
1945 + "keyCode=" + keyCode + ", category=" + category, ex);
1946 }
Jeff Brown68b909d2011-12-07 16:36:01 -08001947 return -1;
Jeff Brown6651a632011-11-28 12:59:11 -08001948 }
1949 }
1950
Jeff Brown68b909d2011-12-07 16:36:01 -08001951 // Display task switcher for ALT-TAB or Meta-TAB.
1952 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
Jeff Brown602ab322012-05-16 13:33:47 -07001953 if (mRecentAppsDialogHeldModifiers == 0 && !keyguardOn) {
Jeff Brown68b909d2011-12-07 16:36:01 -08001954 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
1955 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
1956 || KeyEvent.metaStateHasModifiers(
1957 shiftlessModifiers, KeyEvent.META_META_ON)) {
1958 mRecentAppsDialogHeldModifiers = shiftlessModifiers;
1959 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);
1960 return -1;
1961 }
1962 }
1963 } else if (!down && mRecentAppsDialogHeldModifiers != 0
1964 && (metaState & mRecentAppsDialogHeldModifiers) == 0) {
1965 mRecentAppsDialogHeldModifiers = 0;
Jeff Brown602ab322012-05-16 13:33:47 -07001966 showOrHideRecentAppsDialog(keyguardOn ? RECENT_APPS_BEHAVIOR_DISMISS :
1967 RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);
Jeff Brown68b909d2011-12-07 16:36:01 -08001968 }
1969
Jeff Browncf39bdf2012-05-18 14:41:19 -07001970 // Handle keyboard language switching.
1971 if (down && repeatCount == 0
1972 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
1973 || (keyCode == KeyEvent.KEYCODE_SPACE
1974 && (metaState & KeyEvent.META_CTRL_MASK) != 0))) {
1975 int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
1976 mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
1977 return -1;
1978 }
1979 if (mLanguageSwitchKeyPressed && !down
1980 && (keyCode == KeyEvent.KEYCODE_LANGUAGE_SWITCH
1981 || keyCode == KeyEvent.KEYCODE_SPACE)) {
1982 mLanguageSwitchKeyPressed = false;
1983 return -1;
1984 }
1985
Jeff Brown68b909d2011-12-07 16:36:01 -08001986 // Let the application handle the key.
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001987 return 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001988 }
1989
Jeff Brown3915bb82010-11-05 15:02:16 -07001990 /** {@inheritDoc} */
1991 @Override
Jeff Brown49ed71d2010-12-06 17:13:33 -08001992 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
Jeff Brown54875002011-04-06 15:33:01 -07001993 // Note: This method is only called if the initial down was unhandled.
Jeff Brown40013652012-05-16 21:22:36 -07001994 if (DEBUG_INPUT) {
Jeff Brown1f245102010-11-18 20:53:46 -08001995 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
1996 + ", flags=" + event.getFlags()
1997 + ", keyCode=" + event.getKeyCode()
1998 + ", scanCode=" + event.getScanCode()
1999 + ", metaState=" + event.getMetaState()
2000 + ", repeatCount=" + event.getRepeatCount()
2001 + ", policyFlags=" + policyFlags);
Jeff Brown3915bb82010-11-05 15:02:16 -07002002 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08002003
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002004 KeyEvent fallbackEvent = null;
Jeff Brown49ed71d2010-12-06 17:13:33 -08002005 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
2006 final KeyCharacterMap kcm = event.getKeyCharacterMap();
Jeff Brownc1fb48d2010-12-08 16:52:09 -08002007 final int keyCode = event.getKeyCode();
2008 final int metaState = event.getMetaState();
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002009 final boolean initialDown = event.getAction() == KeyEvent.ACTION_DOWN
2010 && event.getRepeatCount() == 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08002011
Jeff Brown54875002011-04-06 15:33:01 -07002012 // Check for fallback actions specified by the key character map.
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002013 final FallbackAction fallbackAction;
2014 if (initialDown) {
2015 fallbackAction = kcm.getFallbackAction(keyCode, metaState);
2016 } else {
2017 fallbackAction = mFallbackActions.get(keyCode);
2018 }
2019
2020 if (fallbackAction != null) {
Jeff Brown40013652012-05-16 21:22:36 -07002021 if (DEBUG_INPUT) {
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002022 Slog.d(TAG, "Fallback: keyCode=" + fallbackAction.keyCode
2023 + " metaState=" + Integer.toHexString(fallbackAction.metaState));
Jeff Brown49ed71d2010-12-06 17:13:33 -08002024 }
2025
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002026 final int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
2027 fallbackEvent = KeyEvent.obtain(
Jeff Brown49ed71d2010-12-06 17:13:33 -08002028 event.getDownTime(), event.getEventTime(),
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002029 event.getAction(), fallbackAction.keyCode,
2030 event.getRepeatCount(), fallbackAction.metaState,
Jeff Brown49ed71d2010-12-06 17:13:33 -08002031 event.getDeviceId(), event.getScanCode(),
2032 flags, event.getSource(), null);
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002033
2034 if (!interceptFallback(win, fallbackEvent, policyFlags)) {
2035 fallbackEvent.recycle();
2036 fallbackEvent = null;
Jeff Brown49ed71d2010-12-06 17:13:33 -08002037 }
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002038
2039 if (initialDown) {
2040 mFallbackActions.put(keyCode, fallbackAction);
2041 } else if (event.getAction() == KeyEvent.ACTION_UP) {
2042 mFallbackActions.remove(keyCode);
2043 fallbackAction.recycle();
2044 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08002045 }
2046 }
2047
Jeff Brown40013652012-05-16 21:22:36 -07002048 if (DEBUG_INPUT) {
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002049 if (fallbackEvent == null) {
2050 Slog.d(TAG, "No fallback.");
2051 } else {
2052 Slog.d(TAG, "Performing fallback: " + fallbackEvent);
2053 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08002054 }
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002055 return fallbackEvent;
Jeff Brown3915bb82010-11-05 15:02:16 -07002056 }
2057
Jeff Brownfd23e3e2012-05-09 13:34:28 -07002058 private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
2059 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
2060 if ((actions & ACTION_PASS_TO_USER) != 0) {
2061 long delayMillis = interceptKeyBeforeDispatching(
2062 win, fallbackEvent, policyFlags);
2063 if (delayMillis == 0) {
2064 return true;
2065 }
2066 }
2067 return false;
Jeff Brown6f2fba42011-02-19 01:08:02 -08002068 }
2069
Jeff Brownde7a8ea2012-06-13 18:28:57 -07002070 private void launchAssistLongPressAction() {
2071 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
2072 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
2073
2074 // launch the search activity
2075 Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
2076 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
2077 try {
Jim Miller45308b12012-06-18 19:23:39 -07002078 // TODO: This only stops the factory-installed search manager.
2079 // Need to formalize an API to handle others
Jeff Brownde7a8ea2012-06-13 18:28:57 -07002080 SearchManager searchManager = getSearchManager();
2081 if (searchManager != null) {
2082 searchManager.stopSearch();
2083 }
Dianne Hackborn79af1dd2012-08-16 16:42:52 -07002084 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
Jeff Brownde7a8ea2012-06-13 18:28:57 -07002085 } catch (ActivityNotFoundException e) {
2086 Slog.w(TAG, "No activity to handle assist long press action.", e);
2087 }
2088 }
2089
2090 private void launchAssistAction() {
2091 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
Amith Yamasanic1d07a42012-08-14 09:32:02 -07002092 Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
Dianne Hackbornf02b60a2012-08-16 10:48:27 -07002093 .getAssistIntent(mContext, UserHandle.USER_CURRENT);
Jim Miller45308b12012-06-18 19:23:39 -07002094 if (intent != null) {
2095 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
2096 | Intent.FLAG_ACTIVITY_SINGLE_TOP
2097 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
2098 try {
Dianne Hackborn79af1dd2012-08-16 16:42:52 -07002099 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
Jim Miller45308b12012-06-18 19:23:39 -07002100 } catch (ActivityNotFoundException e) {
2101 Slog.w(TAG, "No activity to handle assist action.", e);
Jeff Brownde7a8ea2012-06-13 18:28:57 -07002102 }
2103 }
2104 }
2105
2106 private SearchManager getSearchManager() {
2107 if (mSearchManager == null) {
2108 mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
2109 }
2110 return mSearchManager;
2111 }
2112
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002113 /**
2114 * A home key -> launch home action was detected. Take the appropriate action
2115 * given the situation with the keyguard.
2116 */
2117 void launchHomeFromHotKey() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002118 if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002119 // don't launch home if keyguard showing
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002120 } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002121 // when in keyguard restricted mode, must first verify unlock
2122 // before launching home
2123 mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
2124 public void onKeyguardExitResult(boolean success) {
2125 if (success) {
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07002126 try {
2127 ActivityManagerNative.getDefault().stopAppSwitches();
2128 } catch (RemoteException e) {
2129 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05002130 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002131 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002132 }
2133 }
2134 });
2135 } else {
2136 // no keyguard stuff to worry about, just launch home!
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07002137 try {
2138 ActivityManagerNative.getDefault().stopAppSwitches();
2139 } catch (RemoteException e) {
2140 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05002141 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002142 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002143 }
2144 }
2145
Dianne Hackborne26ab702011-10-16 13:21:33 -07002146 /**
2147 * A delayed callback use to determine when it is okay to re-allow applications
2148 * to use certain system UI flags. This is used to prevent applications from
2149 * spamming system UI changes that prevent the navigation bar from being shown.
2150 */
2151 final Runnable mAllowSystemUiDelay = new Runnable() {
2152 @Override public void run() {
2153 }
2154 };
2155
2156 /**
2157 * Input handler used while nav bar is hidden. Captures any touch on the screen,
2158 * to determine when the nav bar should be shown and prevent applications from
2159 * receiving those touches.
2160 */
Jeff Brown32cbc38552011-12-01 14:01:49 -08002161 final class HideNavInputEventReceiver extends InputEventReceiver {
2162 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
2163 super(inputChannel, looper);
2164 }
2165
Dianne Hackborndf89e652011-10-06 22:35:11 -07002166 @Override
Jeff Brown32cbc38552011-12-01 14:01:49 -08002167 public void onInputEvent(InputEvent event) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002168 boolean handled = false;
2169 try {
Jeff Brown4952dfd2011-11-30 19:23:22 -08002170 if (event instanceof MotionEvent
2171 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
2172 final MotionEvent motionEvent = (MotionEvent)event;
2173 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002174 // When the user taps down, we re-show the nav bar.
2175 boolean changed = false;
2176 synchronized (mLock) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002177 // Any user activity always causes us to show the
2178 // navigation controls, if they had been hidden.
2179 // We also clear the low profile and only content
2180 // flags so that tapping on the screen will atomically
2181 // restore all currently hidden screen decorations.
2182 int newVal = mResettingSystemUiFlags |
2183 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
2184 View.SYSTEM_UI_FLAG_LOW_PROFILE |
2185 View.SYSTEM_UI_FLAG_FULLSCREEN;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002186 if (mResettingSystemUiFlags != newVal) {
2187 mResettingSystemUiFlags = newVal;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002188 changed = true;
2189 }
Dianne Hackborne26ab702011-10-16 13:21:33 -07002190 // We don't allow the system's nav bar to be hidden
2191 // again for 1 second, to prevent applications from
2192 // spamming us and keeping it from being shown.
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002193 newVal = mForceClearedSystemUiFlags |
2194 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002195 if (mForceClearedSystemUiFlags != newVal) {
2196 mForceClearedSystemUiFlags = newVal;
2197 changed = true;
2198 mHandler.postDelayed(new Runnable() {
2199 @Override public void run() {
2200 synchronized (mLock) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002201 // Clear flags.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002202 mForceClearedSystemUiFlags &=
2203 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
2204 }
2205 mWindowManagerFuncs.reevaluateStatusBarVisibility();
2206 }
2207 }, 1000);
2208 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07002209 }
2210 if (changed) {
2211 mWindowManagerFuncs.reevaluateStatusBarVisibility();
2212 }
2213 }
2214 }
2215 } finally {
Jeff Brown32cbc38552011-12-01 14:01:49 -08002216 finishInputEvent(event, handled);
Dianne Hackborndf89e652011-10-06 22:35:11 -07002217 }
2218 }
Jeff Brown32cbc38552011-12-01 14:01:49 -08002219 }
2220 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
2221 new InputEventReceiver.Factory() {
2222 @Override
2223 public InputEventReceiver createInputEventReceiver(
2224 InputChannel inputChannel, Looper looper) {
2225 return new HideNavInputEventReceiver(inputChannel, looper);
2226 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07002227 };
2228
2229 @Override
2230 public int adjustSystemUiVisibilityLw(int visibility) {
2231 // Reset any bits in mForceClearingStatusBarVisibility that
2232 // are now clear.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002233 mResettingSystemUiFlags &= visibility;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002234 // Clear any bits in the new visibility that are currently being
2235 // force cleared, before reporting it.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002236 return visibility & ~mResettingSystemUiFlags
2237 & ~mForceClearedSystemUiFlags;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002238 }
2239
Craig Mautner69b08182012-09-05 13:07:13 -07002240 @Override
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002241 public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
2242 final int fl = attrs.flags;
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002243 final int systemUiVisibility = (attrs.systemUiVisibility|attrs.subtreeSystemUiVisibility);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002244
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002245 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR))
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002246 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002247 int availRight, availBottom;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002248 if (mCanHideNavigationBar &&
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002249 (systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002250 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
2251 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
2252 } else {
2253 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
2254 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
2255 }
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002256 if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2257 if ((fl & FLAG_FULLSCREEN) != 0) {
2258 contentInset.set(mStableFullscreenLeft, mStableFullscreenTop,
2259 availRight - mStableFullscreenRight,
2260 availBottom - mStableFullscreenBottom);
2261 } else {
2262 contentInset.set(mStableLeft, mStableTop,
2263 availRight - mStableRight, availBottom - mStableBottom);
2264 }
2265 } else if ((fl & FLAG_FULLSCREEN) != 0) {
2266 contentInset.setEmpty();
2267 } else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002268 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
2269 contentInset.set(mCurLeft, mCurTop,
2270 availRight - mCurRight, availBottom - mCurBottom);
2271 } else {
2272 contentInset.set(mCurLeft, mCurTop,
2273 availRight - mCurRight, availBottom - mCurBottom);
2274 }
2275 return;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002276 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002277 contentInset.setEmpty();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002278 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002279
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002280 /** {@inheritDoc} */
Craig Mautner69b08182012-09-05 13:07:13 -07002281 @Override
2282 public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
2283 int displayRotation) {
Joe Onorato29fc2c92010-11-24 10:26:50 -08002284 mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
2285 mUnrestrictedScreenWidth = displayWidth;
2286 mUnrestrictedScreenHeight = displayHeight;
2287 mRestrictedScreenLeft = mRestrictedScreenTop = 0;
2288 mRestrictedScreenWidth = displayWidth;
2289 mRestrictedScreenHeight = displayHeight;
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002290 mDockLeft = mContentLeft = mStableLeft = mStableFullscreenLeft
2291 = mSystemLeft = mCurLeft = 0;
2292 mDockTop = mContentTop = mStableTop = mStableFullscreenTop
2293 = mSystemTop = mCurTop = 0;
2294 mDockRight = mContentRight = mStableRight = mStableFullscreenRight
2295 = mSystemRight = mCurRight = displayWidth;
2296 mDockBottom = mContentBottom = mStableBottom = mStableFullscreenBottom
2297 = mSystemBottom = mCurBottom = displayHeight;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002298 mDockLayer = 0x10000000;
Dianne Hackborn5c58de32012-04-28 19:52:37 -07002299 mStatusBarLayer = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002300
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002301 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
2302 final Rect pf = mTmpParentFrame;
2303 final Rect df = mTmpDisplayFrame;
2304 final Rect vf = mTmpVisibleFrame;
2305 pf.left = df.left = vf.left = mDockLeft;
2306 pf.top = df.top = vf.top = mDockTop;
2307 pf.right = df.right = vf.right = mDockRight;
2308 pf.bottom = df.bottom = vf.bottom = mDockBottom;
2309
Craig Mautner69b08182012-09-05 13:07:13 -07002310 if (isDefaultDisplay) {
2311 // For purposes of putting out fake window up to steal focus, we will
2312 // drive nav being hidden only by whether it is requested.
2313 boolean navVisible = (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002314
Craig Mautner69b08182012-09-05 13:07:13 -07002315 // When the navigation bar isn't visible, we put up a fake
2316 // input window to catch all touch events. This way we can
2317 // detect when the user presses anywhere to bring back the nav
2318 // bar and ensure the application doesn't see the event.
2319 if (navVisible) {
2320 if (mHideNavFakeWindow != null) {
2321 mHideNavFakeWindow.dismiss();
2322 mHideNavFakeWindow = null;
2323 }
2324 } else if (mHideNavFakeWindow == null) {
2325 mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
2326 mHandler.getLooper(), mHideNavInputEventReceiverFactory,
2327 "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
2328 0, false, false, true);
Dianne Hackborne26ab702011-10-16 13:21:33 -07002329 }
Dianne Hackborne26ab702011-10-16 13:21:33 -07002330
Craig Mautner69b08182012-09-05 13:07:13 -07002331 // For purposes of positioning and showing the nav bar, if we have
2332 // decided that it can't be hidden (because of the screen aspect ratio),
2333 // then take that into account.
2334 navVisible |= !mCanHideNavigationBar;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002335
Craig Mautner69b08182012-09-05 13:07:13 -07002336 if (mNavigationBar != null) {
2337 // Force the navigation bar to its appropriate place and
2338 // size. We need to do this directly, instead of relying on
2339 // it to bubble up from the nav bar, because this needs to
2340 // change atomically with screen rotations.
2341 mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
2342 if (mNavigationBarOnBottom) {
2343 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
2344 int top = displayHeight - mNavigationBarHeightForRotation[displayRotation];
2345 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
2346 mStableBottom = mStableFullscreenBottom = mTmpNavigationFrame.top;
2347 if (navVisible) {
2348 mNavigationBar.showLw(true);
2349 mDockBottom = mTmpNavigationFrame.top;
2350 mRestrictedScreenHeight = mDockBottom - mDockTop;
2351 } else {
2352 // We currently want to hide the navigation UI.
2353 mNavigationBar.hideLw(true);
2354 }
2355 if (navVisible && !mNavigationBar.isAnimatingLw()) {
2356 // If the nav bar is currently requested to be visible,
2357 // and not in the process of animating on or off, then
2358 // we can tell the app that it is covered by it.
2359 mSystemBottom = mTmpNavigationFrame.top;
2360 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002361 } else {
Craig Mautner69b08182012-09-05 13:07:13 -07002362 // Landscape screen; nav bar goes to the right.
2363 int left = displayWidth - mNavigationBarWidthForRotation[displayRotation];
2364 mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight);
2365 mStableRight = mStableFullscreenRight = mTmpNavigationFrame.left;
2366 if (navVisible) {
2367 mNavigationBar.showLw(true);
2368 mDockRight = mTmpNavigationFrame.left;
2369 mRestrictedScreenWidth = mDockRight - mDockLeft;
2370 } else {
2371 // We currently want to hide the navigation UI.
2372 mNavigationBar.hideLw(true);
2373 }
2374 if (navVisible && !mNavigationBar.isAnimatingLw()) {
2375 // If the nav bar is currently requested to be visible,
2376 // and not in the process of animating on or off, then
2377 // we can tell the app that it is covered by it.
2378 mSystemRight = mTmpNavigationFrame.left;
2379 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002380 }
Craig Mautner69b08182012-09-05 13:07:13 -07002381 // Make sure the content and current rectangles are updated to
2382 // account for the restrictions from the navigation bar.
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002383 mContentTop = mCurTop = mDockTop;
2384 mContentBottom = mCurBottom = mDockBottom;
2385 mContentLeft = mCurLeft = mDockLeft;
2386 mContentRight = mCurRight = mDockRight;
Craig Mautner69b08182012-09-05 13:07:13 -07002387 mStatusBarLayer = mNavigationBar.getSurfaceLayer();
2388 // And compute the final frame.
2389 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
2390 mTmpNavigationFrame, mTmpNavigationFrame);
2391 if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002392 }
Craig Mautner69b08182012-09-05 13:07:13 -07002393 if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
2394 mDockLeft, mDockTop, mDockRight, mDockBottom));
2395
2396 // decide where the status bar goes ahead of time
2397 if (mStatusBar != null) {
2398 // apply any navigation bar insets
2399 pf.left = df.left = mUnrestrictedScreenLeft;
2400 pf.top = df.top = mUnrestrictedScreenTop;
2401 pf.right = df.right = mUnrestrictedScreenWidth - mUnrestrictedScreenLeft;
2402 pf.bottom = df.bottom = mUnrestrictedScreenHeight - mUnrestrictedScreenTop;
2403 vf.left = mStableLeft;
2404 vf.top = mStableTop;
2405 vf.right = mStableRight;
2406 vf.bottom = mStableBottom;
2407
2408 mStatusBarLayer = mStatusBar.getSurfaceLayer();
2409
2410 // Let the status bar determine its size.
2411 mStatusBar.computeFrameLw(pf, df, vf, vf);
2412
2413 // For layout, the status bar is always at the top with our fixed height.
2414 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
2415
2416 // If the status bar is hidden, we don't want to cause
2417 // windows behind it to scroll.
2418 if (mStatusBar.isVisibleLw()) {
2419 // Status bar may go away, so the screen area it occupies
2420 // is available to apps but just covering them when the
2421 // status bar is visible.
2422 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
2423
2424 mContentTop = mCurTop = mDockTop;
2425 mContentBottom = mCurBottom = mDockBottom;
2426 mContentLeft = mCurLeft = mDockLeft;
2427 mContentRight = mCurRight = mDockRight;
2428
2429 if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
2430 String.format(
2431 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
2432 mDockLeft, mDockTop, mDockRight, mDockBottom,
2433 mContentLeft, mContentTop, mContentRight, mContentBottom,
2434 mCurLeft, mCurTop, mCurRight, mCurBottom));
2435 }
2436 if (mStatusBar.isVisibleLw() && !mStatusBar.isAnimatingLw()) {
2437 // If the status bar is currently requested to be visible,
2438 // and not in the process of animating on or off, then
2439 // we can tell the app that it is covered by it.
2440 mSystemTop = mUnrestrictedScreenTop + mStatusBarHeight;
2441 }
Dianne Hackborn5c58de32012-04-28 19:52:37 -07002442 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002443 }
2444 }
2445
Dianne Hackborn85afd1b2012-05-13 13:31:06 -07002446 /** {@inheritDoc} */
2447 public int getSystemDecorRectLw(Rect systemRect) {
2448 systemRect.left = mSystemLeft;
2449 systemRect.top = mSystemTop;
2450 systemRect.right = mSystemRight;
2451 systemRect.bottom = mSystemBottom;
2452 if (mStatusBar != null) return mStatusBar.getSurfaceLayer();
2453 if (mNavigationBar != null) return mNavigationBar.getSurfaceLayer();
2454 return 0;
2455 }
2456
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002457 void setAttachedWindowFrames(WindowState win, int fl, int adjust,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002458 WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
2459 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
2460 // Here's a special case: if this attached window is a panel that is
2461 // above the dock window, and the window it is attached to is below
2462 // the dock window, then the frames we computed for the window it is
2463 // attached to can not be used because the dock is effectively part
2464 // of the underlying window and the attached window is floating on top
2465 // of the whole thing. So, we ignore the attached window and explicitly
2466 // compute the frames that would be appropriate without the dock.
2467 df.left = cf.left = vf.left = mDockLeft;
2468 df.top = cf.top = vf.top = mDockTop;
2469 df.right = cf.right = vf.right = mDockRight;
2470 df.bottom = cf.bottom = vf.bottom = mDockBottom;
2471 } else {
2472 // The effective display frame of the attached window depends on
2473 // whether it is taking care of insetting its content. If not,
2474 // we need to use the parent's content frame so that the entire
2475 // window is positioned within that content. Otherwise we can use
2476 // the display frame and let the attached window take care of
2477 // positioning its content appropriately.
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002478 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002479 cf.set(attached.getDisplayFrameLw());
2480 } else {
2481 // If the window is resizing, then we want to base the content
2482 // frame on our attached content frame to resize... however,
2483 // things can be tricky if the attached window is NOT in resize
2484 // mode, in which case its content frame will be larger.
2485 // Ungh. So to deal with that, make sure the content frame
2486 // we end up using is not covering the IM dock.
2487 cf.set(attached.getContentFrameLw());
2488 if (attached.getSurfaceLayer() < mDockLayer) {
2489 if (cf.left < mContentLeft) cf.left = mContentLeft;
2490 if (cf.top < mContentTop) cf.top = mContentTop;
2491 if (cf.right > mContentRight) cf.right = mContentRight;
2492 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
2493 }
2494 }
2495 df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
2496 vf.set(attached.getVisibleFrameLw());
2497 }
2498 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
2499 // window should be positioned relative to its parent or the entire
2500 // screen.
2501 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
2502 ? attached.getFrameLw() : df);
2503 }
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002504
2505 private void applyStableConstraints(int sysui, int fl, Rect r) {
2506 if ((sysui & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2507 // If app is requesting a stable layout, don't let the
2508 // content insets go below the stable values.
2509 if ((fl & FLAG_FULLSCREEN) != 0) {
2510 if (r.left < mStableFullscreenLeft) r.left = mStableFullscreenLeft;
2511 if (r.top < mStableFullscreenTop) r.top = mStableFullscreenTop;
2512 if (r.right > mStableFullscreenRight) r.right = mStableFullscreenRight;
2513 if (r.bottom > mStableFullscreenBottom) r.bottom = mStableFullscreenBottom;
2514 } else {
2515 if (r.left < mStableLeft) r.left = mStableLeft;
2516 if (r.top < mStableTop) r.top = mStableTop;
2517 if (r.right > mStableRight) r.right = mStableRight;
2518 if (r.bottom > mStableBottom) r.bottom = mStableBottom;
2519 }
2520 }
2521 }
2522
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002523 /** {@inheritDoc} */
Craig Mautner69b08182012-09-05 13:07:13 -07002524 @Override
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07002525 public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
2526 WindowState attached) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002527 // we've already done the status bar
Dianne Hackborn1f903c32011-09-13 19:18:06 -07002528 if (win == mStatusBar || win == mNavigationBar) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002529 return;
2530 }
Craig Mautner69b08182012-09-05 13:07:13 -07002531 final boolean isDefaultDisplay = win.isDefaultDisplay();
2532 final boolean needsToOffsetInputMethodTarget = isDefaultDisplay &&
satok1bc0a492012-04-25 22:47:12 +09002533 (win == mLastInputMethodTargetWindow && mLastInputMethodWindow != null);
2534 if (needsToOffsetInputMethodTarget) {
2535 if (DEBUG_LAYOUT) {
2536 Slog.i(TAG, "Offset ime target window by the last ime window state");
2537 }
2538 offsetInputMethodWindowLw(mLastInputMethodWindow);
2539 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002540
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002541 final int fl = attrs.flags;
2542 final int sim = attrs.softInputMode;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002543 final int sysUiFl = win.getSystemUiVisibility();
2544
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002545 final Rect pf = mTmpParentFrame;
2546 final Rect df = mTmpDisplayFrame;
2547 final Rect cf = mTmpContentFrame;
2548 final Rect vf = mTmpVisibleFrame;
Craig Mautner69b08182012-09-05 13:07:13 -07002549
2550 final boolean hasNavBar = (isDefaultDisplay && mHasNavigationBar
Daniel Sandler36412a72011-08-04 09:35:13 -04002551 && mNavigationBar != null && mNavigationBar.isVisibleLw());
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002552
Craig Mautner69b08182012-09-05 13:07:13 -07002553 if (!isDefaultDisplay) {
2554 if (attached != null) {
2555 // If this window is attached to another, our display
2556 // frame is the same as the one we are attached to.
2557 setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
2558 } else {
2559 // Give the window full screen.
2560 pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
2561 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
2562 pf.right = df.right = cf.right
2563 = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
2564 pf.bottom = df.bottom = cf.bottom
2565 = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
2566 }
2567 } else if (attrs.type == TYPE_INPUT_METHOD) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002568 pf.left = df.left = cf.left = vf.left = mDockLeft;
2569 pf.top = df.top = cf.top = vf.top = mDockTop;
2570 pf.right = df.right = cf.right = vf.right = mDockRight;
2571 pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
2572 // IM dock windows always go to the bottom of the screen.
2573 attrs.gravity = Gravity.BOTTOM;
2574 mDockLayer = win.getSurfaceLayer();
2575 } else {
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002576 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
2577
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07002578 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002579 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)
2580 && (sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002581 if (DEBUG_LAYOUT)
2582 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2583 + "): IN_SCREEN, INSET_DECOR, !FULLSCREEN");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002584 // This is the case for a normal activity window: we want it
2585 // to cover all of the screen space, and it can take care of
2586 // moving its contents to account for screen decorations that
2587 // intrude into that space.
2588 if (attached != null) {
2589 // If this window is attached to another, our display
2590 // frame is the same as the one we are attached to.
2591 setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
2592 } else {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002593 if (attrs.type == TYPE_STATUS_BAR_PANEL
2594 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
Joe Onorato29fc2c92010-11-24 10:26:50 -08002595 // Status bar panels are the only windows who can go on top of
2596 // the status bar. They are protected by the STATUS_BAR_SERVICE
2597 // permission, so they have the same privileges as the status
2598 // bar itself.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002599 //
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002600 // However, they should still dodge the navigation bar if it exists.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002601
2602 pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002603 pf.top = df.top = mUnrestrictedScreenTop;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002604 pf.right = df.right = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002605 ? mRestrictedScreenLeft+mRestrictedScreenWidth
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002606 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2607 pf.bottom = df.bottom = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002608 ? mRestrictedScreenTop+mRestrictedScreenHeight
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002609 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
2610
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002611 if (DEBUG_LAYOUT) {
2612 Log.v(TAG, String.format(
2613 "Laying out status bar window: (%d,%d - %d,%d)",
2614 pf.left, pf.top, pf.right, pf.bottom));
2615 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002616 } else if (mCanHideNavigationBar
2617 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002618 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
2619 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
2620 // Asking for layout as if the nav bar is hidden, lets the
2621 // application extend into the unrestricted screen area. We
2622 // only do this for application windows to ensure no window that
2623 // can be above the nav bar can do this.
2624 pf.left = df.left = mUnrestrictedScreenLeft;
2625 pf.top = df.top = mUnrestrictedScreenTop;
2626 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2627 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002628 } else {
2629 pf.left = df.left = mRestrictedScreenLeft;
2630 pf.top = df.top = mRestrictedScreenTop;
2631 pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2632 pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
2633 }
Craig Mautner69b08182012-09-05 13:07:13 -07002634
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002635 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002636 cf.left = mDockLeft;
2637 cf.top = mDockTop;
2638 cf.right = mDockRight;
2639 cf.bottom = mDockBottom;
2640 } else {
2641 cf.left = mContentLeft;
2642 cf.top = mContentTop;
2643 cf.right = mContentRight;
2644 cf.bottom = mContentBottom;
2645 }
Craig Mautner69b08182012-09-05 13:07:13 -07002646
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002647 applyStableConstraints(sysUiFl, fl, cf);
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002648 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2649 vf.left = mCurLeft;
2650 vf.top = mCurTop;
2651 vf.right = mCurRight;
2652 vf.bottom = mCurBottom;
2653 } else {
2654 vf.set(cf);
2655 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002656 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002657 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
2658 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
2659 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002660 if (DEBUG_LAYOUT)
2661 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002662 // A window that has requested to fill the entire screen just
2663 // gets everything, period.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002664 if (attrs.type == TYPE_STATUS_BAR_PANEL
2665 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
2666 pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002667 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002668 pf.right = df.right = cf.right = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002669 ? mRestrictedScreenLeft+mRestrictedScreenWidth
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002670 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2671 pf.bottom = df.bottom = cf.bottom = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002672 ? mRestrictedScreenTop+mRestrictedScreenHeight
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002673 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Daniel Sandler36412a72011-08-04 09:35:13 -04002674 if (DEBUG_LAYOUT) {
2675 Log.v(TAG, String.format(
2676 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
2677 pf.left, pf.top, pf.right, pf.bottom));
2678 }
Jim Millere898ac52012-04-06 17:10:57 -07002679 } else if (attrs.type == TYPE_NAVIGATION_BAR
2680 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002681 // The navigation bar has Real Ultimate Power.
2682 pf.left = df.left = mUnrestrictedScreenLeft;
2683 pf.top = df.top = mUnrestrictedScreenTop;
2684 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2685 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
2686 if (DEBUG_LAYOUT) {
2687 Log.v(TAG, String.format(
2688 "Laying out navigation bar window: (%d,%d - %d,%d)",
2689 pf.left, pf.top, pf.right, pf.bottom));
2690 }
Dianne Hackborn01011c32012-02-21 13:54:21 -08002691 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
2692 || attrs.type == TYPE_BOOT_PROGRESS)
Jeff Brownbfcb60a2011-09-08 18:51:14 -07002693 && ((fl & FLAG_FULLSCREEN) != 0)) {
2694 // Fullscreen secure system overlays get what they ask for.
2695 pf.left = df.left = mUnrestrictedScreenLeft;
2696 pf.top = df.top = mUnrestrictedScreenTop;
2697 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2698 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Dianne Hackborna4b7f2f2012-05-21 11:28:41 -07002699 } else if (attrs.type == TYPE_BOOT_PROGRESS
2700 || attrs.type == TYPE_UNIVERSE_BACKGROUND) {
Dianne Hackborn01011c32012-02-21 13:54:21 -08002701 // Boot progress screen always covers entire display.
2702 pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
2703 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
2704 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2705 pf.bottom = df.bottom = cf.bottom
2706 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002707 } else if (mCanHideNavigationBar
2708 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002709 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
2710 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
2711 // Asking for layout as if the nav bar is hidden, lets the
2712 // application extend into the unrestricted screen area. We
2713 // only do this for application windows to ensure no window that
2714 // can be above the nav bar can do this.
2715 // XXX This assumes that an app asking for this will also
2716 // ask for layout in only content. We can't currently figure out
2717 // what the screen would be if only laying out to hide the nav bar.
2718 pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
2719 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
2720 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2721 pf.bottom = df.bottom = cf.bottom
2722 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002723 } else {
2724 pf.left = df.left = cf.left = mRestrictedScreenLeft;
2725 pf.top = df.top = cf.top = mRestrictedScreenTop;
2726 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2727 pf.bottom = df.bottom = cf.bottom
2728 = mRestrictedScreenTop+mRestrictedScreenHeight;
2729 }
Craig Mautner69b08182012-09-05 13:07:13 -07002730
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002731 applyStableConstraints(sysUiFl, fl, cf);
Craig Mautner69b08182012-09-05 13:07:13 -07002732
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002733 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2734 vf.left = mCurLeft;
2735 vf.top = mCurTop;
2736 vf.right = mCurRight;
2737 vf.bottom = mCurBottom;
2738 } else {
2739 vf.set(cf);
2740 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002741 } else if (attached != null) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002742 if (DEBUG_LAYOUT)
2743 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): attached to " + attached);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002744 // A child window should be placed inside of the same visible
2745 // frame that its parent had.
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002746 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002747 } else {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002748 if (DEBUG_LAYOUT)
2749 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002750 // Otherwise, a normal window must be placed inside the content
2751 // of all screen decorations.
Dianne Hackborna239c842011-06-01 12:28:20 -07002752 if (attrs.type == TYPE_STATUS_BAR_PANEL) {
2753 // Status bar panels are the only windows who can go on top of
2754 // the status bar. They are protected by the STATUS_BAR_SERVICE
2755 // permission, so they have the same privileges as the status
2756 // bar itself.
Dianne Hackborn7d049322011-06-14 15:00:32 -07002757 pf.left = df.left = cf.left = mRestrictedScreenLeft;
2758 pf.top = df.top = cf.top = mRestrictedScreenTop;
2759 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2760 pf.bottom = df.bottom = cf.bottom
2761 = mRestrictedScreenTop+mRestrictedScreenHeight;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002762 } else {
Dianne Hackborna239c842011-06-01 12:28:20 -07002763 pf.left = mContentLeft;
2764 pf.top = mContentTop;
2765 pf.right = mContentRight;
2766 pf.bottom = mContentBottom;
2767 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
2768 df.left = cf.left = mDockLeft;
2769 df.top = cf.top = mDockTop;
2770 df.right = cf.right = mDockRight;
2771 df.bottom = cf.bottom = mDockBottom;
2772 } else {
2773 df.left = cf.left = mContentLeft;
2774 df.top = cf.top = mContentTop;
2775 df.right = cf.right = mContentRight;
2776 df.bottom = cf.bottom = mContentBottom;
2777 }
2778 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2779 vf.left = mCurLeft;
2780 vf.top = mCurTop;
2781 vf.right = mCurRight;
2782 vf.bottom = mCurBottom;
2783 } else {
2784 vf.set(cf);
2785 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002786 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002787 }
2788 }
Craig Mautner69b08182012-09-05 13:07:13 -07002789
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002790 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
2791 df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
2792 df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
2793 }
2794
The Android Open Source Project11267662009-03-18 17:39:47 -07002795 if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
2796 + ": sim=#" + Integer.toHexString(sim)
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002797 + " attach=" + attached + " type=" + attrs.type
2798 + String.format(" flags=0x%08x", fl)
The Android Open Source Project11267662009-03-18 17:39:47 -07002799 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
2800 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
Craig Mautner69b08182012-09-05 13:07:13 -07002801
Dianne Hackborn85afd1b2012-05-13 13:31:06 -07002802 win.computeFrameLw(pf, df, cf, vf);
Craig Mautner69b08182012-09-05 13:07:13 -07002803
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002804 // Dock windows carve out the bottom of the screen, so normal windows
2805 // can't appear underneath them.
2806 if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
satok1bc0a492012-04-25 22:47:12 +09002807 setLastInputMethodWindowLw(null, null);
2808 offsetInputMethodWindowLw(win);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002809 }
2810 }
2811
satok1bc0a492012-04-25 22:47:12 +09002812 private void offsetInputMethodWindowLw(WindowState win) {
2813 int top = win.getContentFrameLw().top;
2814 top += win.getGivenContentInsetsLw().top;
2815 if (mContentBottom > top) {
2816 mContentBottom = top;
2817 }
2818 top = win.getVisibleFrameLw().top;
2819 top += win.getGivenVisibleInsetsLw().top;
2820 if (mCurBottom > top) {
2821 mCurBottom = top;
2822 }
2823 if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom="
2824 + mDockBottom + " mContentBottom="
2825 + mContentBottom + " mCurBottom=" + mCurBottom);
2826 }
2827
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002828 /** {@inheritDoc} */
Craig Mautner61ac6bb2012-02-02 17:29:33 -08002829 @Override
2830 public void finishLayoutLw() {
2831 return;
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002832 }
2833
2834 /** {@inheritDoc} */
Craig Mautner39834192012-09-02 07:47:24 -07002835 public void beginPostLayoutPolicyLw(int displayWidth, int displayHeight) {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002836 mTopFullscreenOpaqueWindowState = null;
2837 mForceStatusBar = false;
2838
2839 mHideLockScreen = false;
2840 mAllowLockscreenWhenOn = false;
2841 mDismissKeyguard = false;
2842 }
2843
2844 /** {@inheritDoc} */
Craig Mautner39834192012-09-02 07:47:24 -07002845 public void applyPostLayoutPolicyLw(WindowState win,
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002846 WindowManager.LayoutParams attrs) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002847 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
2848 + win.isVisibleOrBehindKeyguardLw());
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002849 if (mTopFullscreenOpaqueWindowState == null &&
Dianne Hackborn01b02a72012-01-12 14:05:03 -08002850 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002851 if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
2852 mForceStatusBar = true;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002853 }
Daniel Sandlerf7178d32012-08-10 10:24:05 -04002854 if (((attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type <= LAST_APPLICATION_WINDOW)
2855 || attrs.type == TYPE_DREAM)
Dianne Hackborn6493e642010-10-01 13:06:30 -07002856 && attrs.x == 0 && attrs.y == 0
2857 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
2858 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002859 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win);
2860 mTopFullscreenOpaqueWindowState = win;
2861 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2862 if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
2863 mHideLockScreen = true;
2864 }
2865 if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2866 if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win);
2867 mDismissKeyguard = true;
2868 }
2869 if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
2870 mAllowLockscreenWhenOn = true;
2871 }
2872 }
2873 }
2874 }
2875
2876 /** {@inheritDoc} */
Craig Mautner39834192012-09-02 07:47:24 -07002877 public int finishPostLayoutPolicyLw() {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002878 int changes = 0;
Joe Onorato93056472010-09-10 10:30:46 -04002879 boolean topIsFullscreen = false;
Daniel Sandlere02d8082010-10-08 15:13:22 -04002880
2881 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
2882 ? mTopFullscreenOpaqueWindowState.getAttrs()
2883 : null;
2884
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002885 if (mStatusBar != null) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002886 if (DEBUG_LAYOUT) Log.i(TAG, "force=" + mForceStatusBar
Dianne Hackbornd70bc2f2009-10-06 23:25:51 -07002887 + " top=" + mTopFullscreenOpaqueWindowState);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002888 if (mForceStatusBar) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002889 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: forced");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002890 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002891 } else if (mTopFullscreenOpaqueWindowState != null) {
Joe Onorato93056472010-09-10 10:30:46 -04002892 if (localLOGV) {
2893 Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
2894 + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
2895 Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
2896 + " lp.flags=0x" + Integer.toHexString(lp.flags));
2897 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002898 topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
2899 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
Joe Onorato93056472010-09-10 10:30:46 -04002900 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
2901 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
2902 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
2903 // case though.
2904 if (topIsFullscreen) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002905 if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar");
2906 if (mStatusBar.hideLw(true)) {
2907 changes |= FINISH_LAYOUT_REDO_LAYOUT;
Daniel Sandler9c00d5b2011-09-13 14:04:26 -04002908
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002909 mHandler.post(new Runnable() { public void run() {
Dianne Hackborn42e620c2012-06-24 13:20:51 -07002910 try {
2911 IStatusBarService statusbar = getStatusBarService();
2912 if (statusbar != null) {
2913 statusbar.collapse();
2914 }
2915 } catch (RemoteException ex) {
2916 // re-acquire status bar service next time it is needed.
2917 mStatusBarService = null;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002918 }
2919 }});
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002920 } else if (DEBUG_LAYOUT) {
Daniel Sandler40427442010-07-16 11:44:52 -04002921 Log.v(TAG, "Preventing status bar from hiding by policy");
2922 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002923 } else {
Dianne Hackborn01b02a72012-01-12 14:05:03 -08002924 if (DEBUG_LAYOUT) Log.v(TAG, "** SHOWING status bar: top is not fullscreen");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002925 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002926 }
2927 }
2928 }
Daniel Sandlere02d8082010-10-08 15:13:22 -04002929
Joe Onorato644f9c32011-01-25 12:06:23 -08002930 mTopIsFullscreen = topIsFullscreen;
Daniel Sandlere02d8082010-10-08 15:13:22 -04002931
Craig Mautner39834192012-09-02 07:47:24 -07002932 // Hide the key guard if a visible window explicitly specifies that it wants to be
2933 // displayed when the screen is locked.
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002934 if (mKeyguard != null) {
Craig Mautner39834192012-09-02 07:47:24 -07002935 if (localLOGV) Log.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
2936 + mHideLockScreen);
Dianne Hackborn05726582009-09-22 17:28:24 -07002937 if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
Dianne Hackborn08743722009-12-21 12:16:51 -08002938 if (mKeyguard.hideLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002939 changes |= FINISH_LAYOUT_REDO_LAYOUT
2940 | FINISH_LAYOUT_REDO_CONFIG
2941 | FINISH_LAYOUT_REDO_WALLPAPER;
2942 }
Dianne Hackborn05726582009-09-22 17:28:24 -07002943 if (mKeyguardMediator.isShowing()) {
Dianne Hackbornb446e972009-09-20 15:23:25 -07002944 mHandler.post(new Runnable() {
2945 public void run() {
Dianne Hackborn05726582009-09-22 17:28:24 -07002946 mKeyguardMediator.keyguardDone(false, false);
Dianne Hackbornb446e972009-09-20 15:23:25 -07002947 }
2948 });
2949 }
Dianne Hackborn05726582009-09-22 17:28:24 -07002950 } else if (mHideLockScreen) {
Dianne Hackborn08743722009-12-21 12:16:51 -08002951 if (mKeyguard.hideLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002952 changes |= FINISH_LAYOUT_REDO_LAYOUT
2953 | FINISH_LAYOUT_REDO_CONFIG
2954 | FINISH_LAYOUT_REDO_WALLPAPER;
2955 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05002956 mKeyguardMediator.setHidden(true);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002957 } else {
Dianne Hackborn08743722009-12-21 12:16:51 -08002958 if (mKeyguard.showLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002959 changes |= FINISH_LAYOUT_REDO_LAYOUT
2960 | FINISH_LAYOUT_REDO_CONFIG
2961 | FINISH_LAYOUT_REDO_WALLPAPER;
2962 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05002963 mKeyguardMediator.setHidden(false);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002964 }
2965 }
Joe Onorato664644d2011-01-23 17:53:23 -08002966
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002967 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002968 // If the navigation bar has been hidden or shown, we need to do another
2969 // layout pass to update that window.
2970 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2971 }
Joe Onorato664644d2011-01-23 17:53:23 -08002972
Mike Lockwood28569302010-01-28 11:54:40 -05002973 // update since mAllowLockscreenWhenOn might have changed
2974 updateLockScreenTimeout();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002975 return changes;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002976 }
2977
Dianne Hackborn08743722009-12-21 12:16:51 -08002978 public boolean allowAppAnimationsLw() {
Craig Mautnerf03e4c52012-06-14 14:11:27 -07002979 if (mKeyguard != null && mKeyguard.isVisibleLw() && !mKeyguard.isAnimatingLw()) {
Dianne Hackborn08743722009-12-21 12:16:51 -08002980 // If keyguard is currently visible, no reason to animate
2981 // behind it.
2982 return false;
2983 }
Dianne Hackborn08743722009-12-21 12:16:51 -08002984 return true;
2985 }
2986
Dianne Hackborndf89e652011-10-06 22:35:11 -07002987 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
Joe Onorato664644d2011-01-23 17:53:23 -08002988 mFocusedWindow = newFocus;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002989 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002990 // If the navigation bar has been hidden or shown, we need to do another
2991 // layout pass to update that window.
2992 return FINISH_LAYOUT_REDO_LAYOUT;
2993 }
2994 return 0;
Joe Onorato664644d2011-01-23 17:53:23 -08002995 }
2996
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07002997 /** {@inheritDoc} */
Jeff Brown46b9ac02010-04-22 18:58:52 -07002998 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002999 // do nothing if headless
Mike Lockwoodd747dc82011-09-13 16:28:22 -04003000 if (mHeadless) return;
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003001
Jeff Brown46b9ac02010-04-22 18:58:52 -07003002 // lid changed state
Jeff Brownc458ce92012-04-30 14:58:40 -07003003 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
3004 if (newLidState == mLidState) {
3005 return;
3006 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003007
Jeff Brownc458ce92012-04-30 14:58:40 -07003008 mLidState = newLidState;
3009 applyLidSwitchState();
Jeff Brown01a98dd2011-09-20 15:08:29 -07003010 updateRotation(true);
Jeff Brownc458ce92012-04-30 14:58:40 -07003011
3012 if (lidOpen) {
3013 if (keyguardIsShowingTq()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07003014 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
Jeff Brown43150bf2011-11-08 20:22:03 -08003015 KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
Jeff Brown46b9ac02010-04-22 18:58:52 -07003016 } else {
Jeff Brown96307042012-07-27 15:51:34 -07003017 mPowerManager.wakeUp(SystemClock.uptimeMillis());
Jeff Brown46b9ac02010-04-22 18:58:52 -07003018 }
Jeff Brownc458ce92012-04-30 14:58:40 -07003019 } else if (!mLidControlsSleep) {
Jeff Brown96307042012-07-27 15:51:34 -07003020 mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
Jeff Brown46b9ac02010-04-22 18:58:52 -07003021 }
3022 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003023
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08003024 void setHdmiPlugged(boolean plugged) {
3025 if (mHdmiPlugged != plugged) {
3026 mHdmiPlugged = plugged;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07003027 updateRotation(true, true);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08003028 Intent intent = new Intent(ACTION_HDMI_PLUGGED);
Joe Onoratodc100302011-01-11 17:07:41 -08003029 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08003030 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07003031 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08003032 }
3033 }
3034
Joe Onoratoea495d42011-04-06 11:41:11 -07003035 void initializeHdmiState() {
Joe Onorato7ba631f2011-05-04 15:28:00 -07003036 boolean plugged = false;
Joe Onoratoea495d42011-04-06 11:41:11 -07003037 // watch for HDMI plug messages if the hdmi switch exists
3038 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
3039 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
3040
Joe Onoratoea495d42011-04-06 11:41:11 -07003041 final String filename = "/sys/class/switch/hdmi/state";
3042 FileReader reader = null;
3043 try {
3044 reader = new FileReader(filename);
3045 char[] buf = new char[15];
3046 int n = reader.read(buf);
3047 if (n > 1) {
3048 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
3049 }
3050 } catch (IOException ex) {
3051 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
3052 } catch (NumberFormatException ex) {
3053 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
3054 } finally {
3055 if (reader != null) {
3056 try {
3057 reader.close();
3058 } catch (IOException ex) {
3059 }
Joe Onoratodc100302011-01-11 17:07:41 -08003060 }
3061 }
3062 }
Joe Onorato7ba631f2011-05-04 15:28:00 -07003063 // This dance forces the code in setHdmiPlugged to run.
3064 // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
3065 mHdmiPlugged = !plugged;
3066 setHdmiPlugged(!mHdmiPlugged);
Joe Onoratodc100302011-01-11 17:07:41 -08003067 }
3068
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003069 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003070 * @return Whether music is being played right now.
3071 */
3072 boolean isMusicActive() {
Eric Laurent413cb9d2009-07-17 11:52:43 -07003073 final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
3074 if (am == null) {
3075 Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003076 return false;
3077 }
Eric Laurent413cb9d2009-07-17 11:52:43 -07003078 return am.isMusicActive();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003079 }
3080
3081 /**
3082 * Tell the audio service to adjust the volume appropriate to the event.
3083 * @param keycode
3084 */
Mike Lockwooda53e3812009-09-25 10:51:39 -04003085 void handleVolumeKey(int stream, int keycode) {
Jeff Brown4d396052010-10-29 21:50:21 -07003086 IAudioService audioService = getAudioService();
3087 if (audioService == null) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003088 return;
3089 }
3090 try {
3091 // since audio is playing, we shouldn't have to hold a wake lock
3092 // during the call, but we do it as a precaution for the rare possibility
3093 // that the music stops right before we call this
Jeff Brownb0418da2010-11-01 15:24:01 -07003094 // TODO: Actually handle MUTE.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003095 mBroadcastWakeLock.acquire();
Jeff Brown4d396052010-10-29 21:50:21 -07003096 audioService.adjustStreamVolume(stream,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003097 keycode == KeyEvent.KEYCODE_VOLUME_UP
3098 ? AudioManager.ADJUST_RAISE
3099 : AudioManager.ADJUST_LOWER,
3100 0);
3101 } catch (RemoteException e) {
3102 Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e);
3103 } finally {
3104 mBroadcastWakeLock.release();
3105 }
3106 }
Jeff Brown4d396052010-10-29 21:50:21 -07003107
Dianne Hackbornc0e3f242011-08-19 14:19:10 -07003108 final Object mScreenshotLock = new Object();
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07003109 ServiceConnection mScreenshotConnection = null;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07003110
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003111 final Runnable mScreenshotTimeout = new Runnable() {
3112 @Override public void run() {
3113 synchronized (mScreenshotLock) {
3114 if (mScreenshotConnection != null) {
3115 mContext.unbindService(mScreenshotConnection);
3116 mScreenshotConnection = null;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07003117 }
Winson Chung9112ec32011-06-27 13:15:32 -07003118 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003119 }
3120 };
3121
3122 // Assume this is called from the Handler thread.
3123 private void takeScreenshot() {
3124 synchronized (mScreenshotLock) {
3125 if (mScreenshotConnection != null) {
3126 return;
3127 }
3128 ComponentName cn = new ComponentName("com.android.systemui",
3129 "com.android.systemui.screenshot.TakeScreenshotService");
3130 Intent intent = new Intent();
3131 intent.setComponent(cn);
3132 ServiceConnection conn = new ServiceConnection() {
3133 @Override
3134 public void onServiceConnected(ComponentName name, IBinder service) {
3135 synchronized (mScreenshotLock) {
3136 if (mScreenshotConnection != this) {
3137 return;
3138 }
3139 Messenger messenger = new Messenger(service);
3140 Message msg = Message.obtain(null, 1);
3141 final ServiceConnection myConn = this;
3142 Handler h = new Handler(mHandler.getLooper()) {
3143 @Override
3144 public void handleMessage(Message msg) {
3145 synchronized (mScreenshotLock) {
3146 if (mScreenshotConnection == myConn) {
3147 mContext.unbindService(mScreenshotConnection);
3148 mScreenshotConnection = null;
3149 mHandler.removeCallbacks(mScreenshotTimeout);
3150 }
3151 }
3152 }
3153 };
3154 msg.replyTo = new Messenger(h);
Winson Chunga63bb842011-10-17 10:26:28 -07003155 msg.arg1 = msg.arg2 = 0;
3156 if (mStatusBar != null && mStatusBar.isVisibleLw())
3157 msg.arg1 = 1;
3158 if (mNavigationBar != null && mNavigationBar.isVisibleLw())
3159 msg.arg2 = 1;
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003160 try {
3161 messenger.send(msg);
3162 } catch (RemoteException e) {
3163 }
3164 }
3165 }
3166 @Override
3167 public void onServiceDisconnected(ComponentName name) {}
3168 };
Jeff Sharkey35744c12012-08-28 16:48:05 -07003169 if (mContext.bindService(
3170 intent, conn, Context.BIND_AUTO_CREATE, UserHandle.USER_CURRENT)) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003171 mScreenshotConnection = conn;
3172 mHandler.postDelayed(mScreenshotTimeout, 10000);
3173 }
3174 }
Winson Chung9112ec32011-06-27 13:15:32 -07003175 }
3176
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003177 /** {@inheritDoc} */
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003178 @Override
Jeff Brown1f245102010-11-18 20:53:46 -08003179 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
Jeff Brown96307042012-07-27 15:51:34 -07003180 if (!mSystemBooted) {
3181 // If we have not yet booted, don't let key events do anything.
3182 return 0;
3183 }
3184
Jeff Brown1f245102010-11-18 20:53:46 -08003185 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3186 final boolean canceled = event.isCanceled();
3187 final int keyCode = event.getKeyCode();
Jeff Browne20c9e02010-10-11 14:20:19 -07003188
Jeff Brown3122e442010-10-11 23:32:49 -07003189 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
Jeff Brown3122e442010-10-11 23:32:49 -07003190
Mike Lockwoodc72b15f2009-11-28 20:58:22 -05003191 // If screen is off then we treat the case where the keyguard is open but hidden
3192 // the same as if it were open and in front.
3193 // This will prevent any keys other than the power button from waking the screen
3194 // when the keyguard is hidden by another activity.
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003195 final boolean keyguardActive = (mKeyguardMediator == null ? false :
3196 (isScreenOn ?
3197 mKeyguardMediator.isShowingAndNotHidden() :
3198 mKeyguardMediator.isShowing()));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003199
Jeff Brown96307042012-07-27 15:51:34 -07003200 if (keyCode == KeyEvent.KEYCODE_POWER) {
3201 policyFlags |= WindowManagerPolicy.FLAG_WAKE;
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07003202 }
Jeff Brown96307042012-07-27 15:51:34 -07003203 final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
3204 | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07003205
Jeff Brown40013652012-05-16 21:22:36 -07003206 if (DEBUG_INPUT) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003207 Log.d(TAG, "interceptKeyTq keycode=" + keyCode
Jeff Brown96307042012-07-27 15:51:34 -07003208 + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive
3209 + " policyFlags=" + Integer.toHexString(policyFlags)
3210 + " isWakeKey=" + isWakeKey);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003211 }
3212
Jeff Brown98392ef2011-09-12 18:24:59 -07003213 if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
3214 && event.getRepeatCount() == 0) {
Jeff Brown4d396052010-10-29 21:50:21 -07003215 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
3216 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003217
Jeff Brown4d396052010-10-29 21:50:21 -07003218 // Basic policy based on screen state and keyguard.
3219 // FIXME: This policy isn't quite correct. We shouldn't care whether the screen
3220 // is on or off, really. We should care about whether the device is in an
3221 // interactive state or is in suspend pretending to be "off".
3222 // The primary screen might be turned off due to proximity sensor or
3223 // because we are presenting media on an auxiliary screen or remotely controlling
3224 // the device some other way (which is why we have an exemption here for injected
3225 // events).
3226 int result;
Mike Lockwoodd747dc82011-09-13 16:28:22 -04003227 if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) {
Jeff Brown4d396052010-10-29 21:50:21 -07003228 // When the screen is on or if the key is injected pass the key to the application.
3229 result = ACTION_PASS_TO_USER;
3230 } else {
3231 // When the screen is off and the key is not injected, determine whether
3232 // to wake the device but don't pass the key to the application.
3233 result = 0;
Jeff Brown4d396052010-10-29 21:50:21 -07003234 if (down && isWakeKey) {
3235 if (keyguardActive) {
3236 // If the keyguard is showing, let it decide what to do with the wake key.
Jeff Brown43150bf2011-11-08 20:22:03 -08003237 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode,
3238 mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
Jeff Brown4d396052010-10-29 21:50:21 -07003239 } else {
3240 // Otherwise, wake the device ourselves.
Jeff Brown96307042012-07-27 15:51:34 -07003241 result |= ACTION_WAKE_UP;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003242 }
3243 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003244 }
3245
Jeff Brown4d396052010-10-29 21:50:21 -07003246 // Handle special keys.
3247 switch (keyCode) {
3248 case KeyEvent.KEYCODE_VOLUME_DOWN:
Jeff Brownb0418da2010-11-01 15:24:01 -07003249 case KeyEvent.KEYCODE_VOLUME_UP:
3250 case KeyEvent.KEYCODE_VOLUME_MUTE: {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003251 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
3252 if (down) {
3253 if (isScreenOn && !mVolumeDownKeyTriggered
3254 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3255 mVolumeDownKeyTriggered = true;
3256 mVolumeDownKeyTime = event.getDownTime();
3257 mVolumeDownKeyConsumedByScreenshotChord = false;
3258 cancelPendingPowerKeyAction();
3259 interceptScreenshotChord();
3260 }
3261 } else {
3262 mVolumeDownKeyTriggered = false;
3263 cancelPendingScreenshotChordAction();
3264 }
3265 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
3266 if (down) {
3267 if (isScreenOn && !mVolumeUpKeyTriggered
3268 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3269 mVolumeUpKeyTriggered = true;
3270 cancelPendingPowerKeyAction();
3271 cancelPendingScreenshotChordAction();
3272 }
3273 } else {
3274 mVolumeUpKeyTriggered = false;
3275 cancelPendingScreenshotChordAction();
3276 }
3277 }
Jeff Brown4d396052010-10-29 21:50:21 -07003278 if (down) {
3279 ITelephony telephonyService = getTelephonyService();
3280 if (telephonyService != null) {
3281 try {
3282 if (telephonyService.isRinging()) {
3283 // If an incoming call is ringing, either VOLUME key means
3284 // "silence ringer". We handle these keys here, rather than
3285 // in the InCallScreen, to make sure we'll respond to them
3286 // even if the InCallScreen hasn't come to the foreground yet.
3287 // Look for the DOWN event here, to agree with the "fallback"
3288 // behavior in the InCallScreen.
3289 Log.i(TAG, "interceptKeyBeforeQueueing:"
3290 + " VOLUME key-down while ringing: Silence ringer!");
3291
3292 // Silence the ringer. (It's safe to call this
3293 // even if the ringer has already been silenced.)
3294 telephonyService.silenceRinger();
3295
3296 // And *don't* pass this key thru to the current activity
3297 // (which is probably the InCallScreen.)
3298 result &= ~ACTION_PASS_TO_USER;
3299 break;
3300 }
3301 if (telephonyService.isOffhook()
3302 && (result & ACTION_PASS_TO_USER) == 0) {
3303 // If we are in call but we decided not to pass the key to
3304 // the application, handle the volume change here.
3305 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
3306 break;
3307 }
3308 } catch (RemoteException ex) {
3309 Log.w(TAG, "ITelephony threw RemoteException", ex);
3310 }
3311 }
3312
3313 if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) {
3314 // If music is playing but we decided not to pass the key to the
3315 // application, handle the volume change here.
3316 handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
3317 break;
3318 }
3319 }
3320 break;
3321 }
3322
3323 case KeyEvent.KEYCODE_ENDCALL: {
3324 result &= ~ACTION_PASS_TO_USER;
3325 if (down) {
3326 ITelephony telephonyService = getTelephonyService();
3327 boolean hungUp = false;
3328 if (telephonyService != null) {
3329 try {
3330 hungUp = telephonyService.endCall();
3331 } catch (RemoteException ex) {
3332 Log.w(TAG, "ITelephony threw RemoteException", ex);
3333 }
3334 }
3335 interceptPowerKeyDown(!isScreenOn || hungUp);
3336 } else {
3337 if (interceptPowerKeyUp(canceled)) {
3338 if ((mEndcallBehavior
3339 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
3340 if (goHome()) {
3341 break;
Dianne Hackborn0041e972009-07-24 17:14:43 -07003342 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003343 }
Jeff Brown4d396052010-10-29 21:50:21 -07003344 if ((mEndcallBehavior
3345 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
Jeff Brown96307042012-07-27 15:51:34 -07003346 result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
Jeff Brown4d396052010-10-29 21:50:21 -07003347 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003348 }
Jeff Brown4d396052010-10-29 21:50:21 -07003349 }
3350 break;
3351 }
3352
3353 case KeyEvent.KEYCODE_POWER: {
3354 result &= ~ACTION_PASS_TO_USER;
3355 if (down) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003356 if (isScreenOn && !mPowerKeyTriggered
3357 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3358 mPowerKeyTriggered = true;
3359 mPowerKeyTime = event.getDownTime();
3360 interceptScreenshotChord();
Winson Chung9112ec32011-06-27 13:15:32 -07003361 }
Winson Chung9112ec32011-06-27 13:15:32 -07003362
Jeff Brown4d396052010-10-29 21:50:21 -07003363 ITelephony telephonyService = getTelephonyService();
3364 boolean hungUp = false;
3365 if (telephonyService != null) {
3366 try {
3367 if (telephonyService.isRinging()) {
3368 // Pressing Power while there's a ringing incoming
3369 // call should silence the ringer.
3370 telephonyService.silenceRinger();
3371 } else if ((mIncallPowerBehavior
3372 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
3373 && telephonyService.isOffhook()) {
3374 // Otherwise, if "Power button ends call" is enabled,
3375 // the Power button will hang up any current active call.
3376 hungUp = telephonyService.endCall();
3377 }
3378 } catch (RemoteException ex) {
3379 Log.w(TAG, "ITelephony threw RemoteException", ex);
3380 }
3381 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003382 interceptPowerKeyDown(!isScreenOn || hungUp
3383 || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003384 } else {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003385 mPowerKeyTriggered = false;
3386 cancelPendingScreenshotChordAction();
3387 if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
Jeff Brown96307042012-07-27 15:51:34 -07003388 result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003389 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003390 mPendingPowerKeyUpCanceled = false;
Jeff Brown4d396052010-10-29 21:50:21 -07003391 }
3392 break;
3393 }
3394
3395 case KeyEvent.KEYCODE_MEDIA_PLAY:
3396 case KeyEvent.KEYCODE_MEDIA_PAUSE:
3397 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
3398 if (down) {
3399 ITelephony telephonyService = getTelephonyService();
3400 if (telephonyService != null) {
3401 try {
3402 if (!telephonyService.isIdle()) {
3403 // Suppress PLAY/PAUSE toggle when phone is ringing or in-call
3404 // to avoid music playback.
3405 break;
3406 }
3407 } catch (RemoteException ex) {
3408 Log.w(TAG, "ITelephony threw RemoteException", ex);
Jeff Brown3122e442010-10-11 23:32:49 -07003409 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003410 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003411 }
Jeff Brown4d396052010-10-29 21:50:21 -07003412 case KeyEvent.KEYCODE_HEADSETHOOK:
3413 case KeyEvent.KEYCODE_MUTE:
3414 case KeyEvent.KEYCODE_MEDIA_STOP:
3415 case KeyEvent.KEYCODE_MEDIA_NEXT:
3416 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
3417 case KeyEvent.KEYCODE_MEDIA_REWIND:
3418 case KeyEvent.KEYCODE_MEDIA_RECORD:
3419 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
3420 if ((result & ACTION_PASS_TO_USER) == 0) {
3421 // Only do this if we would otherwise not pass it to the user. In that
3422 // case, the PhoneWindow class will do the same thing, except it will
3423 // only do it if the showing app doesn't process the key on its own.
Jeff Brown40013652012-05-16 21:22:36 -07003424 // Note that we need to make a copy of the key event here because the
3425 // original key event will be recycled when we return.
Jeff Brown4d396052010-10-29 21:50:21 -07003426 mBroadcastWakeLock.acquire();
Jeff Brown40013652012-05-16 21:22:36 -07003427 Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
3428 new KeyEvent(event));
3429 msg.setAsynchronous(true);
3430 msg.sendToTarget();
Jeff Brown4d396052010-10-29 21:50:21 -07003431 }
3432 break;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003433 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003434
Jeff Brown4d396052010-10-29 21:50:21 -07003435 case KeyEvent.KEYCODE_CALL: {
3436 if (down) {
3437 ITelephony telephonyService = getTelephonyService();
3438 if (telephonyService != null) {
3439 try {
3440 if (telephonyService.isRinging()) {
3441 Log.i(TAG, "interceptKeyBeforeQueueing:"
3442 + " CALL key-down while ringing: Answer the call!");
3443 telephonyService.answerRingingCall();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003444
Jeff Brown4d396052010-10-29 21:50:21 -07003445 // And *don't* pass this key thru to the current activity
3446 // (which is presumably the InCallScreen.)
3447 result &= ~ACTION_PASS_TO_USER;
3448 }
3449 } catch (RemoteException ex) {
3450 Log.w(TAG, "ITelephony threw RemoteException", ex);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003451 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003452 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003453 }
Jeff Brown4d396052010-10-29 21:50:21 -07003454 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003455 }
3456 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003457 return result;
3458 }
3459
Jeff Brown56194eb2011-03-02 19:23:13 -08003460 /** {@inheritDoc} */
3461 @Override
3462 public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
3463 int result = 0;
3464
3465 final boolean isWakeMotion = (policyFlags
3466 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
3467 if (isWakeMotion) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003468 if (mKeyguardMediator != null && mKeyguardMediator.isShowing()) {
Jeff Brown56194eb2011-03-02 19:23:13 -08003469 // If the keyguard is showing, let it decide what to do with the wake motion.
3470 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
3471 } else {
3472 // Otherwise, wake the device ourselves.
Jeff Brown96307042012-07-27 15:51:34 -07003473 result |= ACTION_WAKE_UP;
Jeff Brown56194eb2011-03-02 19:23:13 -08003474 }
3475 }
3476 return result;
3477 }
3478
Jeff Brown40013652012-05-16 21:22:36 -07003479 void dispatchMediaKeyWithWakeLock(KeyEvent event) {
3480 if (DEBUG_INPUT) {
3481 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: " + event);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003482 }
3483
Jeff Brown40013652012-05-16 21:22:36 -07003484 if (mHavePendingMediaKeyRepeatWithWakeLock) {
3485 if (DEBUG_INPUT) {
3486 Slog.d(TAG, "dispatchMediaKeyWithWakeLock: canceled repeat");
3487 }
3488
3489 mHandler.removeMessages(MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK);
3490 mHavePendingMediaKeyRepeatWithWakeLock = false;
3491 mBroadcastWakeLock.release(); // pending repeat was holding onto the wake lock
3492 }
3493
3494 dispatchMediaKeyWithWakeLockToAudioService(event);
3495
3496 if (event.getAction() == KeyEvent.ACTION_DOWN
3497 && event.getRepeatCount() == 0) {
3498 mHavePendingMediaKeyRepeatWithWakeLock = true;
3499
3500 Message msg = mHandler.obtainMessage(
3501 MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK, event);
3502 msg.setAsynchronous(true);
3503 mHandler.sendMessageDelayed(msg, ViewConfiguration.getKeyRepeatTimeout());
3504 } else {
3505 mBroadcastWakeLock.release();
3506 }
3507 }
3508
3509 void dispatchMediaKeyRepeatWithWakeLock(KeyEvent event) {
3510 mHavePendingMediaKeyRepeatWithWakeLock = false;
3511
3512 KeyEvent repeatEvent = KeyEvent.changeTimeRepeat(event,
3513 SystemClock.uptimeMillis(), 1, event.getFlags() | KeyEvent.FLAG_LONG_PRESS);
3514 if (DEBUG_INPUT) {
3515 Slog.d(TAG, "dispatchMediaKeyRepeatWithWakeLock: " + repeatEvent);
3516 }
3517
3518 dispatchMediaKeyWithWakeLockToAudioService(repeatEvent);
3519 mBroadcastWakeLock.release();
3520 }
3521
3522 void dispatchMediaKeyWithWakeLockToAudioService(KeyEvent event) {
3523 if (ActivityManagerNative.isSystemReady()) {
3524 IAudioService audioService = getAudioService();
3525 if (audioService != null) {
3526 try {
3527 audioService.dispatchMediaKeyEventUnderWakelock(event);
3528 } catch (RemoteException e) {
3529 Log.e(TAG, "dispatchMediaKeyEvent threw exception " + e);
Jean-Michel Trivic6802222012-04-30 11:15:03 -07003530 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003531 }
3532 }
3533 }
3534
Mike Lockwood1753f7f2009-08-24 14:49:07 -07003535 BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
3536 public void onReceive(Context context, Intent intent) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07003537 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
3538 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
3539 Intent.EXTRA_DOCK_STATE_UNDOCKED);
3540 } else {
3541 try {
3542 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
3543 ServiceManager.getService(Context.UI_MODE_SERVICE));
3544 mUiMode = uiModeService.getCurrentModeType();
3545 } catch (RemoteException e) {
3546 }
Dianne Hackborn80fa1662009-10-07 14:02:10 -07003547 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003548 updateRotation(true);
Mike Lockwoode9867d22009-09-20 01:59:02 -04003549 updateOrientationListenerLp();
Mike Lockwood1753f7f2009-08-24 14:49:07 -07003550 }
3551 };
3552
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003553 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003554 public void screenTurnedOff(int why) {
Dianne Hackborn74489012009-03-24 20:50:09 -07003555 EventLog.writeEvent(70000, 0);
The Android Open Source Project0727d222009-03-11 12:11:58 -07003556 synchronized (mLock) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003557 mScreenOnEarly = false;
3558 mScreenOnFully = false;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003559 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003560 if (mKeyguardMediator != null) {
3561 mKeyguardMediator.onScreenTurnedOff(why);
3562 }
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003563 synchronized (mLock) {
The Android Open Source Project0727d222009-03-11 12:11:58 -07003564 updateOrientationListenerLp();
Mike Lockwood28569302010-01-28 11:54:40 -05003565 updateLockScreenTimeout();
The Android Open Source Project0727d222009-03-11 12:11:58 -07003566 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003567 }
3568
3569 /** {@inheritDoc} */
Dianne Hackborn38e29a62011-09-18 14:43:08 -07003570 public void screenTurningOn(final ScreenOnListener screenOnListener) {
Dianne Hackborn74489012009-03-24 20:50:09 -07003571 EventLog.writeEvent(70000, 1);
Dianne Hackborn40011092011-09-22 13:37:48 -07003572 if (false) {
3573 RuntimeException here = new RuntimeException("here");
3574 here.fillInStackTrace();
3575 Slog.i(TAG, "Screen turning on...", here);
3576 }
3577 if (screenOnListener != null) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003578 if (mKeyguardMediator != null) {
Craig Mautner3d7b7d52012-05-24 11:28:26 -07003579 try {
3580 mWindowManager.setEventDispatching(true);
3581 } catch (RemoteException unhandled) {
3582 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003583 mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
3584 @Override public void onShown(IBinder windowToken) {
3585 if (windowToken != null) {
3586 try {
3587 mWindowManager.waitForWindowDrawn(windowToken,
3588 new IRemoteCallback.Stub() {
3589 @Override public void sendResult(Bundle data) {
3590 Slog.i(TAG, "Lock screen displayed!");
3591 screenOnListener.onScreenOn();
3592 synchronized (mLock) {
3593 mScreenOnFully = true;
3594 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003595 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003596 });
3597 } catch (RemoteException e) {
3598 }
3599 } else {
3600 Slog.i(TAG, "No lock screen!");
3601 screenOnListener.onScreenOn();
3602 synchronized (mLock) {
3603 mScreenOnFully = true;
3604 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003605 }
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003606 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003607 });
3608 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003609 } else {
Craig Mautner4f5d1512012-06-21 13:03:41 -07003610 if (mKeyguardMediator != null) {
3611 // Must set mScreenOn = true.
3612 mKeyguardMediator.onScreenTurnedOn(null);
3613 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003614 synchronized (mLock) {
3615 mScreenOnFully = true;
Dianne Hackborn38e29a62011-09-18 14:43:08 -07003616 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003617 }
The Android Open Source Project0727d222009-03-11 12:11:58 -07003618 synchronized (mLock) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003619 mScreenOnEarly = true;
The Android Open Source Project0727d222009-03-11 12:11:58 -07003620 updateOrientationListenerLp();
Mike Lockwood28569302010-01-28 11:54:40 -05003621 updateLockScreenTimeout();
The Android Open Source Project0727d222009-03-11 12:11:58 -07003622 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003623 }
3624
3625 /** {@inheritDoc} */
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003626 public boolean isScreenOnEarly() {
3627 return mScreenOnEarly;
3628 }
3629
3630 /** {@inheritDoc} */
3631 public boolean isScreenOnFully() {
3632 return mScreenOnFully;
Dianne Hackborn08743722009-12-21 12:16:51 -08003633 }
3634
3635 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003636 public void enableKeyguard(boolean enabled) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003637 if (mKeyguardMediator != null) {
3638 mKeyguardMediator.setKeyguardEnabled(enabled);
3639 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003640 }
3641
3642 /** {@inheritDoc} */
3643 public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003644 if (mKeyguardMediator != null) {
3645 mKeyguardMediator.verifyUnlock(callback);
3646 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003647 }
3648
Mike Lockwoodf7913302009-11-28 22:27:10 -05003649 private boolean keyguardIsShowingTq() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003650 if (mKeyguardMediator == null) return false;
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08003651 return mKeyguardMediator.isShowingAndNotHidden();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003652 }
3653
Mike Lockwood520d8bc2011-02-18 13:23:13 -05003654
3655 /** {@inheritDoc} */
3656 public boolean isKeyguardLocked() {
3657 return keyguardOn();
3658 }
3659
3660 /** {@inheritDoc} */
3661 public boolean isKeyguardSecure() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003662 if (mKeyguardMediator == null) return false;
Mike Lockwood520d8bc2011-02-18 13:23:13 -05003663 return mKeyguardMediator.isSecure();
3664 }
3665
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003666 /** {@inheritDoc} */
3667 public boolean inKeyguardRestrictedKeyInputMode() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003668 if (mKeyguardMediator == null) return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003669 return mKeyguardMediator.isInputRestricted();
3670 }
3671
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003672 public void dismissKeyguardLw() {
3673 if (!mKeyguardMediator.isSecure()) {
3674 if (mKeyguardMediator.isShowing()) {
3675 mHandler.post(new Runnable() {
3676 public void run() {
3677 mKeyguardMediator.keyguardDone(false, true);
3678 }
3679 });
3680 }
3681 }
3682 }
3683
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003684 void sendCloseSystemWindows() {
3685 sendCloseSystemWindows(mContext, null);
3686 }
3687
3688 void sendCloseSystemWindows(String reason) {
3689 sendCloseSystemWindows(mContext, reason);
3690 }
3691
3692 static void sendCloseSystemWindows(Context context, String reason) {
3693 if (ActivityManagerNative.isSystemReady()) {
Dianne Hackborn94a679d2009-07-28 17:51:07 -07003694 try {
3695 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
3696 } catch (RemoteException e) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003697 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003698 }
3699 }
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07003700
Jeff Brown01a98dd2011-09-20 15:08:29 -07003701 @Override
3702 public int rotationForOrientationLw(int orientation, int lastRotation) {
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003703 if (false) {
3704 Slog.v(TAG, "rotationForOrientationLw(orient="
3705 + orientation + ", last=" + lastRotation
3706 + "); user=" + mUserRotation + " "
3707 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
3708 ? "USER_ROTATION_LOCKED" : "")
3709 );
3710 }
3711
The Android Open Source Project0727d222009-03-11 12:11:58 -07003712 synchronized (mLock) {
Jeff Brownc0347aa2011-09-23 17:26:09 -07003713 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
3714 if (sensorRotation < 0) {
Craig Mautner4bd149e2012-08-03 13:54:02 -07003715 // Sensor is disabled, device probably just turned off.
3716 if (mLastSensorRotation >= 0) {
3717 sensorRotation = mLastSensorRotation;
3718 } else {
3719 // Sensor has never been enabled. Last resort is to use lastRotation.
3720 sensorRotation = lastRotation;
3721 }
3722 } else {
3723 // Valid sensor data, save it away.
3724 mLastSensorRotation = sensorRotation;
Jeff Brownc0347aa2011-09-23 17:26:09 -07003725 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003726
Jeff Browndec6cf42011-11-15 14:08:20 -08003727 final int preferredRotation;
Jeff Brown2e7760e2012-04-11 15:14:55 -07003728 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003729 // Ignore sensor when lid switch is open and rotation is forced.
3730 preferredRotation = mLidOpenRotation;
3731 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
Jeff Brownc0347aa2011-09-23 17:26:09 -07003732 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003733 // Ignore sensor when in car dock unless explicitly enabled.
3734 // This case can override the behavior of NOSENSOR, and can also
3735 // enable 180 degree rotation while docked.
Jeff Brownc0347aa2011-09-23 17:26:09 -07003736 preferredRotation = mCarDockEnablesAccelerometer
Jeff Brown01a98dd2011-09-20 15:08:29 -07003737 ? sensorRotation : mCarDockRotation;
Jeff Brown1a693182011-11-08 14:44:16 -08003738 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
3739 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
3740 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
Jeff Brownc0347aa2011-09-23 17:26:09 -07003741 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003742 // Ignore sensor when in desk dock unless explicitly enabled.
3743 // This case can override the behavior of NOSENSOR, and can also
3744 // enable 180 degree rotation while docked.
Jeff Brownc0347aa2011-09-23 17:26:09 -07003745 preferredRotation = mDeskDockEnablesAccelerometer
Jeff Brown01a98dd2011-09-20 15:08:29 -07003746 ? sensorRotation : mDeskDockRotation;
Jeff Browneb3e4b92011-12-06 19:54:24 -08003747 } else if (mHdmiPlugged) {
3748 // Ignore sensor when plugged into HDMI.
3749 // Note that the dock orientation overrides the HDMI orientation.
3750 preferredRotation = mHdmiRotation;
Jeff Brown207673cd2012-06-05 17:47:11 -07003751 } else if ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
Jeff Brown01a98dd2011-09-20 15:08:29 -07003752 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
3753 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED))
3754 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
3755 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
3756 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
3757 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
3758 // Otherwise, use sensor only if requested by the application or enabled
3759 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR.
Jeff Brownd3187e32011-09-21 19:26:44 -07003760 if (mAllowAllRotations < 0) {
3761 // Can't read this during init() because the context doesn't
3762 // have display metrics at that time so we cannot determine
3763 // tablet vs. phone then.
3764 mAllowAllRotations = mContext.getResources().getBoolean(
3765 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
3766 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003767 if (sensorRotation != Surface.ROTATION_180
Jeff Brownd3187e32011-09-21 19:26:44 -07003768 || mAllowAllRotations == 1
Jeff Brown01a98dd2011-09-20 15:08:29 -07003769 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) {
3770 preferredRotation = sensorRotation;
3771 } else {
3772 preferredRotation = lastRotation;
3773 }
Jeff Brown207673cd2012-06-05 17:47:11 -07003774 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED
3775 && orientation != ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
3776 // Apply rotation lock. Does not apply to NOSENSOR.
3777 // The idea is that the user rotation expresses a weak preference for the direction
3778 // of gravity and as NOSENSOR is never affected by gravity, then neither should
3779 // NOSENSOR be affected by rotation lock (although it will be affected by docks).
Jeff Brown4dfce202011-10-05 12:00:10 -07003780 preferredRotation = mUserRotation;
Jeff Browndec6cf42011-11-15 14:08:20 -08003781 } else {
3782 // No overriding preference.
3783 // We will do exactly what the application asked us to do.
3784 preferredRotation = -1;
Jeff Brown01a98dd2011-09-20 15:08:29 -07003785 }
3786
Dianne Hackborne5439f22010-10-02 16:53:50 -07003787 switch (orientation) {
3788 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
Jeff Browndec6cf42011-11-15 14:08:20 -08003789 // Return portrait unless overridden.
3790 if (isAnyPortrait(preferredRotation)) {
3791 return preferredRotation;
3792 }
Dianne Hackborne5439f22010-10-02 16:53:50 -07003793 return mPortraitRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003794
Jeff Brown01a98dd2011-09-20 15:08:29 -07003795 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
Jeff Browndec6cf42011-11-15 14:08:20 -08003796 // Return landscape unless overridden.
3797 if (isLandscapeOrSeascape(preferredRotation)) {
3798 return preferredRotation;
3799 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003800 return mLandscapeRotation;
3801
3802 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
Jeff Browndec6cf42011-11-15 14:08:20 -08003803 // Return reverse portrait unless overridden.
3804 if (isAnyPortrait(preferredRotation)) {
3805 return preferredRotation;
3806 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003807 return mUpsideDownRotation;
3808
3809 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
Jeff Browndec6cf42011-11-15 14:08:20 -08003810 // Return seascape unless overridden.
3811 if (isLandscapeOrSeascape(preferredRotation)) {
3812 return preferredRotation;
3813 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003814 return mSeascapeRotation;
3815
3816 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
3817 // Return either landscape rotation.
3818 if (isLandscapeOrSeascape(preferredRotation)) {
3819 return preferredRotation;
3820 }
3821 if (isLandscapeOrSeascape(lastRotation)) {
Jeff Brown4519f072011-01-23 13:16:01 -08003822 return lastRotation;
3823 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003824 return mLandscapeRotation;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003825
Jeff Brown01a98dd2011-09-20 15:08:29 -07003826 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
3827 // Return either portrait rotation.
3828 if (isAnyPortrait(preferredRotation)) {
3829 return preferredRotation;
3830 }
3831 if (isAnyPortrait(lastRotation)) {
3832 return lastRotation;
3833 }
3834 return mPortraitRotation;
3835
3836 default:
Jeff Brown4dfce202011-10-05 12:00:10 -07003837 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
3838 // just return the preferred orientation we already calculated.
Jeff Brown01a98dd2011-09-20 15:08:29 -07003839 if (preferredRotation >= 0) {
3840 return preferredRotation;
3841 }
Dianne Hackborndacea8c2011-04-21 17:26:39 -07003842 return Surface.ROTATION_0;
Daniel Sandlere7e5ac22011-02-22 16:10:21 -05003843 }
3844 }
Steve Howarda7bfe6a2010-09-23 16:47:49 -07003845 }
3846
Jeff Brown01a98dd2011-09-20 15:08:29 -07003847 @Override
3848 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
3849 switch (orientation) {
3850 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
3851 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
3852 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
3853 return isAnyPortrait(rotation);
3854
3855 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
3856 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
3857 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
3858 return isLandscapeOrSeascape(rotation);
3859
3860 default:
3861 return true;
3862 }
Steve Howarda7bfe6a2010-09-23 16:47:49 -07003863 }
3864
Jeff Brownc0347aa2011-09-23 17:26:09 -07003865 @Override
3866 public void setRotationLw(int rotation) {
3867 mOrientationListener.setCurrentRotation(rotation);
3868 }
3869
Jeff Brown01a98dd2011-09-20 15:08:29 -07003870 private boolean isLandscapeOrSeascape(int rotation) {
3871 return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003872 }
3873
Jeff Brown01a98dd2011-09-20 15:08:29 -07003874 private boolean isAnyPortrait(int rotation) {
3875 return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003876 }
3877
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003878
3879 // User rotation: to be used when all else fails in assigning an orientation to the device
3880 public void setUserRotationMode(int mode, int rot) {
3881 ContentResolver res = mContext.getContentResolver();
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003882
3883 // mUserRotationMode and mUserRotation will be assigned by the content observer
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003884 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003885 Settings.System.putInt(res,
3886 Settings.System.USER_ROTATION,
3887 rot);
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003888 Settings.System.putInt(res,
3889 Settings.System.ACCELEROMETER_ROTATION,
3890 0);
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003891 } else {
3892 Settings.System.putInt(res,
3893 Settings.System.ACCELEROMETER_ROTATION,
3894 1);
3895 }
3896 }
3897
Jeff Brownac143512012-04-05 18:57:33 -07003898 public void setSafeMode(boolean safeMode) {
3899 mSafeMode = safeMode;
3900 performHapticFeedbackLw(null, safeMode
3901 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
3902 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003903 }
3904
Dianne Hackborn181ceb52009-08-27 22:16:40 -07003905 static long[] getLongIntArray(Resources r, int resid) {
3906 int[] ar = r.getIntArray(resid);
3907 if (ar == null) {
3908 return null;
3909 }
3910 long[] out = new long[ar.length];
3911 for (int i=0; i<ar.length; i++) {
3912 out[i] = ar[i];
3913 }
3914 return out;
3915 }
3916
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003917 /** {@inheritDoc} */
3918 public void systemReady() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003919 if (mKeyguardMediator != null) {
3920 // tell the keyguard
3921 mKeyguardMediator.onSystemReady();
3922 }
Dianne Hackbornb1a79802009-09-29 15:18:31 -07003923 synchronized (mLock) {
3924 updateOrientationListenerLp();
Dianne Hackbornc777e072010-02-12 13:07:59 -08003925 mSystemReady = true;
3926 mHandler.post(new Runnable() {
3927 public void run() {
3928 updateSettings();
3929 }
3930 });
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003931 }
3932 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07003933
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07003934 /** {@inheritDoc} */
3935 public void systemBooted() {
3936 synchronized (mLock) {
3937 mSystemBooted = true;
3938 }
3939 }
3940
Dianne Hackborn661cd522011-08-22 00:26:20 -07003941 ProgressDialog mBootMsgDialog = null;
3942
3943 /** {@inheritDoc} */
3944 public void showBootMessage(final CharSequence msg, final boolean always) {
Mike Lockwoodaa5bf142011-09-21 13:03:40 -04003945 if (mHeadless) return;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003946 mHandler.post(new Runnable() {
3947 @Override public void run() {
3948 if (mBootMsgDialog == null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07003949 mBootMsgDialog = new ProgressDialog(mContext) {
3950 // This dialog will consume all events coming in to
3951 // it, to avoid it trying to do things too early in boot.
3952 @Override public boolean dispatchKeyEvent(KeyEvent event) {
3953 return true;
3954 }
3955 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
3956 return true;
3957 }
3958 @Override public boolean dispatchTouchEvent(MotionEvent ev) {
3959 return true;
3960 }
3961 @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
3962 return true;
3963 }
3964 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
3965 return true;
3966 }
3967 @Override public boolean dispatchPopulateAccessibilityEvent(
3968 AccessibilityEvent event) {
3969 return true;
3970 }
3971 };
Dianne Hackborn661cd522011-08-22 00:26:20 -07003972 mBootMsgDialog.setTitle(R.string.android_upgrading_title);
3973 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
3974 mBootMsgDialog.setIndeterminate(true);
3975 mBootMsgDialog.getWindow().setType(
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003976 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
Dianne Hackborn661cd522011-08-22 00:26:20 -07003977 mBootMsgDialog.getWindow().addFlags(
3978 WindowManager.LayoutParams.FLAG_DIM_BEHIND
3979 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
3980 mBootMsgDialog.getWindow().setDimAmount(1);
Dianne Hackbornd9efb952011-12-07 14:56:51 -08003981 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
3982 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
3983 mBootMsgDialog.getWindow().setAttributes(lp);
Dianne Hackborn661cd522011-08-22 00:26:20 -07003984 mBootMsgDialog.setCancelable(false);
3985 mBootMsgDialog.show();
3986 }
3987 mBootMsgDialog.setMessage(msg);
3988 }
3989 });
3990 }
3991
3992 /** {@inheritDoc} */
3993 public void hideBootMessages() {
3994 mHandler.post(new Runnable() {
3995 @Override public void run() {
3996 if (mBootMsgDialog != null) {
3997 mBootMsgDialog.dismiss();
3998 mBootMsgDialog = null;
3999 }
4000 }
4001 });
4002 }
4003
Mike Lockwood28569302010-01-28 11:54:40 -05004004 /** {@inheritDoc} */
4005 public void userActivity() {
Dianne Hackborndf89e652011-10-06 22:35:11 -07004006 // ***************************************
4007 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
4008 // ***************************************
4009 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
4010 // WITH ITS LOCKS HELD.
4011 //
4012 // This code must be VERY careful about the locks
4013 // it acquires.
4014 // In fact, the current code acquires way too many,
4015 // and probably has lurking deadlocks.
4016
Mike Lockwood28569302010-01-28 11:54:40 -05004017 synchronized (mScreenLockTimeout) {
4018 if (mLockScreenTimerActive) {
4019 // reset the timer
4020 mHandler.removeCallbacks(mScreenLockTimeout);
4021 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
4022 }
4023 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04004024 }
4025
Mike Lockwood28569302010-01-28 11:54:40 -05004026 Runnable mScreenLockTimeout = new Runnable() {
4027 public void run() {
4028 synchronized (this) {
4029 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
Mike Lockwood3a74bd32011-08-12 13:55:22 -07004030 if (mKeyguardMediator != null) {
4031 mKeyguardMediator.doKeyguardTimeout();
4032 }
Mike Lockwood28569302010-01-28 11:54:40 -05004033 mLockScreenTimerActive = false;
4034 }
4035 }
4036 };
4037
Jim Miller93c518e2012-01-17 15:55:31 -08004038 public void lockNow() {
4039 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
4040 mHandler.removeCallbacks(mScreenLockTimeout);
4041 mHandler.post(mScreenLockTimeout);
4042 }
4043
Mike Lockwood28569302010-01-28 11:54:40 -05004044 private void updateLockScreenTimeout() {
4045 synchronized (mScreenLockTimeout) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07004046 boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly &&
4047 mKeyguardMediator != null && mKeyguardMediator.isSecure());
Mike Lockwood28569302010-01-28 11:54:40 -05004048 if (mLockScreenTimerActive != enable) {
4049 if (enable) {
4050 if (localLOGV) Log.v(TAG, "setting lockscreen timer");
4051 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
4052 } else {
4053 if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
4054 mHandler.removeCallbacks(mScreenLockTimeout);
4055 }
4056 mLockScreenTimerActive = enable;
4057 }
4058 }
4059 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004060
4061 /** {@inheritDoc} */
4062 public void enableScreenAfterBoot() {
4063 readLidState();
Jeff Brownc458ce92012-04-30 14:58:40 -07004064 applyLidSwitchState();
Jeff Brown01a98dd2011-09-20 15:08:29 -07004065 updateRotation(true);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004066 }
Dianne Hackbornf54c8f92009-09-19 14:03:57 -07004067
Jeff Brownc458ce92012-04-30 14:58:40 -07004068 private void applyLidSwitchState() {
Jeff Brownc458ce92012-04-30 14:58:40 -07004069 if (mLidState == LID_CLOSED && mLidControlsSleep) {
4070 mPowerManager.goToSleep(SystemClock.uptimeMillis());
4071 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07004072 }
4073
4074 void updateRotation(boolean alwaysSendConfiguration) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004075 try {
4076 //set orientation on WindowManager
Dianne Hackbornf87d1962012-04-04 12:48:24 -07004077 mWindowManager.updateRotation(alwaysSendConfiguration, false);
4078 } catch (RemoteException e) {
4079 // Ignore
4080 }
4081 }
4082
4083 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
4084 try {
4085 //set orientation on WindowManager
4086 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004087 } catch (RemoteException e) {
4088 // Ignore
4089 }
4090 }
4091
4092 /**
Daniel Sandler11ddf532011-11-16 11:10:03 -08004093 * Return an Intent to launch the currently active dock app as home. Returns
4094 * null if the standard home should be launched, which is the case if any of the following is
4095 * true:
4096 * <ul>
4097 * <li>The device is not in either car mode or desk mode
4098 * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
4099 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
4100 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
4101 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
4102 * </ul>
Dianne Hackborn39c2d712009-09-22 11:41:31 -07004103 * @return
4104 */
4105 Intent createHomeDockIntent() {
Daniel Sandler11ddf532011-11-16 11:10:03 -08004106 Intent intent = null;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07004107
4108 // What home does is based on the mode, not the dock state. That
4109 // is, when in car mode you should be taken to car home regardless
4110 // of whether we are actually in a car dock.
Dianne Hackborn78968392010-03-04 20:47:56 -08004111 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
Daniel Sandler11ddf532011-11-16 11:10:03 -08004112 if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
4113 intent = mCarDockIntent;
4114 }
Dianne Hackborn78968392010-03-04 20:47:56 -08004115 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
Daniel Sandler11ddf532011-11-16 11:10:03 -08004116 if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
4117 intent = mDeskDockIntent;
4118 }
4119 }
4120
4121 if (intent == null) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07004122 return null;
4123 }
4124
4125 ActivityInfo ai = intent.resolveActivityInfo(
4126 mContext.getPackageManager(), PackageManager.GET_META_DATA);
4127 if (ai == null) {
4128 return null;
4129 }
4130
4131 if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
4132 intent = new Intent(intent);
4133 intent.setClassName(ai.packageName, ai.name);
4134 return intent;
4135 }
4136
4137 return null;
4138 }
4139
4140 void startDockOrHome() {
4141 Intent dock = createHomeDockIntent();
4142 if (dock != null) {
4143 try {
4144 mContext.startActivity(dock);
4145 return;
4146 } catch (ActivityNotFoundException e) {
4147 }
4148 }
4149 mContext.startActivity(mHomeIntent);
4150 }
4151
4152 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004153 * goes to the home screen
4154 * @return whether it did anything
4155 */
4156 boolean goHome() {
4157 if (false) {
4158 // This code always brings home to the front.
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07004159 try {
4160 ActivityManagerNative.getDefault().stopAppSwitches();
4161 } catch (RemoteException e) {
4162 }
Dianne Hackborn94a679d2009-07-28 17:51:07 -07004163 sendCloseSystemWindows();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07004164 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004165 } else {
4166 // This code brings home to the front or, if it is already
4167 // at the front, puts the device to sleep.
4168 try {
Wink Savilled2e6a332010-02-12 12:12:06 -08004169 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
4170 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
4171 Log.d(TAG, "UTS-TEST-MODE");
4172 } else {
4173 ActivityManagerNative.getDefault().stopAppSwitches();
4174 sendCloseSystemWindows();
4175 Intent dock = createHomeDockIntent();
4176 if (dock != null) {
4177 int result = ActivityManagerNative.getDefault()
4178 .startActivity(null, dock,
4179 dock.resolveTypeIfNeeded(mContext.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07004180 null, null, 0,
4181 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
4182 null, null, null);
4183 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
Wink Savilled2e6a332010-02-12 12:12:06 -08004184 return false;
4185 }
Dianne Hackborn39c2d712009-09-22 11:41:31 -07004186 }
4187 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004188 int result = ActivityManagerNative.getDefault()
4189 .startActivity(null, mHomeIntent,
4190 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07004191 null, null, 0,
4192 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
4193 null, null, null);
4194 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004195 return false;
4196 }
4197 } catch (RemoteException ex) {
4198 // bummer, the activity manager, which is in this process, is dead
4199 }
4200 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004201 return true;
4202 }
4203
The Android Open Source Project0727d222009-03-11 12:11:58 -07004204 public void setCurrentOrientationLw(int newOrientation) {
4205 synchronized (mLock) {
4206 if (newOrientation != mCurrentAppOrientation) {
4207 mCurrentAppOrientation = newOrientation;
4208 updateOrientationListenerLp();
4209 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004210 }
4211 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004212
The Android Open Source Project0727d222009-03-11 12:11:58 -07004213 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
Jim Miller89b17222009-10-27 14:54:09 -07004214 final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
4215 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08004216 if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004217 return false;
4218 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004219 long[] pattern = null;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004220 switch (effectId) {
4221 case HapticFeedbackConstants.LONG_PRESS:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004222 pattern = mLongPressVibePattern;
4223 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004224 case HapticFeedbackConstants.VIRTUAL_KEY:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004225 pattern = mVirtualKeyVibePattern;
4226 break;
4227 case HapticFeedbackConstants.KEYBOARD_TAP:
4228 pattern = mKeyboardTapVibePattern;
4229 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004230 case HapticFeedbackConstants.SAFE_MODE_DISABLED:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004231 pattern = mSafeModeDisabledVibePattern;
4232 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004233 case HapticFeedbackConstants.SAFE_MODE_ENABLED:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004234 pattern = mSafeModeEnabledVibePattern;
4235 break;
Amith Yamasanic33cb712010-02-10 15:21:49 -08004236 default:
4237 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004238 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004239 if (pattern.length == 1) {
4240 // One-shot vibration
4241 mVibrator.vibrate(pattern[0]);
4242 } else {
4243 // Pattern vibration
4244 mVibrator.vibrate(pattern, -1);
4245 }
4246 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004247 }
4248
Daniel Sandler0601eb72011-04-13 01:01:32 -04004249 public void screenOnStartedLw() {
Daniel Sandler0601eb72011-04-13 01:01:32 -04004250 }
4251
The Android Open Source Project0727d222009-03-11 12:11:58 -07004252 public void screenOnStoppedLw() {
Daniel Sandler0601eb72011-04-13 01:01:32 -04004253 if (mPowerManager.isScreenOn()) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07004254 if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
Daniel Sandler0601eb72011-04-13 01:01:32 -04004255 long curTime = SystemClock.uptimeMillis();
Jeff Brown96307042012-07-27 15:51:34 -07004256 mPowerManager.userActivity(curTime, false);
Daniel Sandler0601eb72011-04-13 01:01:32 -04004257 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004258 }
4259 }
Mike Lockwoodfcb39242009-10-21 23:01:07 -04004260
4261 public boolean allowKeyRepeat() {
4262 // disable key repeat when screen is off
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07004263 return mScreenOnEarly;
Mike Lockwoodfcb39242009-10-21 23:01:07 -04004264 }
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004265
Dianne Hackborndf89e652011-10-06 22:35:11 -07004266 private int updateSystemUiVisibilityLw() {
Joe Onorato664644d2011-01-23 17:53:23 -08004267 // If there is no window focused, there will be nobody to handle the events
4268 // anyway, so just hang on in whatever state we're in until things settle down.
Dianne Hackborndf89e652011-10-06 22:35:11 -07004269 if (mFocusedWindow == null) {
4270 return 0;
4271 }
4272 final int visibility = mFocusedWindow.getSystemUiVisibility()
Dianne Hackborne26ab702011-10-16 13:21:33 -07004273 & ~mResettingSystemUiFlags
4274 & ~mForceClearedSystemUiFlags;
4275 int diff = visibility ^ mLastSystemUiFlags;
Dianne Hackborn73ab6a42011-12-13 11:16:23 -08004276 final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
Dianne Hackborne0f085d2011-11-30 18:41:15 -08004277 if (diff == 0 && mLastFocusNeedsMenu == needsMenu
4278 && mFocusedApp == mFocusedWindow.getAppToken()) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07004279 return 0;
4280 }
Dianne Hackborne26ab702011-10-16 13:21:33 -07004281 mLastSystemUiFlags = visibility;
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004282 mLastFocusNeedsMenu = needsMenu;
Dianne Hackborne0f085d2011-11-30 18:41:15 -08004283 mFocusedApp = mFocusedWindow.getAppToken();
Dianne Hackborndf89e652011-10-06 22:35:11 -07004284 mHandler.post(new Runnable() {
4285 public void run() {
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004286 try {
4287 IStatusBarService statusbar = getStatusBarService();
4288 if (statusbar != null) {
4289 statusbar.setSystemUiVisibility(visibility, 0xffffffff);
4290 statusbar.topAppWindowChanged(needsMenu);
Joe Onorato664644d2011-01-23 17:53:23 -08004291 }
Dianne Hackborn42e620c2012-06-24 13:20:51 -07004292 } catch (RemoteException e) {
4293 // re-acquire status bar service next time it is needed.
4294 mStatusBarService = null;
Joe Onorato664644d2011-01-23 17:53:23 -08004295 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07004296 }
4297 });
4298 return diff;
Joe Onorato664644d2011-01-23 17:53:23 -08004299 }
4300
Daniel Sandler0c4ccff2011-10-19 16:39:14 -04004301 // Use this instead of checking config_showNavigationBar so that it can be consistently
4302 // overridden by qemu.hw.mainkeys in the emulator.
4303 public boolean hasNavigationBar() {
4304 return mHasNavigationBar;
4305 }
4306
satok1bc0a492012-04-25 22:47:12 +09004307 @Override
4308 public void setLastInputMethodWindowLw(WindowState ime, WindowState target) {
4309 mLastInputMethodWindow = ime;
4310 mLastInputMethodTargetWindow = target;
4311 }
4312
Jeff Brownd7a04de2012-06-17 14:17:52 -07004313 public void dump(String prefix, PrintWriter pw, String[] args) {
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004314 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07004315 pw.print(" mSystemReady="); pw.print(mSystemReady);
4316 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
Jeff Brown2e7760e2012-04-11 15:14:55 -07004317 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004318 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
4319 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
Dianne Hackborne26ab702011-10-16 13:21:33 -07004320 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
4321 || mForceClearedSystemUiFlags != 0) {
4322 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
4323 pw.print(Integer.toHexString(mLastSystemUiFlags));
4324 pw.print(" mResettingSystemUiFlags=0x");
4325 pw.print(Integer.toHexString(mResettingSystemUiFlags));
4326 pw.print(" mForceClearedSystemUiFlags=0x");
4327 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
Dianne Hackborndf89e652011-10-06 22:35:11 -07004328 }
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004329 if (mLastFocusNeedsMenu) {
4330 pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
4331 pw.println(mLastFocusNeedsMenu);
4332 }
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004333 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
4334 pw.print(" mDockMode="); pw.print(mDockMode);
4335 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
4336 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
4337 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
4338 pw.print(" mUserRotation="); pw.print(mUserRotation);
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05004339 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
Dianne Hackborn6e2281d2012-06-19 17:48:32 -07004340 pw.print(prefix); pw.print("mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004341 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
4342 pw.print(mCarDockEnablesAccelerometer);
4343 pw.print(" mDeskDockEnablesAccelerometer=");
4344 pw.println(mDeskDockEnablesAccelerometer);
4345 pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
4346 pw.print(mLidKeyboardAccessibility);
4347 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
Dianne Hackborn6e2281d2012-06-19 17:48:32 -07004348 pw.print(" mLidControlsSleep="); pw.println(mLidControlsSleep);
4349 pw.print(prefix); pw.print("mLongPressOnPowerBehavior=");
4350 pw.print(mLongPressOnPowerBehavior);
4351 pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07004352 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
4353 pw.print(" mScreenOnFully="); pw.print(mScreenOnFully);
Dianne Hackborn6e2281d2012-06-19 17:48:32 -07004354 pw.print(" mOrientationSensorEnabled="); pw.println(mOrientationSensorEnabled);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004355 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
4356 pw.print(","); pw.print(mUnrestrictedScreenTop);
4357 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
4358 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
4359 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
4360 pw.print(","); pw.print(mRestrictedScreenTop);
4361 pw.print(") "); pw.print(mRestrictedScreenWidth);
4362 pw.print("x"); pw.println(mRestrictedScreenHeight);
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07004363 pw.print(prefix); pw.print("mStableFullscreen=("); pw.print(mStableFullscreenLeft);
4364 pw.print(","); pw.print(mStableFullscreenTop);
4365 pw.print(")-("); pw.print(mStableFullscreenRight);
4366 pw.print(","); pw.print(mStableFullscreenBottom); pw.println(")");
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07004367 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
4368 pw.print(","); pw.print(mStableTop);
4369 pw.print(")-("); pw.print(mStableRight);
4370 pw.print(","); pw.print(mStableBottom); pw.println(")");
Dianne Hackborn5c58de32012-04-28 19:52:37 -07004371 pw.print(prefix); pw.print("mSystem=("); pw.print(mSystemLeft);
4372 pw.print(","); pw.print(mSystemTop);
4373 pw.print(")-("); pw.print(mSystemRight);
4374 pw.print(","); pw.print(mSystemBottom); pw.println(")");
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004375 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
4376 pw.print(","); pw.print(mCurTop);
4377 pw.print(")-("); pw.print(mCurRight);
4378 pw.print(","); pw.print(mCurBottom); pw.println(")");
4379 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
4380 pw.print(","); pw.print(mContentTop);
4381 pw.print(")-("); pw.print(mContentRight);
4382 pw.print(","); pw.print(mContentBottom); pw.println(")");
4383 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
4384 pw.print(","); pw.print(mDockTop);
4385 pw.print(")-("); pw.print(mDockRight);
4386 pw.print(","); pw.print(mDockBottom); pw.println(")");
Dianne Hackborn5c58de32012-04-28 19:52:37 -07004387 pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
4388 pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004389 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
4390 pw.println(mTopFullscreenOpaqueWindowState);
4391 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
4392 pw.print(" mForceStatusBar="); pw.print(mForceStatusBar);
4393 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
4394 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
4395 pw.print(" mHomePressed="); pw.println(mHomePressed);
4396 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
4397 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
4398 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
4399 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
4400 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
4401 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
4402 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
4403 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
4404 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
4405 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
4406 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004407}