blob: 709e8479ae9afa252f16aaec02bedf5eb0186ac3 [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
18import android.app.Activity;
Dianne Hackborna4972e92012-03-14 10:38:05 -070019import android.app.ActivityManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080020import android.app.ActivityManagerNative;
Dianne Hackborn78968392010-03-04 20:47:56 -080021import android.app.IUiModeManager;
Dianne Hackborn661cd522011-08-22 00:26:20 -070022import android.app.ProgressDialog;
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;
37import android.database.ContentObserver;
Dianne Hackbornc777e072010-02-12 13:07:59 -080038import android.graphics.PixelFormat;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080039import android.graphics.Rect;
Dianne Hackbornd040edb2011-08-31 12:47:58 -070040import android.graphics.RectF;
Michael Jurka7a348952012-02-27 13:07:58 -080041import android.media.AudioManager;
42import android.media.IAudioService;
Daniel Sandler7e37df52011-11-16 22:08:23 -080043import android.os.BatteryManager;
Dianne Hackborn38e29a62011-09-18 14:43:08 -070044import android.os.Bundle;
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;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080048import android.os.LocalPowerManager;
Jeff Brown32cbc38552011-12-01 14:01:49 -080049import android.os.Looper;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -070050import android.os.Message;
51import android.os.Messenger;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080052import android.os.PowerManager;
53import android.os.RemoteException;
54import android.os.ServiceManager;
55import android.os.SystemClock;
56import android.os.SystemProperties;
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -080057import android.os.UEventObserver;
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;
Joe Onoratod208e702010-10-08 16:22:43 -040062import com.android.internal.app.ShutdownThread;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080063import com.android.internal.policy.PolicyManager;
Joe Onorato0cbda992010-05-02 16:28:15 -070064import com.android.internal.statusbar.IStatusBarService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080065import com.android.internal.telephony.ITelephony;
Dianne Hackborn6019c9d2010-03-01 21:43:11 -080066import com.android.internal.widget.PointerLocationView;
67
Daniel Sandler7d276c32012-01-30 14:33:52 -050068import android.service.dreams.IDreamManager;
Michael Jurka7a348952012-02-27 13:07:58 -080069import android.speech.RecognizerIntent;
Dianne Hackborn81e56d52011-05-26 00:55:58 -070070import android.util.DisplayMetrics;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080071import android.util.EventLog;
72import android.util.Log;
Jeff Browna41ca772010-08-11 14:46:32 -070073import android.util.Slog;
Jeff Brown6651a632011-11-28 12:59:11 -080074import android.util.SparseArray;
Dianne Hackbornf87d1962012-04-04 12:48:24 -070075import android.view.Display;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080076import android.view.Gravity;
77import android.view.HapticFeedbackConstants;
Dianne Hackborne0f085d2011-11-30 18:41:15 -080078import android.view.IApplicationToken;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080079import android.view.IWindowManager;
Jeff Browna41ca772010-08-11 14:46:32 -070080import android.view.InputChannel;
Jeff Brown4d396052010-10-29 21:50:21 -070081import android.view.InputDevice;
Jeff Brown4952dfd2011-11-30 19:23:22 -080082import android.view.InputEvent;
Jeff Brown32cbc38552011-12-01 14:01:49 -080083import android.view.InputEventReceiver;
Jeff Brown6b53e8d2010-11-10 16:03:06 -080084import android.view.KeyCharacterMap;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080085import android.view.KeyEvent;
86import android.view.MotionEvent;
87import 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;
Christopher Tatea53146c2010-09-07 11:57:52 -0700111import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
Daniel Sandler7d276c32012-01-30 14:33:52 -0500112import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700113import static android.view.WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800114import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
115import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
116import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
117import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
118import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
Jeff Brown3b2b3542010-10-15 00:54:27 -0700119import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800120import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
121import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
Joe Onorato29fc2c92010-11-24 10:26:50 -0800122import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800123import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800124import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
125import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
126import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
127import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
128import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
129import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700130import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700131import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Jeff Brown83c09682010-12-23 17:50:18 -0800132import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400133import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
Jim Millere898ac52012-04-06 17:10:57 -0700134import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -0700135import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800136import android.view.WindowManagerImpl;
137import android.view.WindowManagerPolicy;
Jeff Brownac143512012-04-05 18:57:33 -0700138import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
139import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
140import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
Jeff Brown6f2fba42011-02-19 01:08:02 -0800141import android.view.KeyCharacterMap.FallbackAction;
Dianne Hackborn295e3c22011-08-25 13:19:08 -0700142import android.view.accessibility.AccessibilityEvent;
Dianne Hackborn01ad2f42009-09-24 19:24:56 -0700143import android.view.animation.Animation;
144import android.view.animation.AnimationUtils;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800145
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800146import java.io.File;
Dianne Hackbornf99f9c52011-01-12 15:49:25 -0800147import java.io.FileDescriptor;
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 -0800151import java.util.ArrayList;
152
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800153/**
The Android Open Source Project0727d222009-03-11 12:11:58 -0700154 * WindowManagerPolicy implementation for the Android phone UI. This
155 * introduces a new method suffix, Lp, for an internal lock of the
156 * PhoneWindowManager. This is used to protect some internal state, and
157 * can be acquired with either thw Lw and Li lock held, so has the restrictions
158 * of both of those when held.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800159 */
160public class PhoneWindowManager implements WindowManagerPolicy {
161 static final String TAG = "WindowManager";
162 static final boolean DEBUG = false;
Joe Onorato43a17652011-04-06 19:22:23 -0700163 static final boolean localLOGV = false;
The Android Open Source Project11267662009-03-18 17:39:47 -0700164 static final boolean DEBUG_LAYOUT = false;
Jeff Brown49ed71d2010-12-06 17:13:33 -0800165 static final boolean DEBUG_FALLBACK = 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
Daniel Sandler7e37df52011-11-16 22:08:23 -0800174 // Should screen savers use their own timeout, or the SCREEN_OFF_TIMEOUT?
175 static final boolean SEPARATE_TIMEOUT_FOR_SCREEN_SAVER = false;
176
Joe Onoratod208e702010-10-08 16:22:43 -0400177 static final int LONG_PRESS_POWER_NOTHING = 0;
178 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
179 static final int LONG_PRESS_POWER_SHUT_OFF = 2;
Michael Jurka3b1fc472011-06-13 10:54:40 -0700180
181 // These need to match the documentation/constant in
182 // core/res/res/values/config.xml
Joe Onorato46b0d682010-11-22 17:37:27 -0800183 static final int LONG_PRESS_HOME_NOTHING = 0;
184 static final int LONG_PRESS_HOME_RECENT_DIALOG = 1;
Michael Jurka3b1fc472011-06-13 10:54:40 -0700185 static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 2;
Michael Jurka7a348952012-02-27 13:07:58 -0800186 static final int LONG_PRESS_HOME_VOICE_SEARCH = 3;
Joe Onorato46b0d682010-11-22 17:37:27 -0800187
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700188 // wallpaper is at the bottom, though the window manager may move it.
Dianne Hackborn3c3bd442009-08-19 17:09:46 -0700189 static final int WALLPAPER_LAYER = 2;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700190 static final int APPLICATION_LAYER = 2;
191 static final int PHONE_LAYER = 3;
192 static final int SEARCH_BAR_LAYER = 4;
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700193 static final int SYSTEM_DIALOG_LAYER = 5;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800194 // toasts and the plugged-in battery thing
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700195 static final int TOAST_LAYER = 6;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800196 // SIM errors and unlock. Not sure if this really should be in a high layer.
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700197 static final int PRIORITY_PHONE_LAYER = 7;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800198 // like the ANR / app crashed dialogs
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700199 static final int SYSTEM_ALERT_LAYER = 8;
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_LAYER = 9;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800202 // on-screen keyboards and other such input method user interfaces go here.
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700203 static final int INPUT_METHOD_DIALOG_LAYER = 10;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800204 // the keyguard; nothing on top of these can take focus, since they are
205 // responsible for power management when displayed.
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700206 static final int KEYGUARD_LAYER = 11;
207 static final int KEYGUARD_DIALOG_LAYER = 12;
Daniel Sandler7d276c32012-01-30 14:33:52 -0500208 // used for Dreams (screensavers with TYPE_DREAM windows)
209 static final int SCREENSAVER_LAYER = 13;
210 static final int STATUS_BAR_SUB_PANEL_LAYER = 14;
211 static final int STATUS_BAR_LAYER = 15;
212 static final int STATUS_BAR_PANEL_LAYER = 16;
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700213 // the on-screen volume indicator and controller shown when the user
214 // changes the device volume
Daniel Sandler7d276c32012-01-30 14:33:52 -0500215 static final int VOLUME_OVERLAY_LAYER = 17;
Jeff Brownbfcb60a2011-09-08 18:51:14 -0700216 // things in here CAN NOT take focus, but are shown on top of everything else.
Daniel Sandler7d276c32012-01-30 14:33:52 -0500217 static final int SYSTEM_OVERLAY_LAYER = 18;
Jeff Brownbfcb60a2011-09-08 18:51:14 -0700218 // the navigation bar, if available, shows atop most things
Daniel Sandler7d276c32012-01-30 14:33:52 -0500219 static final int NAVIGATION_BAR_LAYER = 19;
Jim Millere898ac52012-04-06 17:10:57 -0700220 // some panels (e.g. search) need to show on top of the navigation bar
221 static final int NAVIGATION_BAR_PANEL_LAYER = 20;
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700222 // system-level error dialogs
Jim Millere898ac52012-04-06 17:10:57 -0700223 static final int SYSTEM_ERROR_LAYER = 21;
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
Jim Millere898ac52012-04-06 17:10:57 -0700226 static final int DRAG_LAYER = 22;
227 static final int SECURE_SYSTEM_OVERLAY_LAYER = 23;
228 static final int BOOT_PROGRESS_LAYER = 24;
Jeff Brown83c09682010-12-23 17:50:18 -0800229 // the (mouse) pointer layer
Jim Millere898ac52012-04-06 17:10:57 -0700230 static final int POINTER_LAYER = 25;
231 static final int HIDDEN_NAV_CONSUMER_LAYER = 26;
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";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800242
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700243 /**
244 * These are the system UI flags that, when changing, can cause the layout
245 * of the screen to change.
246 */
247 static final int SYSTEM_UI_CHANGING_LAYOUT =
248 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
249
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700250 private static final int BTN_MOUSE = 0x110;
Jeff Brown6651a632011-11-28 12:59:11 -0800251
252 /* Table of Application Launch keys. Maps from key codes to intent categories.
253 *
254 * These are special keys that are used to launch particular kinds of applications,
255 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C)
256 * usage page. We don't support quite that many yet...
257 */
258 static SparseArray<String> sApplicationLaunchKeyCategories;
259 static {
260 sApplicationLaunchKeyCategories = new SparseArray<String>();
261 sApplicationLaunchKeyCategories.append(
262 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
263 sApplicationLaunchKeyCategories.append(
264 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
265 sApplicationLaunchKeyCategories.append(
266 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
267 sApplicationLaunchKeyCategories.append(
268 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
269 sApplicationLaunchKeyCategories.append(
270 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
271 sApplicationLaunchKeyCategories.append(
272 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
273 }
274
Dianne Hackborndf89e652011-10-06 22:35:11 -0700275 /**
276 * Lock protecting internal state. Must not call out into window
277 * manager with lock held. (This lock will be acquired in places
278 * where the window manager is calling in with its own lock held.)
279 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700280 final Object mLock = new Object();
Dianne Hackborndf89e652011-10-06 22:35:11 -0700281
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800282 Context mContext;
283 IWindowManager mWindowManager;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700284 WindowManagerFuncs mWindowManagerFuncs;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800285 LocalPowerManager mPowerManager;
Joe Onorato93056472010-09-10 10:30:46 -0400286 IStatusBarService mStatusBarService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800287 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
288
Dianne Hackborn181ceb52009-08-27 22:16:40 -0700289 // Vibrator pattern for haptic feedback of a long press.
290 long[] mLongPressVibePattern;
291
292 // Vibrator pattern for haptic feedback of virtual key press.
293 long[] mVirtualKeyVibePattern;
294
Amith Yamasanic33cb712010-02-10 15:21:49 -0800295 // Vibrator pattern for a short vibration.
296 long[] mKeyboardTapVibePattern;
297
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700298 // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
299 long[] mSafeModeDisabledVibePattern;
300
301 // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
302 long[] mSafeModeEnabledVibePattern;
Romain Guy8154cd32010-03-29 14:41:15 -0700303
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800304 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
305 boolean mEnableShiftMenuBugReports = false;
Mike Lockwoodd747dc82011-09-13 16:28:22 -0400306
307 boolean mHeadless;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800308 boolean mSafeMode;
309 WindowState mStatusBar = null;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700310 boolean mHasSystemNavBar;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700311 int mStatusBarHeight;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400312 WindowState mNavigationBar = null;
Daniel Sandler36412a72011-08-04 09:35:13 -0400313 boolean mHasNavigationBar = false;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700314 boolean mCanHideNavigationBar = false;
Daniel Sandler4a066c52012-04-20 14:49:13 -0400315 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
316 boolean mNavigationBarOnBottom = true; // is the navigation bar on the bottom *right now*?
317 int[] mNavigationBarHeightForRotation = new int[4];
318 int[] mNavigationBarWidthForRotation = new int[4];
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400319
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800320 WindowState mKeyguard = null;
321 KeyguardViewMediator mKeyguardMediator;
322 GlobalActions mGlobalActions;
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700323 volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
324 boolean mPendingPowerKeyUpCanceled;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800325 Handler mHandler;
Jeff Brown4aed78b2011-01-14 17:36:55 -0800326
Jeff Brown68b909d2011-12-07 16:36:01 -0800327 static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0;
328 static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1;
329 static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 2;
330
331 RecentApplicationsDialog mRecentAppsDialog;
332 int mRecentAppsDialogHeldModifiers;
333
Jeff Brown2e7760e2012-04-11 15:14:55 -0700334 int mLidState = LID_ABSENT;
Jeff Brown4aed78b2011-01-14 17:36:55 -0800335
Dianne Hackbornc777e072010-02-12 13:07:59 -0800336 boolean mSystemReady;
Dianne Hackbornba24e4d2011-09-01 11:17:06 -0700337 boolean mSystemBooted;
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800338 boolean mHdmiPlugged;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700339 int mExternalDisplayWidth;
340 int mExternalDisplayHeight;
Joe Onorato44fcb832011-12-14 20:59:30 -0800341 int mUiMode;
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700342 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700343 int mLidOpenRotation;
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400344 int mCarDockRotation;
345 int mDeskDockRotation;
Erik Gilling9a41ef82011-09-26 19:21:03 -0700346 int mHdmiRotation;
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400347
348 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
349 int mUserRotation = Surface.ROTATION_0;
350
Jeff Brownd3187e32011-09-21 19:26:44 -0700351 int mAllowAllRotations = -1;
Mike Lockwoode9867d22009-09-20 01:59:02 -0400352 boolean mCarDockEnablesAccelerometer;
353 boolean mDeskDockEnablesAccelerometer;
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700354 int mLidKeyboardAccessibility;
355 int mLidNavigationAccessibility;
Jeff Brownc458ce92012-04-30 14:58:40 -0700356 boolean mLidControlsSleep;
Joe Onoratod208e702010-10-08 16:22:43 -0400357 int mLongPressOnPowerBehavior = -1;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700358 boolean mScreenOnEarly = false;
359 boolean mScreenOnFully = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800360 boolean mOrientationSensorEnabled = false;
361 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
362 static final int DEFAULT_ACCELEROMETER_ROTATION = 0;
363 int mAccelerometerDefault = DEFAULT_ACCELEROMETER_ROTATION;
364 boolean mHasSoftInput = false;
365
Jeff Brown70825162012-03-28 17:27:48 -0700366 int mPointerLocationMode = 0; // guarded by mLock
Joe Onorato664644d2011-01-23 17:53:23 -0800367
368 // The last window we were told about in focusChanged.
369 WindowState mFocusedWindow;
Dianne Hackborne0f085d2011-11-30 18:41:15 -0800370 IApplicationToken mFocusedApp;
Joe Onorato664644d2011-01-23 17:53:23 -0800371
Jeff Brown70825162012-03-28 17:27:48 -0700372 private static final class PointerLocationInputEventReceiver extends InputEventReceiver {
373 private final PointerLocationView mView;
374
375 public PointerLocationInputEventReceiver(InputChannel inputChannel, Looper looper,
376 PointerLocationView view) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800377 super(inputChannel, looper);
Jeff Brown70825162012-03-28 17:27:48 -0700378 mView = view;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800379 }
380
Jeff Browna41ca772010-08-11 14:46:32 -0700381 @Override
Jeff Brown32cbc38552011-12-01 14:01:49 -0800382 public void onInputEvent(InputEvent event) {
Jeff Brown3915bb82010-11-05 15:02:16 -0700383 boolean handled = false;
384 try {
Jeff Brown4952dfd2011-11-30 19:23:22 -0800385 if (event instanceof MotionEvent
386 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
387 final MotionEvent motionEvent = (MotionEvent)event;
Jeff Brown70825162012-03-28 17:27:48 -0700388 mView.addPointerEvent(motionEvent);
389 handled = true;
Jeff Brown93ed4e32010-09-23 13:51:48 -0700390 }
Jeff Brown3915bb82010-11-05 15:02:16 -0700391 } finally {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800392 finishInputEvent(event, handled);
Jeff Browna41ca772010-08-11 14:46:32 -0700393 }
394 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800395 }
Jeff Brown70825162012-03-28 17:27:48 -0700396
397 // Pointer location view state, only modified on the mHandler Looper.
Jeff Brown32cbc38552011-12-01 14:01:49 -0800398 PointerLocationInputEventReceiver mPointerLocationInputEventReceiver;
Jeff Brown70825162012-03-28 17:27:48 -0700399 PointerLocationView mPointerLocationView;
400 InputChannel mPointerLocationInputChannel;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800401
Joe Onorato29fc2c92010-11-24 10:26:50 -0800402 // The current size of the screen; really; (ir)regardless of whether the status
403 // bar can be hidden or not
404 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
405 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
Dianne Hackborn82de1ae2010-10-28 11:28:39 -0700406 // The current size of the screen; these may be different than (0,0)-(dw,dh)
407 // if the status bar can't be hidden; in that case it effectively carves out
408 // that area of the display from all other windows.
Joe Onorato29fc2c92010-11-24 10:26:50 -0800409 int mRestrictedScreenLeft, mRestrictedScreenTop;
410 int mRestrictedScreenWidth, mRestrictedScreenHeight;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700411 // For applications requesting stable content insets, these are them.
412 int mStableLeft, mStableTop, mStableRight, mStableBottom;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800413 // During layout, the current screen borders with all outer decoration
414 // (status bar, input method dock) accounted for.
415 int mCurLeft, mCurTop, mCurRight, mCurBottom;
416 // During layout, the frame in which content should be displayed
417 // to the user, accounting for all screen decoration except for any
418 // space they deem as available for other content. This is usually
419 // the same as mCur*, but may be larger if the screen decor has supplied
420 // content insets.
421 int mContentLeft, mContentTop, mContentRight, mContentBottom;
Dianne Hackborn8e11ef02010-11-18 19:47:42 -0800422 // During layout, the current screen borders along which input method
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800423 // windows are placed.
424 int mDockLeft, mDockTop, mDockRight, mDockBottom;
425 // During layout, the layer at which the doc window is placed.
426 int mDockLayer;
Dianne Hackborne26ab702011-10-16 13:21:33 -0700427 int mLastSystemUiFlags;
428 // Bits that we are in the process of clearing, so we want to prevent
429 // them from being set by applications until everything has been updated
430 // to have them clear.
431 int mResettingSystemUiFlags = 0;
432 // Bits that we are currently always keeping cleared.
433 int mForceClearedSystemUiFlags = 0;
Dianne Hackborn4eff8d32011-11-10 19:38:40 -0800434 // What we last reported to system UI about whether the compatibility
435 // menu needs to be displayed.
436 boolean mLastFocusNeedsMenu = false;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700437
438 FakeWindow mHideNavFakeWindow = null;
439
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800440 static final Rect mTmpParentFrame = new Rect();
441 static final Rect mTmpDisplayFrame = new Rect();
442 static final Rect mTmpContentFrame = new Rect();
443 static final Rect mTmpVisibleFrame = new Rect();
Dianne Hackborn1f903c32011-09-13 19:18:06 -0700444 static final Rect mTmpNavigationFrame = new Rect();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800445
446 WindowState mTopFullscreenOpaqueWindowState;
Joe Onorato93056472010-09-10 10:30:46 -0400447 boolean mTopIsFullscreen;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800448 boolean mForceStatusBar;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700449 boolean mHideLockScreen;
450 boolean mDismissKeyguard;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800451 boolean mHomePressed;
Michael Jurka7f2668c2012-03-27 07:49:52 -0700452 boolean mHomeLongPressed;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800453 Intent mHomeIntent;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700454 Intent mCarDockIntent;
455 Intent mDeskDockIntent;
Jeff Brown49ed71d2010-12-06 17:13:33 -0800456 int mShortcutKeyPressed = -1;
457 boolean mConsumeShortcutKeyUp;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800458
Mike Lockwood28569302010-01-28 11:54:40 -0500459 // support for activating the lock screen while the screen is on
460 boolean mAllowLockscreenWhenOn;
461 int mLockScreenTimeout;
462 boolean mLockScreenTimerActive;
463
Daniel Sandler0601eb72011-04-13 01:01:32 -0400464 // visual screen saver support
Daniel Sandler7d276c32012-01-30 14:33:52 -0500465 boolean mScreenSaverFeatureAvailable;
Daniel Sandlere5f2cfe2011-11-02 23:30:58 -0400466 int mScreenSaverTimeout = 0;
Daniel Sandler2d545362011-11-17 10:38:37 -0800467 boolean mScreenSaverEnabledByUser = false;
468 boolean mScreenSaverMayRun = true; // false if a wakelock is held
Daniel Sandler7e37df52011-11-16 22:08:23 -0800469 boolean mPluggedIn;
Daniel Sandler0601eb72011-04-13 01:01:32 -0400470
David Brownbaf8d092010-03-08 21:52:59 -0800471 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800472 int mEndcallBehavior;
David Brownbaf8d092010-03-08 21:52:59 -0800473
474 // Behavior of POWER button while in-call and screen on.
475 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
476 int mIncallPowerBehavior;
477
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700478 Display mDisplay;
479
Dianne Hackborn9d132642011-04-21 17:26:39 -0700480 int mLandscapeRotation = 0; // default landscape rotation
481 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation
482 int mPortraitRotation = 0; // default portrait rotation
483 int mUpsideDownRotation = 0; // "other" portrait rotation
Mitsuru Oshima831d0d92009-06-16 18:27:18 -0700484
Joe Onorato46b0d682010-11-22 17:37:27 -0800485 // What we do when the user long presses on home
486 private int mLongPressOnHomeBehavior = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800487
Winson Chung9112ec32011-06-27 13:15:32 -0700488 // Screenshot trigger states
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700489 // Time to volume and power must be pressed within this interval of each other.
490 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
Christopher Tatee90585f2012-03-05 18:56:25 -0800491 private boolean mScreenshotChordEnabled;
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700492 private boolean mVolumeDownKeyTriggered;
493 private long mVolumeDownKeyTime;
494 private boolean mVolumeDownKeyConsumedByScreenshotChord;
495 private boolean mVolumeUpKeyTriggered;
496 private boolean mPowerKeyTriggered;
497 private long mPowerKeyTime;
Winson Chung9112ec32011-06-27 13:15:32 -0700498
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800499 ShortcutManager mShortcutManager;
500 PowerManager.WakeLock mBroadcastWakeLock;
501
Jeff Brown49ed71d2010-12-06 17:13:33 -0800502 final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction();
503
Jeff Brown70825162012-03-28 17:27:48 -0700504 private static final int MSG_ENABLE_POINTER_LOCATION = 1;
505 private static final int MSG_DISABLE_POINTER_LOCATION = 2;
506
507 private class PolicyHandler extends Handler {
508 @Override
509 public void handleMessage(Message msg) {
510 switch (msg.what) {
511 case MSG_ENABLE_POINTER_LOCATION:
512 enablePointerLocation();
513 break;
514 case MSG_DISABLE_POINTER_LOCATION:
515 disablePointerLocation();
516 break;
517 }
518 }
519 }
520
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800521 private UEventObserver mHDMIObserver = new UEventObserver() {
522 @Override
523 public void onUEvent(UEventObserver.UEvent event) {
524 setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
525 }
526 };
527
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800528 class SettingsObserver extends ContentObserver {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800529 SettingsObserver(Handler handler) {
530 super(handler);
531 }
David Brownbaf8d092010-03-08 21:52:59 -0800532
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800533 void observe() {
534 ContentResolver resolver = mContext.getContentResolver();
535 resolver.registerContentObserver(Settings.System.getUriFor(
536 Settings.System.END_BUTTON_BEHAVIOR), false, this);
David Brownbaf8d092010-03-08 21:52:59 -0800537 resolver.registerContentObserver(Settings.Secure.getUriFor(
538 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800539 resolver.registerContentObserver(Settings.System.getUriFor(
540 Settings.System.ACCELEROMETER_ROTATION), false, this);
Mike Lockwood28569302010-01-28 11:54:40 -0500541 resolver.registerContentObserver(Settings.System.getUriFor(
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400542 Settings.System.USER_ROTATION), false, this);
543 resolver.registerContentObserver(Settings.System.getUriFor(
Mike Lockwood28569302010-01-28 11:54:40 -0500544 Settings.System.SCREEN_OFF_TIMEOUT), false, this);
Dianne Hackbornc777e072010-02-12 13:07:59 -0800545 resolver.registerContentObserver(Settings.System.getUriFor(
Jeff Brown4519f072011-01-23 13:16:01 -0800546 Settings.System.WINDOW_ORIENTATION_LISTENER_LOG), false, this);
547 resolver.registerContentObserver(Settings.System.getUriFor(
Dianne Hackbornc777e072010-02-12 13:07:59 -0800548 Settings.System.POINTER_LOCATION), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800549 resolver.registerContentObserver(Settings.Secure.getUriFor(
550 Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700551 resolver.registerContentObserver(Settings.System.getUriFor(
552 "fancy_rotation_anim"), false, this);
Daniel Sandler2d545362011-11-17 10:38:37 -0800553 resolver.registerContentObserver(Settings.Secure.getUriFor(
554 Settings.Secure.SCREENSAVER_ENABLED), false, this);
Daniel Sandler7e37df52011-11-16 22:08:23 -0800555 if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
556 resolver.registerContentObserver(Settings.Secure.getUriFor(
Daniel Sandler2d545362011-11-17 10:38:37 -0800557 "screensaver_timeout"), false, this);
Daniel Sandler7e37df52011-11-16 22:08:23 -0800558 } // otherwise SCREEN_OFF_TIMEOUT will do nicely
Dianne Hackbornc777e072010-02-12 13:07:59 -0800559 updateSettings();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800560 }
561
562 @Override public void onChange(boolean selfChange) {
Dianne Hackbornc777e072010-02-12 13:07:59 -0800563 updateSettings();
Jeff Brown01a98dd2011-09-20 15:08:29 -0700564 updateRotation(false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800565 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800566 }
567
568 class MyOrientationListener extends WindowOrientationListener {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800569 MyOrientationListener(Context context) {
570 super(context);
571 }
572
573 @Override
Jeff Brownc0347aa2011-09-23 17:26:09 -0700574 public void onProposedRotationChanged(int rotation) {
575 if (localLOGV) Log.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
Jeff Brown01a98dd2011-09-20 15:08:29 -0700576 updateRotation(false);
577 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800578 }
579 MyOrientationListener mOrientationListener;
580
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700581 /*
582 * We always let the sensor be switched on by default except when
583 * the user has explicitly disabled sensor based rotation or when the
584 * screen is switched off.
585 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700586 boolean needSensorRunningLp() {
Dianne Hackborne5439f22010-10-02 16:53:50 -0700587 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
588 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
589 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
590 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800591 // If the application has explicitly requested to follow the
592 // orientation, then we need to turn the sensor or.
593 return true;
594 }
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700595 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
Jeff Brown1a693182011-11-08 14:44:16 -0800596 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
597 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
598 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
Mike Lockwoode9867d22009-09-20 01:59:02 -0400599 // enable accelerometer if we are docked in a dock that enables accelerometer
600 // orientation management,
601 return true;
602 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700603 if (mAccelerometerDefault == 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800604 // If the setting for using the sensor by default is enabled, then
605 // we will always leave it on. Note that the user could go to
606 // a window that forces an orientation that does not use the
607 // sensor and in theory we could turn it off... however, when next
608 // turning it on we won't have a good value for the current
609 // orientation for a little bit, which can cause orientation
610 // changes to lag, so we'd like to keep it always on. (It will
611 // still be turned off when the screen is off.)
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700612 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800613 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700614 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800615 }
616
617 /*
618 * Various use cases for invoking this function
619 * screen turning off, should always disable listeners if already enabled
620 * screen turned on and current app has sensor based orientation, enable listeners
621 * if not already enabled
622 * screen turned on and current app does not have sensor orientation, disable listeners if
623 * already enabled
624 * screen turning on and current app has sensor based orientation, enable listeners if needed
625 * screen turning on and current app has nosensor based orientation, do nothing
626 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700627 void updateOrientationListenerLp() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800628 if (!mOrientationListener.canDetectOrientation()) {
629 // If sensor is turned off or nonexistent for some reason
630 return;
631 }
632 //Could have been invoked due to screen turning on or off or
633 //change of the currently visible window's orientation
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700634 if (localLOGV) Log.v(TAG, "Screen status="+mScreenOnEarly+
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800635 ", current orientation="+mCurrentAppOrientation+
636 ", SensorEnabled="+mOrientationSensorEnabled);
637 boolean disable = true;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700638 if (mScreenOnEarly) {
The Android Open Source Project0727d222009-03-11 12:11:58 -0700639 if (needSensorRunningLp()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800640 disable = false;
641 //enable listener if not already enabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700642 if (!mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800643 mOrientationListener.enable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700644 if(localLOGV) Log.v(TAG, "Enabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800645 mOrientationSensorEnabled = true;
646 }
647 }
648 }
649 //check if sensors need to be disabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700650 if (disable && mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800651 mOrientationListener.disable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700652 if(localLOGV) Log.v(TAG, "Disabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800653 mOrientationSensorEnabled = false;
654 }
655 }
656
Jeff Brown4d396052010-10-29 21:50:21 -0700657 private void interceptPowerKeyDown(boolean handled) {
658 mPowerKeyHandled = handled;
659 if (!handled) {
660 mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
661 }
662 }
663
664 private boolean interceptPowerKeyUp(boolean canceled) {
665 if (!mPowerKeyHandled) {
666 mHandler.removeCallbacks(mPowerLongPress);
667 return !canceled;
Jeff Brown4d396052010-10-29 21:50:21 -0700668 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700669 return false;
670 }
671
672 private void cancelPendingPowerKeyAction() {
673 if (!mPowerKeyHandled) {
674 mHandler.removeCallbacks(mPowerLongPress);
675 }
Jeff Brownff204712011-10-25 21:27:54 -0700676 if (mPowerKeyTriggered) {
677 mPendingPowerKeyUpCanceled = true;
678 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700679 }
680
681 private void interceptScreenshotChord() {
Christopher Tatee90585f2012-03-05 18:56:25 -0800682 if (mScreenshotChordEnabled
683 && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700684 final long now = SystemClock.uptimeMillis();
685 if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
686 && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
687 mVolumeDownKeyConsumedByScreenshotChord = true;
688 cancelPendingPowerKeyAction();
689
690 mHandler.postDelayed(mScreenshotChordLongPress,
691 ViewConfiguration.getGlobalActionKeyTimeout());
692 }
693 }
694 }
695
696 private void cancelPendingScreenshotChordAction() {
697 mHandler.removeCallbacks(mScreenshotChordLongPress);
Jeff Brown4d396052010-10-29 21:50:21 -0700698 }
699
700 private final Runnable mPowerLongPress = new Runnable() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800701 public void run() {
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700702 // The context isn't read
703 if (mLongPressOnPowerBehavior < 0) {
704 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
705 com.android.internal.R.integer.config_longPressOnPowerBehavior);
Joe Onoratod208e702010-10-08 16:22:43 -0400706 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700707 switch (mLongPressOnPowerBehavior) {
708 case LONG_PRESS_POWER_NOTHING:
709 break;
710 case LONG_PRESS_POWER_GLOBAL_ACTIONS:
711 mPowerKeyHandled = true;
712 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
713 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
714 showGlobalActionsDialog();
715 break;
716 case LONG_PRESS_POWER_SHUT_OFF:
717 mPowerKeyHandled = true;
718 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
719 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
720 ShutdownThread.shutdown(mContext, true);
721 break;
722 }
723 }
724 };
725
726 private final Runnable mScreenshotChordLongPress = new Runnable() {
727 public void run() {
728 takeScreenshot();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800729 }
730 };
731
732 void showGlobalActionsDialog() {
733 if (mGlobalActions == null) {
734 mGlobalActions = new GlobalActions(mContext);
735 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -0700736 final boolean keyguardShowing = keyguardIsShowingTq();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800737 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
738 if (keyguardShowing) {
739 // since it took two seconds of long press to bring this up,
740 // poke the wake lock so they have some time to see the dialog.
741 mKeyguardMediator.pokeWakelock();
742 }
743 }
744
745 boolean isDeviceProvisioned() {
746 return Settings.Secure.getInt(
747 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
748 }
749
Patrick Dubroyece94522011-02-23 18:35:01 -0800750 private void handleLongPressOnHome() {
Jim Milleree969aa2010-08-26 20:17:43 -0700751 // We can't initialize this in init() since the configuration hasn't been loaded yet.
Joe Onorato46b0d682010-11-22 17:37:27 -0800752 if (mLongPressOnHomeBehavior < 0) {
753 mLongPressOnHomeBehavior
Joe Onorato50262e52010-11-26 14:04:54 -0800754 = mContext.getResources().getInteger(R.integer.config_longPressOnHomeBehavior);
Joe Onorato46b0d682010-11-22 17:37:27 -0800755 if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
Michael Jurka3b1fc472011-06-13 10:54:40 -0700756 mLongPressOnHomeBehavior > LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
Joe Onorato46b0d682010-11-22 17:37:27 -0800757 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
758 }
Michael Jurka7a348952012-02-27 13:07:58 -0800759 if (hasNavigationBar()) {
760 mLongPressOnHomeBehavior = LONG_PRESS_HOME_VOICE_SEARCH;
761 }
Joe Onorato46b0d682010-11-22 17:37:27 -0800762 }
763
764 if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
765 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
766 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
Patrick Dubroyece94522011-02-23 18:35:01 -0800767
768 // Eat the longpress so it won't dismiss the recent apps dialog when
769 // the user lets go of the home key
Michael Jurka7f2668c2012-03-27 07:49:52 -0700770 mHomeLongPressed = true;
Jim Milleree969aa2010-08-26 20:17:43 -0700771 }
Patrick Dubroyece94522011-02-23 18:35:01 -0800772
Joe Onorato46b0d682010-11-22 17:37:27 -0800773 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
Jeff Brown68b909d2011-12-07 16:36:01 -0800774 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
Michael Jurka3b1fc472011-06-13 10:54:40 -0700775 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
Jim Millere6ad1a82010-08-20 19:25:39 -0700776 try {
Michael Jurka3b1fc472011-06-13 10:54:40 -0700777 mStatusBarService.toggleRecentApps();
778 } catch (RemoteException e) {
779 Slog.e(TAG, "RemoteException when showing recent apps", e);
Jim Millere6ad1a82010-08-20 19:25:39 -0700780 }
Michael Jurka7a348952012-02-27 13:07:58 -0800781 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_VOICE_SEARCH) {
782 Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
783 try {
784 intent.setFlags(
785 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
786 mContext.startActivity(intent);
787 } catch (ActivityNotFoundException e) {
788 Log.e(TAG, "Unable to launch. tag=" + TAG + " intent=" + intent, e);
789 } catch (SecurityException e) {
790 Log.e(TAG, "PhoneWindowManager does not have the permission to launch " +
791 "tag=" + TAG + " intent=" + intent, e);
792 }
Jim Millere6ad1a82010-08-20 19:25:39 -0700793 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800794 }
Patrick Dubroyece94522011-02-23 18:35:01 -0800795
796 /**
Jeff Brown68b909d2011-12-07 16:36:01 -0800797 * Create (if necessary) and show or dismiss the recent apps dialog according
798 * according to the requested behavior.
Patrick Dubroyece94522011-02-23 18:35:01 -0800799 */
Jeff Brown68b909d2011-12-07 16:36:01 -0800800 void showOrHideRecentAppsDialog(final int behavior) {
Jeff Brownda3d5a92011-03-29 15:11:34 -0700801 mHandler.post(new Runnable() {
802 @Override
803 public void run() {
804 if (mRecentAppsDialog == null) {
Jeff Brown54875002011-04-06 15:33:01 -0700805 mRecentAppsDialog = new RecentApplicationsDialog(mContext);
Jeff Brownda3d5a92011-03-29 15:11:34 -0700806 }
Jeff Brown54875002011-04-06 15:33:01 -0700807 if (mRecentAppsDialog.isShowing()) {
Jeff Brown68b909d2011-12-07 16:36:01 -0800808 switch (behavior) {
809 case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
810 mRecentAppsDialog.dismiss();
811 break;
812 case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
813 mRecentAppsDialog.dismissAndSwitch();
814 break;
815 case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
816 default:
817 break;
Jeff Brown54875002011-04-06 15:33:01 -0700818 }
819 } else {
Jeff Brown68b909d2011-12-07 16:36:01 -0800820 switch (behavior) {
821 case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
822 mRecentAppsDialog.show();
823 break;
824 case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
825 try {
826 mWindowManager.setInTouchMode(false);
827 } catch (RemoteException e) {
828 }
829 mRecentAppsDialog.show();
830 break;
831 case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
832 default:
833 break;
834 }
Jeff Brown54875002011-04-06 15:33:01 -0700835 }
Jeff Brownda3d5a92011-03-29 15:11:34 -0700836 }
837 });
Patrick Dubroyece94522011-02-23 18:35:01 -0800838 }
Jeff Brownda3d5a92011-03-29 15:11:34 -0700839
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800840 /** {@inheritDoc} */
841 public void init(Context context, IWindowManager windowManager,
Dianne Hackborndf89e652011-10-06 22:35:11 -0700842 WindowManagerFuncs windowManagerFuncs,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800843 LocalPowerManager powerManager) {
844 mContext = context;
845 mWindowManager = windowManager;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700846 mWindowManagerFuncs = windowManagerFuncs;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800847 mPowerManager = powerManager;
Mike Lockwoodd747dc82011-09-13 16:28:22 -0400848 mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
849 if (!mHeadless) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -0700850 // don't create KeyguardViewMediator if headless
851 mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
852 }
Jeff Brown70825162012-03-28 17:27:48 -0700853 mHandler = new PolicyHandler();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800854 mOrientationListener = new MyOrientationListener(mContext);
Jeff Brownc0347aa2011-09-23 17:26:09 -0700855 try {
856 mOrientationListener.setCurrentRotation(windowManager.getRotation());
857 } catch (RemoteException ex) { }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800858 SettingsObserver settingsObserver = new SettingsObserver(mHandler);
859 settingsObserver.observe();
860 mShortcutManager = new ShortcutManager(context, mHandler);
861 mShortcutManager.observe();
Joe Onorato44fcb832011-12-14 20:59:30 -0800862 mUiMode = context.getResources().getInteger(
863 com.android.internal.R.integer.config_defaultUiModeType);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800864 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
865 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
866 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
867 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700868 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
869 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
870 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
871 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
872 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
873 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
874 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
875 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Jim Millere6ad1a82010-08-20 19:25:39 -0700876
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800877 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
878 mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
879 "PhoneWindowManager.mBroadcastWakeLock");
880 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700881 mLidOpenRotation = readRotation(
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400882 com.android.internal.R.integer.config_lidOpenRotation);
883 mCarDockRotation = readRotation(
884 com.android.internal.R.integer.config_carDockRotation);
885 mDeskDockRotation = readRotation(
886 com.android.internal.R.integer.config_deskDockRotation);
Mike Lockwoode9867d22009-09-20 01:59:02 -0400887 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
888 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
889 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
890 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700891 mLidKeyboardAccessibility = mContext.getResources().getInteger(
892 com.android.internal.R.integer.config_lidKeyboardAccessibility);
893 mLidNavigationAccessibility = mContext.getResources().getInteger(
894 com.android.internal.R.integer.config_lidNavigationAccessibility);
Jeff Brownc458ce92012-04-30 14:58:40 -0700895 mLidControlsSleep = mContext.getResources().getBoolean(
896 com.android.internal.R.bool.config_lidControlsSleep);
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700897 // register for dock events
Dianne Hackborn78968392010-03-04 20:47:56 -0800898 IntentFilter filter = new IntentFilter();
899 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
900 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
901 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
902 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700903 filter.addAction(Intent.ACTION_DOCK_EVENT);
904 Intent intent = context.registerReceiver(mDockReceiver, filter);
905 if (intent != null) {
906 // Retrieve current sticky dock event broadcast.
907 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
908 Intent.EXTRA_DOCK_STATE_UNDOCKED);
909 }
Daniel Sandler7e37df52011-11-16 22:08:23 -0800910
911 // watch the plug to know whether to trigger the screen saver
912 filter = new IntentFilter();
913 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
914 intent = context.registerReceiver(mPowerReceiver, filter);
915 if (intent != null) {
916 mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
917 }
918
Jeff Brownc2346132012-04-13 01:55:38 -0700919 mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700920 mLongPressVibePattern = getLongIntArray(mContext.getResources(),
921 com.android.internal.R.array.config_longPressVibePattern);
922 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
923 com.android.internal.R.array.config_virtualKeyVibePattern);
Amith Yamasanic33cb712010-02-10 15:21:49 -0800924 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
925 com.android.internal.R.array.config_keyboardTapVibePattern);
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700926 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
927 com.android.internal.R.array.config_safeModeDisabledVibePattern);
928 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
929 com.android.internal.R.array.config_safeModeEnabledVibePattern);
Daniel Sandler40427442010-07-16 11:44:52 -0400930
Christopher Tatee90585f2012-03-05 18:56:25 -0800931 mScreenshotChordEnabled = mContext.getResources().getBoolean(
932 com.android.internal.R.bool.config_enableScreenshotChord);
933
Joe Onoratoea495d42011-04-06 11:41:11 -0700934 // Controls rotation and the like.
935 initializeHdmiState();
Dianne Hackborn40011092011-09-22 13:37:48 -0700936
937 // Match current screen state.
938 if (mPowerManager.isScreenOn()) {
939 screenTurningOn(null);
940 } else {
941 screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
942 }
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700943 }
944
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700945 public void setInitialDisplaySize(Display display, int width, int height) {
946 mDisplay = display;
947
948 int shortSize, longSize;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700949 if (width > height) {
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700950 shortSize = height;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700951 longSize = width;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700952 mLandscapeRotation = Surface.ROTATION_0;
953 mSeascapeRotation = Surface.ROTATION_180;
954 if (mContext.getResources().getBoolean(
955 com.android.internal.R.bool.config_reverseDefaultRotation)) {
956 mPortraitRotation = Surface.ROTATION_90;
957 mUpsideDownRotation = Surface.ROTATION_270;
958 } else {
959 mPortraitRotation = Surface.ROTATION_270;
960 mUpsideDownRotation = Surface.ROTATION_90;
961 }
962 } else {
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700963 shortSize = width;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700964 longSize = height;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700965 mPortraitRotation = Surface.ROTATION_0;
966 mUpsideDownRotation = Surface.ROTATION_180;
967 if (mContext.getResources().getBoolean(
968 com.android.internal.R.bool.config_reverseDefaultRotation)) {
969 mLandscapeRotation = Surface.ROTATION_270;
970 mSeascapeRotation = Surface.ROTATION_90;
971 } else {
972 mLandscapeRotation = Surface.ROTATION_90;
973 mSeascapeRotation = Surface.ROTATION_270;
974 }
975 }
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700976
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700977 mExternalDisplayWidth = mDisplay.getRawExternalWidth();
978 mExternalDisplayHeight = mDisplay.getRawExternalHeight();
979
980 mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
981 com.android.internal.R.dimen.status_bar_height);
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700982
Daniel Sandler9f65c4c2012-04-26 01:35:35 -0400983 // Height of the navigation bar when presented horizontally at bottom
984 mNavigationBarHeightForRotation[mPortraitRotation] =
985 mNavigationBarHeightForRotation[mUpsideDownRotation] =
Daniel Sandler4a066c52012-04-20 14:49:13 -0400986 mContext.getResources().getDimensionPixelSize(
987 com.android.internal.R.dimen.navigation_bar_height);
Daniel Sandler9f65c4c2012-04-26 01:35:35 -0400988 mNavigationBarHeightForRotation[mLandscapeRotation] =
989 mNavigationBarHeightForRotation[mSeascapeRotation] =
990 mContext.getResources().getDimensionPixelSize(
991 com.android.internal.R.dimen.navigation_bar_height_landscape);
992
993 // Width of the navigation bar when presented vertically along one side
994 mNavigationBarWidthForRotation[mPortraitRotation] =
995 mNavigationBarWidthForRotation[mUpsideDownRotation] =
996 mNavigationBarWidthForRotation[mLandscapeRotation] =
997 mNavigationBarWidthForRotation[mSeascapeRotation] =
Daniel Sandler4a066c52012-04-20 14:49:13 -0400998 mContext.getResources().getDimensionPixelSize(
999 com.android.internal.R.dimen.navigation_bar_width);
1000
1001 // SystemUI (status bar) layout policy
Daniel Sandler631cb3d52011-06-03 01:25:43 -04001002 int shortSizeDp = shortSize
1003 * DisplayMetrics.DENSITY_DEFAULT
1004 / DisplayMetrics.DENSITY_DEVICE;
Daniel Sandler4a066c52012-04-20 14:49:13 -04001005
1006 if (shortSizeDp < 600) {
1007 // 0-599dp: "phone" UI with a separate status & navigation bar
1008 mHasSystemNavBar = false;
1009 mNavigationBarCanMove = true;
1010 } else if (shortSizeDp < 720) {
1011 // 600-719dp: "phone" UI with modifications for larger screens
1012 mHasSystemNavBar = false;
1013 mNavigationBarCanMove = false;
1014 } else {
1015 // 720dp: "tablet" UI with a single combined status & navigation bar
1016 mHasSystemNavBar = true;
1017 mNavigationBarCanMove = false;
1018 }
Daniel Sandler36412a72011-08-04 09:35:13 -04001019
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001020 if (!mHasSystemNavBar) {
1021 mHasNavigationBar = mContext.getResources().getBoolean(
1022 com.android.internal.R.bool.config_showNavigationBar);
1023 // Allow a system property to override this. Used by the emulator.
1024 // See also hasNavigationBar().
1025 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
1026 if (! "".equals(navBarOverride)) {
1027 if (navBarOverride.equals("1")) mHasNavigationBar = false;
1028 else if (navBarOverride.equals("0")) mHasNavigationBar = true;
1029 }
1030 } else {
1031 mHasNavigationBar = false;
Daniel Sandler0c4ccff2011-10-19 16:39:14 -04001032 }
1033
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001034 if (mHasSystemNavBar) {
1035 // The system bar is always at the bottom. If you are watching
1036 // a video in landscape, we don't need to hide it if we can still
1037 // show a 16:9 aspect ratio with it.
1038 int longSizeDp = longSize
1039 * DisplayMetrics.DENSITY_DEFAULT
1040 / DisplayMetrics.DENSITY_DEVICE;
Daniel Sandler4a066c52012-04-20 14:49:13 -04001041 int barHeightDp = mNavigationBarHeightForRotation[mLandscapeRotation]
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001042 * DisplayMetrics.DENSITY_DEFAULT
1043 / DisplayMetrics.DENSITY_DEVICE;
1044 int aspect = ((shortSizeDp-barHeightDp) * 16) / longSizeDp;
1045 // We have computed the aspect ratio with the bar height taken
1046 // out to be 16:aspect. If this is less than 9, then hiding
1047 // the navigation bar will provide more useful space for wide
1048 // screen movies.
1049 mCanHideNavigationBar = aspect < 9;
1050 } else if (mHasNavigationBar) {
1051 // The navigation bar is at the right in landscape; it seems always
1052 // useful to hide it for showing a video.
1053 mCanHideNavigationBar = true;
1054 } else {
1055 mCanHideNavigationBar = false;
1056 }
Erik Gilling9a41ef82011-09-26 19:21:03 -07001057
1058 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
1059 mHdmiRotation = mPortraitRotation;
1060 } else {
1061 mHdmiRotation = mLandscapeRotation;
1062 }
Dianne Hackborn9d132642011-04-21 17:26:39 -07001063 }
1064
Dianne Hackbornc777e072010-02-12 13:07:59 -08001065 public void updateSettings() {
1066 ContentResolver resolver = mContext.getContentResolver();
1067 boolean updateRotation = false;
Dianne Hackbornc777e072010-02-12 13:07:59 -08001068 synchronized (mLock) {
1069 mEndcallBehavior = Settings.System.getInt(resolver,
David Brownbaf8d092010-03-08 21:52:59 -08001070 Settings.System.END_BUTTON_BEHAVIOR,
1071 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT);
1072 mIncallPowerBehavior = Settings.Secure.getInt(resolver,
1073 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
1074 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001075 int accelerometerDefault = Settings.System.getInt(resolver,
1076 Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001077
1078 // set up rotation lock state
Daniel Sandler1b815d62010-11-05 10:24:27 -04001079 mUserRotationMode = (accelerometerDefault == 0)
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001080 ? WindowManagerPolicy.USER_ROTATION_LOCKED
1081 : WindowManagerPolicy.USER_ROTATION_FREE;
1082 mUserRotation = Settings.System.getInt(resolver,
1083 Settings.System.USER_ROTATION,
1084 Surface.ROTATION_0);
1085
Dianne Hackbornc777e072010-02-12 13:07:59 -08001086 if (mAccelerometerDefault != accelerometerDefault) {
1087 mAccelerometerDefault = accelerometerDefault;
1088 updateOrientationListenerLp();
1089 }
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001090
Jeff Brown4519f072011-01-23 13:16:01 -08001091 mOrientationListener.setLogEnabled(
1092 Settings.System.getInt(resolver,
1093 Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, 0) != 0);
1094
Dianne Hackbornc777e072010-02-12 13:07:59 -08001095 if (mSystemReady) {
1096 int pointerLocation = Settings.System.getInt(resolver,
1097 Settings.System.POINTER_LOCATION, 0);
1098 if (mPointerLocationMode != pointerLocation) {
1099 mPointerLocationMode = pointerLocation;
Jeff Brown70825162012-03-28 17:27:48 -07001100 mHandler.sendEmptyMessage(pointerLocation != 0 ?
1101 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001102 }
1103 }
1104 // use screen off timeout setting as the timeout for the lockscreen
1105 mLockScreenTimeout = Settings.System.getInt(resolver,
1106 Settings.System.SCREEN_OFF_TIMEOUT, 0);
1107 String imId = Settings.Secure.getString(resolver,
1108 Settings.Secure.DEFAULT_INPUT_METHOD);
1109 boolean hasSoftInput = imId != null && imId.length() > 0;
1110 if (mHasSoftInput != hasSoftInput) {
1111 mHasSoftInput = hasSoftInput;
1112 updateRotation = true;
1113 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04001114
Daniel Sandler7d276c32012-01-30 14:33:52 -05001115 // dreams
1116 mScreenSaverFeatureAvailable = mContext.getResources().getBoolean(
1117 com.android.internal.R.bool.config_enableDreams);
1118
Daniel Sandler2d545362011-11-17 10:38:37 -08001119 mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver,
1120 Settings.Secure.SCREENSAVER_ENABLED, 1);
1121
Daniel Sandler7e37df52011-11-16 22:08:23 -08001122 if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
1123 mScreenSaverTimeout = Settings.Secure.getInt(resolver,
Daniel Sandler2d545362011-11-17 10:38:37 -08001124 "screensaver_timeout", 0);
Daniel Sandler7e37df52011-11-16 22:08:23 -08001125 } else {
1126 mScreenSaverTimeout = Settings.System.getInt(resolver,
1127 Settings.System.SCREEN_OFF_TIMEOUT, 0);
1128 if (mScreenSaverTimeout > 0) {
1129 // We actually want to activate the screensaver just before the
1130 // power manager's screen timeout
1131 mScreenSaverTimeout -= 5000;
1132 }
1133 }
Dianne Hackbornc777e072010-02-12 13:07:59 -08001134 }
1135 if (updateRotation) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07001136 updateRotation(true);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001137 }
Jeff Brown70825162012-03-28 17:27:48 -07001138 }
1139
1140 private void enablePointerLocation() {
1141 if (mPointerLocationView == null) {
1142 mPointerLocationView = new PointerLocationView(mContext);
1143 mPointerLocationView.setPrintCoords(false);
1144
Dianne Hackbornc777e072010-02-12 13:07:59 -08001145 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
1146 WindowManager.LayoutParams.MATCH_PARENT,
1147 WindowManager.LayoutParams.MATCH_PARENT);
Jeff Brown3b2b3542010-10-15 00:54:27 -07001148 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
Jeff Brownbfcb60a2011-09-08 18:51:14 -07001149 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
1150 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
1151 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1152 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Dianne Hackbornc777e072010-02-12 13:07:59 -08001153 lp.format = PixelFormat.TRANSLUCENT;
1154 lp.setTitle("PointerLocation");
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001155 WindowManager wm = (WindowManager)
Dianne Hackbornc777e072010-02-12 13:07:59 -08001156 mContext.getSystemService(Context.WINDOW_SERVICE);
Jeff Browncc4f7db2011-08-30 20:34:48 -07001157 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
Jeff Brown70825162012-03-28 17:27:48 -07001158 wm.addView(mPointerLocationView, lp);
1159
Jeff Brownac143512012-04-05 18:57:33 -07001160 mPointerLocationInputChannel =
1161 mWindowManagerFuncs.monitorInput("PointerLocationView");
1162 mPointerLocationInputEventReceiver =
1163 new PointerLocationInputEventReceiver(mPointerLocationInputChannel,
1164 Looper.myLooper(), mPointerLocationView);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001165 }
Dianne Hackbornc777e072010-02-12 13:07:59 -08001166 }
Jeff Brown70825162012-03-28 17:27:48 -07001167
1168 private void disablePointerLocation() {
1169 if (mPointerLocationInputEventReceiver != null) {
1170 mPointerLocationInputEventReceiver.dispose();
1171 mPointerLocationInputEventReceiver = null;
1172 }
1173
1174 if (mPointerLocationInputChannel != null) {
1175 mPointerLocationInputChannel.dispose();
1176 mPointerLocationInputChannel = null;
1177 }
1178
1179 if (mPointerLocationView != null) {
1180 WindowManager wm = (WindowManager)
1181 mContext.getSystemService(Context.WINDOW_SERVICE);
1182 wm.removeView(mPointerLocationView);
1183 mPointerLocationView = null;
1184 }
1185 }
1186
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001187 private int readRotation(int resID) {
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001188 try {
1189 int rotation = mContext.getResources().getInteger(resID);
1190 switch (rotation) {
1191 case 0:
1192 return Surface.ROTATION_0;
1193 case 90:
1194 return Surface.ROTATION_90;
1195 case 180:
1196 return Surface.ROTATION_180;
1197 case 270:
1198 return Surface.ROTATION_270;
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001199 }
1200 } catch (Resources.NotFoundException e) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001201 // fall through
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001202 }
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001203 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001204 }
1205
1206 /** {@inheritDoc} */
1207 public int checkAddPermission(WindowManager.LayoutParams attrs) {
1208 int type = attrs.type;
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07001209
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001210 if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
1211 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
1212 return WindowManagerImpl.ADD_OKAY;
1213 }
1214 String permission = null;
1215 switch (type) {
1216 case TYPE_TOAST:
1217 // XXX right now the app process has complete control over
1218 // this... should introduce a token to let the system
1219 // monitor/control what they are doing.
1220 break;
Daniel Sandler7d276c32012-01-30 14:33:52 -05001221 case TYPE_DREAM:
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001222 case TYPE_INPUT_METHOD:
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -07001223 case TYPE_WALLPAPER:
1224 // The window manager will check these.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001225 break;
1226 case TYPE_PHONE:
1227 case TYPE_PRIORITY_PHONE:
1228 case TYPE_SYSTEM_ALERT:
1229 case TYPE_SYSTEM_ERROR:
1230 case TYPE_SYSTEM_OVERLAY:
1231 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
1232 break;
1233 default:
1234 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
1235 }
1236 if (permission != null) {
1237 if (mContext.checkCallingOrSelfPermission(permission)
1238 != PackageManager.PERMISSION_GRANTED) {
1239 return WindowManagerImpl.ADD_PERMISSION_DENIED;
1240 }
1241 }
1242 return WindowManagerImpl.ADD_OKAY;
1243 }
1244
1245 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
1246 switch (attrs.type) {
1247 case TYPE_SYSTEM_OVERLAY:
Jeff Brown3b2b3542010-10-15 00:54:27 -07001248 case TYPE_SECURE_SYSTEM_OVERLAY:
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001249 case TYPE_TOAST:
1250 // These types of windows can't receive input events.
1251 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1252 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Jeff Brownbfcb60a2011-09-08 18:51:14 -07001253 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001254 break;
1255 }
1256 }
1257
1258 void readLidState() {
Jeff Brown2e7760e2012-04-11 15:14:55 -07001259 mLidState = mWindowManagerFuncs.getLidState();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001260 }
1261
Jeff Brown4aed78b2011-01-14 17:36:55 -08001262 private int determineHiddenState(int mode, int hiddenValue, int visibleValue) {
Jeff Brown2e7760e2012-04-11 15:14:55 -07001263 if (mLidState != LID_ABSENT) {
Jeff Brownd04a88c2011-01-16 14:05:47 -08001264 switch (mode) {
1265 case 1:
Jeff Brown2e7760e2012-04-11 15:14:55 -07001266 return mLidState == LID_OPEN ? visibleValue : hiddenValue;
Jeff Brownd04a88c2011-01-16 14:05:47 -08001267 case 2:
Jeff Brown2e7760e2012-04-11 15:14:55 -07001268 return mLidState == LID_OPEN ? hiddenValue : visibleValue;
Jeff Brownd04a88c2011-01-16 14:05:47 -08001269 }
Dianne Hackborn2862fff2009-09-15 22:56:29 -07001270 }
1271 return visibleValue;
1272 }
Jeff Brownd04a88c2011-01-16 14:05:47 -08001273
Jeff Brownc458ce92012-04-30 14:58:40 -07001274 private boolean isKeyboardVisible() {
1275 return determineHiddenState(mLidKeyboardAccessibility, 0, 1) == 1
1276 || determineHiddenState(mLidNavigationAccessibility, 0, 1) == 1;
1277 }
1278
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001279 /** {@inheritDoc} */
1280 public void adjustConfigurationLw(Configuration config) {
1281 readLidState();
Jeff Brownc458ce92012-04-30 14:58:40 -07001282 applyLidSwitchState();
Jeff Brownd04a88c2011-01-16 14:05:47 -08001283
1284 if (config.keyboard == Configuration.KEYBOARD_NOKEYS) {
1285 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
1286 } else {
1287 config.hardKeyboardHidden = determineHiddenState(mLidKeyboardAccessibility,
1288 Configuration.HARDKEYBOARDHIDDEN_YES, Configuration.HARDKEYBOARDHIDDEN_NO);
1289 }
1290
1291 if (config.navigation == Configuration.NAVIGATION_NONAV) {
1292 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
1293 } else {
1294 config.navigationHidden = determineHiddenState(mLidNavigationAccessibility,
1295 Configuration.NAVIGATIONHIDDEN_YES, Configuration.NAVIGATIONHIDDEN_NO);
1296 }
1297
1298 if (mHasSoftInput || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
1299 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
1300 } else {
1301 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
1302 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001303 }
Jeff Brownd04a88c2011-01-16 14:05:47 -08001304
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001305 /** {@inheritDoc} */
1306 public int windowTypeToLayerLw(int type) {
1307 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
1308 return APPLICATION_LAYER;
1309 }
1310 switch (type) {
1311 case TYPE_STATUS_BAR:
1312 return STATUS_BAR_LAYER;
1313 case TYPE_STATUS_BAR_PANEL:
1314 return STATUS_BAR_PANEL_LAYER;
Joe Onorato29fc2c92010-11-24 10:26:50 -08001315 case TYPE_STATUS_BAR_SUB_PANEL:
1316 return STATUS_BAR_SUB_PANEL_LAYER;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -08001317 case TYPE_SYSTEM_DIALOG:
1318 return SYSTEM_DIALOG_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001319 case TYPE_SEARCH_BAR:
1320 return SEARCH_BAR_LAYER;
1321 case TYPE_PHONE:
1322 return PHONE_LAYER;
1323 case TYPE_KEYGUARD:
1324 return KEYGUARD_LAYER;
1325 case TYPE_KEYGUARD_DIALOG:
1326 return KEYGUARD_DIALOG_LAYER;
1327 case TYPE_SYSTEM_ALERT:
1328 return SYSTEM_ALERT_LAYER;
1329 case TYPE_SYSTEM_ERROR:
1330 return SYSTEM_ERROR_LAYER;
1331 case TYPE_INPUT_METHOD:
1332 return INPUT_METHOD_LAYER;
1333 case TYPE_INPUT_METHOD_DIALOG:
1334 return INPUT_METHOD_DIALOG_LAYER;
Dianne Hackborne8ecde12011-08-03 18:55:19 -07001335 case TYPE_VOLUME_OVERLAY:
1336 return VOLUME_OVERLAY_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001337 case TYPE_SYSTEM_OVERLAY:
1338 return SYSTEM_OVERLAY_LAYER;
Jeff Brown3b2b3542010-10-15 00:54:27 -07001339 case TYPE_SECURE_SYSTEM_OVERLAY:
1340 return SECURE_SYSTEM_OVERLAY_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001341 case TYPE_PRIORITY_PHONE:
1342 return PRIORITY_PHONE_LAYER;
1343 case TYPE_TOAST:
1344 return TOAST_LAYER;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -07001345 case TYPE_WALLPAPER:
1346 return WALLPAPER_LAYER;
Christopher Tatea53146c2010-09-07 11:57:52 -07001347 case TYPE_DRAG:
1348 return DRAG_LAYER;
Jeff Brown83c09682010-12-23 17:50:18 -08001349 case TYPE_POINTER:
1350 return POINTER_LAYER;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001351 case TYPE_NAVIGATION_BAR:
1352 return NAVIGATION_BAR_LAYER;
Jim Millere898ac52012-04-06 17:10:57 -07001353 case TYPE_NAVIGATION_BAR_PANEL:
1354 return NAVIGATION_BAR_PANEL_LAYER;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07001355 case TYPE_BOOT_PROGRESS:
1356 return BOOT_PROGRESS_LAYER;
Dianne Hackborndf89e652011-10-06 22:35:11 -07001357 case TYPE_HIDDEN_NAV_CONSUMER:
1358 return HIDDEN_NAV_CONSUMER_LAYER;
Daniel Sandler7d276c32012-01-30 14:33:52 -05001359 case TYPE_DREAM:
1360 return SCREENSAVER_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001361 }
1362 Log.e(TAG, "Unknown window type: " + type);
1363 return APPLICATION_LAYER;
1364 }
1365
1366 /** {@inheritDoc} */
1367 public int subWindowTypeToLayerLw(int type) {
1368 switch (type) {
1369 case TYPE_APPLICATION_PANEL:
1370 case TYPE_APPLICATION_ATTACHED_DIALOG:
1371 return APPLICATION_PANEL_SUBLAYER;
1372 case TYPE_APPLICATION_MEDIA:
1373 return APPLICATION_MEDIA_SUBLAYER;
Dianne Hackborn5cb8d792009-05-21 17:34:15 -07001374 case TYPE_APPLICATION_MEDIA_OVERLAY:
1375 return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001376 case TYPE_APPLICATION_SUB_PANEL:
1377 return APPLICATION_SUB_PANEL_SUBLAYER;
1378 }
1379 Log.e(TAG, "Unknown sub-window type: " + type);
1380 return 0;
1381 }
1382
Dianne Hackbornabe0da02009-09-18 01:55:39 -07001383 public int getMaxWallpaperLayer() {
1384 return STATUS_BAR_LAYER;
1385 }
1386
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001387 public boolean hasSystemNavBar() {
1388 return mHasSystemNavBar;
Dianne Hackborn81e56d52011-05-26 00:55:58 -07001389 }
1390
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001391 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
Dianne Hackborn077ee852012-04-09 16:27:07 -07001392 if (mHasNavigationBar) {
1393 // For a basic navigation bar, when we are in landscape mode we place
1394 // the navigation bar to the side.
Daniel Sandler4a066c52012-04-20 14:49:13 -04001395 if (mNavigationBarCanMove && fullWidth > fullHeight) {
1396 return fullWidth - mNavigationBarWidthForRotation[rotation];
Dianne Hackborn077ee852012-04-09 16:27:07 -07001397 }
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001398 }
1399 return fullWidth;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001400 }
1401
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001402 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
Dianne Hackborn077ee852012-04-09 16:27:07 -07001403 if (mHasSystemNavBar) {
1404 // For the system navigation bar, we always place it at the bottom.
Daniel Sandler4a066c52012-04-20 14:49:13 -04001405 return fullHeight - mNavigationBarHeightForRotation[rotation];
Dianne Hackborn077ee852012-04-09 16:27:07 -07001406 }
1407 if (mHasNavigationBar) {
1408 // For a basic navigation bar, when we are in portrait mode we place
1409 // the navigation bar to the bottom.
Daniel Sandler4a066c52012-04-20 14:49:13 -04001410 if (!mNavigationBarCanMove || fullWidth < fullHeight) {
1411 return fullHeight - mNavigationBarHeightForRotation[rotation];
Dianne Hackborn077ee852012-04-09 16:27:07 -07001412 }
1413 }
1414 return fullHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001415 }
1416
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001417 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
1418 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation);
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001419 }
1420
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001421 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) {
Dianne Hackborn077ee852012-04-09 16:27:07 -07001422 // If we don't have a system nav bar, then there is a separate status
1423 // bar at the top of the display. We don't count that as part of the
1424 // fixed decor, since it can hide; however, for purposes of configurations,
1425 // we do want to exclude it since applications can't generally use that part
1426 // of the screen.
1427 if (!mHasSystemNavBar) {
1428 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) - mStatusBarHeight;
1429 }
1430 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001431 }
1432
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001433 public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
1434 return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
1435 }
1436
1437 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
1438 return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001439 && attrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001440 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
1441 }
1442
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001443 /** {@inheritDoc} */
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001444 public View addStartingWindow(IBinder appToken, String packageName, int theme,
1445 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
1446 int icon, int windowFlags) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001447 if (!SHOW_STARTING_ANIMATIONS) {
1448 return null;
1449 }
1450 if (packageName == null) {
1451 return null;
1452 }
1453
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001454 try {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001455 Context context = mContext;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001456 //Log.i(TAG, "addStartingWindow " + packageName + ": nonLocalizedLabel="
1457 // + nonLocalizedLabel + " theme=" + Integer.toHexString(theme));
Dianne Hackborn247fe742011-01-08 17:25:57 -08001458 if (theme != context.getThemeResId() || labelRes != 0) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001459 try {
1460 context = context.createPackageContext(packageName, 0);
Dianne Hackborn247fe742011-01-08 17:25:57 -08001461 context.setTheme(theme);
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001462 } catch (PackageManager.NameNotFoundException e) {
1463 // Ignore
1464 }
1465 }
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001466
1467 Window win = PolicyManager.makeNewWindow(context);
1468 if (win.getWindowStyle().getBoolean(
1469 com.android.internal.R.styleable.Window_windowDisablePreview, false)) {
1470 return null;
1471 }
1472
1473 Resources r = context.getResources();
1474 win.setTitle(r.getText(labelRes, nonLocalizedLabel));
1475
1476 win.setType(
1477 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
1478 // Force the window flags: this is a fake window, so it is not really
1479 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
1480 // flag because we do know that the next window will take input
1481 // focus, so we want to get the IME window up on top of us right away.
1482 win.setFlags(
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001483 windowFlags|
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001484 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
1485 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
1486 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001487 windowFlags|
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001488 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
1489 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
1490 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
1491
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001492 if (!compatInfo.supportsScreen()) {
1493 win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW);
1494 }
1495
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001496 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001497 WindowManager.LayoutParams.MATCH_PARENT);
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001498
1499 final WindowManager.LayoutParams params = win.getAttributes();
1500 params.token = appToken;
1501 params.packageName = packageName;
1502 params.windowAnimations = win.getWindowStyle().getResourceId(
1503 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
Dianne Hackborn5d927c22011-09-02 12:22:18 -07001504 params.privateFlags |=
1505 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001506 params.setTitle("Starting " + packageName);
1507
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001508 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001509 View view = win.getDecorView();
1510
1511 if (win.isFloating()) {
1512 // Whoops, there is no way to display an animation/preview
1513 // of such a thing! After all that work... let's skip it.
1514 // (Note that we must do this here because it is in
1515 // getDecorView() where the theme is evaluated... maybe
1516 // we should peek the floating attribute from the theme
1517 // earlier.)
1518 return null;
1519 }
1520
1521 if (localLOGV) Log.v(
1522 TAG, "Adding starting window for " + packageName
1523 + " / " + appToken + ": "
1524 + (view.getParent() != null ? view : null));
1525
1526 wm.addView(view, params);
1527
1528 // Only return the view if it was successfully added to the
1529 // window manager... which we can tell by it having a parent.
1530 return view.getParent() != null ? view : null;
1531 } catch (WindowManagerImpl.BadTokenException e) {
1532 // ignore
1533 Log.w(TAG, appToken + " already running, starting window not displayed");
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001534 } catch (RuntimeException e) {
1535 // don't crash if something else bad happens, for example a
1536 // failure loading resources because we are loading from an app
1537 // on external storage that has been unmounted.
1538 Log.w(TAG, appToken + " failed creating starting window", e);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001539 }
1540
1541 return null;
1542 }
1543
1544 /** {@inheritDoc} */
1545 public void removeStartingWindow(IBinder appToken, View window) {
1546 // RuntimeException e = new RuntimeException();
1547 // Log.i(TAG, "remove " + appToken + " " + window, e);
1548
1549 if (localLOGV) Log.v(
1550 TAG, "Removing starting window for " + appToken + ": " + window);
1551
1552 if (window != null) {
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001553 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001554 wm.removeView(window);
1555 }
1556 }
1557
1558 /**
1559 * Preflight adding a window to the system.
1560 *
1561 * Currently enforces that three window types are singletons:
1562 * <ul>
1563 * <li>STATUS_BAR_TYPE</li>
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001564 * <li>KEYGUARD_TYPE</li>
1565 * </ul>
1566 *
1567 * @param win The window to be added
1568 * @param attrs Information about the window to be added
1569 *
1570 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON
1571 */
1572 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
1573 switch (attrs.type) {
1574 case TYPE_STATUS_BAR:
Joe Onorato8bc6c512010-06-04 16:21:12 -04001575 mContext.enforceCallingOrSelfPermission(
1576 android.Manifest.permission.STATUS_BAR_SERVICE,
1577 "PhoneWindowManager");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001578 if (mStatusBar != null) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001579 if (mStatusBar.isAlive()) {
1580 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1581 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001582 }
1583 mStatusBar = win;
1584 break;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001585 case TYPE_NAVIGATION_BAR:
1586 mContext.enforceCallingOrSelfPermission(
1587 android.Manifest.permission.STATUS_BAR_SERVICE,
1588 "PhoneWindowManager");
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001589 if (mNavigationBar != null) {
1590 if (mNavigationBar.isAlive()) {
1591 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1592 }
1593 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001594 mNavigationBar = win;
1595 if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
1596 break;
Jim Millere898ac52012-04-06 17:10:57 -07001597 case TYPE_NAVIGATION_BAR_PANEL:
1598 mContext.enforceCallingOrSelfPermission(
1599 android.Manifest.permission.STATUS_BAR_SERVICE,
1600 "PhoneWindowManager");
1601 break;
Dianne Hackborn08743722009-12-21 12:16:51 -08001602 case TYPE_STATUS_BAR_PANEL:
Joe Onorato8bc6c512010-06-04 16:21:12 -04001603 mContext.enforceCallingOrSelfPermission(
1604 android.Manifest.permission.STATUS_BAR_SERVICE,
1605 "PhoneWindowManager");
Dianne Hackborn08743722009-12-21 12:16:51 -08001606 break;
Joe Onorato29fc2c92010-11-24 10:26:50 -08001607 case TYPE_STATUS_BAR_SUB_PANEL:
1608 mContext.enforceCallingOrSelfPermission(
1609 android.Manifest.permission.STATUS_BAR_SERVICE,
1610 "PhoneWindowManager");
Joe Onorato29fc2c92010-11-24 10:26:50 -08001611 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001612 case TYPE_KEYGUARD:
1613 if (mKeyguard != null) {
1614 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1615 }
1616 mKeyguard = win;
1617 break;
1618 }
1619 return WindowManagerImpl.ADD_OKAY;
1620 }
1621
1622 /** {@inheritDoc} */
1623 public void removeWindowLw(WindowState win) {
1624 if (mStatusBar == win) {
1625 mStatusBar = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001626 } else if (mKeyguard == win) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001627 mKeyguard = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001628 } else if (mNavigationBar == win) {
1629 mNavigationBar = null;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001630 }
1631 }
1632
1633 static final boolean PRINT_ANIM = false;
1634
1635 /** {@inheritDoc} */
1636 public int selectAnimationLw(WindowState win, int transit) {
1637 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
1638 + ": transit=" + transit);
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001639 if (win == mStatusBar) {
1640 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1641 return R.anim.dock_top_exit;
1642 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1643 return R.anim.dock_top_enter;
1644 }
1645 } else if (win == mNavigationBar) {
1646 // This can be on either the bottom or the right.
1647 if (mNavigationBarOnBottom) {
1648 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1649 return R.anim.dock_bottom_exit;
1650 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1651 return R.anim.dock_bottom_enter;
1652 }
1653 } else {
1654 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1655 return R.anim.dock_right_exit;
1656 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1657 return R.anim.dock_right_enter;
1658 }
1659 }
1660 } if (transit == TRANSIT_PREVIEW_DONE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001661 if (win.hasAppShownWindows()) {
1662 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
1663 return com.android.internal.R.anim.app_starting_exit;
1664 }
1665 }
1666
1667 return 0;
1668 }
1669
Dianne Hackborn0c2acff2012-04-12 15:17:07 -07001670 public Animation createForceHideEnterAnimation(boolean onWallpaper) {
1671 return AnimationUtils.loadAnimation(mContext, onWallpaper
1672 ? com.android.internal.R.anim.lock_screen_wallpaper_behind_enter
1673 : com.android.internal.R.anim.lock_screen_behind_enter);
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001674 }
1675
Jeff Brown4d396052010-10-29 21:50:21 -07001676 static ITelephony getTelephonyService() {
Mike Lockwoodf5f4ec92011-11-08 14:05:31 -08001677 return ITelephony.Stub.asInterface(
Jeff Brown4d396052010-10-29 21:50:21 -07001678 ServiceManager.checkService(Context.TELEPHONY_SERVICE));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001679 }
1680
Jeff Brown4d396052010-10-29 21:50:21 -07001681 static IAudioService getAudioService() {
1682 IAudioService audioService = IAudioService.Stub.asInterface(
1683 ServiceManager.checkService(Context.AUDIO_SERVICE));
1684 if (audioService == null) {
1685 Log.w(TAG, "Unable to find IAudioService interface.");
1686 }
1687 return audioService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001688 }
1689
1690 boolean keyguardOn() {
1691 return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
1692 }
1693
1694 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
1695 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
1696 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
1697 };
1698
1699 /** {@inheritDoc} */
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001700 @Override
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001701 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001702 final boolean keyguardOn = keyguardOn();
Jeff Brown1f245102010-11-18 20:53:46 -08001703 final int keyCode = event.getKeyCode();
1704 final int repeatCount = event.getRepeatCount();
1705 final int metaState = event.getMetaState();
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001706 final int flags = event.getFlags();
Jeff Brown1f245102010-11-18 20:53:46 -08001707 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
1708 final boolean canceled = event.isCanceled();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001709
1710 if (false) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001711 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001712 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
1713 }
1714
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001715 // If we think we might have a volume down & power key chord on the way
1716 // but we're not sure, then tell the dispatcher to wait a little while and
1717 // try again later before dispatching.
Christopher Tatee90585f2012-03-05 18:56:25 -08001718 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001719 if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
1720 final long now = SystemClock.uptimeMillis();
1721 final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
1722 if (now < timeoutTime) {
1723 return timeoutTime - now;
1724 }
1725 }
1726 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
1727 && mVolumeDownKeyConsumedByScreenshotChord) {
1728 if (!down) {
1729 mVolumeDownKeyConsumedByScreenshotChord = false;
1730 }
1731 return -1;
1732 }
1733 }
1734
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001735 // First we always handle the home key here, so applications
1736 // can never break it, although if keyguard is on, we do let
1737 // it handle it, because that gives us the correct 5 second
1738 // timeout.
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001739 if (keyCode == KeyEvent.KEYCODE_HOME) {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001740
Jeff Brown49ed71d2010-12-06 17:13:33 -08001741 // If we have released the home key, and didn't do anything else
1742 // while it was pressed, then it is time to go home!
Michael Jurka7f2668c2012-03-27 07:49:52 -07001743 if (!down) {
1744 final boolean homeWasLongPressed = mHomeLongPressed;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001745 mHomePressed = false;
Michael Jurka7f2668c2012-03-27 07:49:52 -07001746 mHomeLongPressed = false;
1747 if (!homeWasLongPressed) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001748 try {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001749 mStatusBarService.cancelPreloadRecentApps();
1750 } catch (RemoteException e) {
1751 Slog.e(TAG, "RemoteException when showing recent apps", e);
Jeff Brown49ed71d2010-12-06 17:13:33 -08001752 }
1753
Michael Jurka7f2668c2012-03-27 07:49:52 -07001754 mHomePressed = false;
1755 if (!canceled) {
1756 // If an incoming call is ringing, HOME is totally disabled.
1757 // (The user is already on the InCallScreen at this point,
1758 // and his ONLY options are to answer or reject the call.)
1759 boolean incomingRinging = false;
1760 try {
1761 ITelephony telephonyService = getTelephonyService();
1762 if (telephonyService != null) {
1763 incomingRinging = telephonyService.isRinging();
1764 }
1765 } catch (RemoteException ex) {
1766 Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
1767 }
1768
1769 if (incomingRinging) {
1770 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
1771 } else {
1772 launchHomeFromHotKey();
1773 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001774 } else {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001775 Log.i(TAG, "Ignoring HOME; event canceled.");
Jeff Brown49ed71d2010-12-06 17:13:33 -08001776 }
Michael Jurka7f2668c2012-03-27 07:49:52 -07001777 return -1;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001778 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001779 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001780
1781 // If a system window has focus, then it doesn't make sense
1782 // right now to interact with applications.
1783 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
1784 if (attrs != null) {
1785 final int type = attrs.type;
1786 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
1787 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
1788 // the "app" is keyguard, so give it the key
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001789 return 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001790 }
1791 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
1792 for (int i=0; i<typeCount; i++) {
1793 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
1794 // don't do anything, but also don't pass it to the app
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001795 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001796 }
1797 }
1798 }
Jeff Brown98392ef2011-09-12 18:24:59 -07001799 if (down) {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001800 if (!mHomePressed) {
1801 try {
1802 mStatusBarService.preloadRecentApps();
1803 } catch (RemoteException e) {
1804 Slog.e(TAG, "RemoteException when preloading recent apps", e);
1805 }
1806 }
Jeff Brown98392ef2011-09-12 18:24:59 -07001807 if (repeatCount == 0) {
1808 mHomePressed = true;
1809 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
1810 if (!keyguardOn) {
1811 handleLongPressOnHome();
1812 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001813 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001814 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001815 return -1;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001816 } else if (keyCode == KeyEvent.KEYCODE_MENU) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001817 // Hijack modified menu keys for debugging features
1818 final int chordBug = KeyEvent.META_SHIFT_ON;
1819
1820 if (down && repeatCount == 0) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001821 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001822 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
1823 mContext.sendOrderedBroadcast(intent, null);
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001824 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001825 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001826 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001827 Intent service = new Intent();
1828 service.setClassName(mContext, "com.android.server.LoadAverageService");
1829 ContentResolver res = mContext.getContentResolver();
1830 boolean shown = Settings.System.getInt(
1831 res, Settings.System.SHOW_PROCESSES, 0) != 0;
1832 if (!shown) {
1833 mContext.startService(service);
1834 } else {
1835 mContext.stopService(service);
1836 }
1837 Settings.System.putInt(
1838 res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001839 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001840 }
1841 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001842 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001843 if (down) {
1844 if (repeatCount == 0) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001845 mShortcutKeyPressed = keyCode;
1846 mConsumeShortcutKeyUp = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001847 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001848 } else if (keyCode == mShortcutKeyPressed) {
1849 mShortcutKeyPressed = -1;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001850 if (mConsumeShortcutKeyUp) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001851 mConsumeShortcutKeyUp = false;
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001852 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001853 }
1854 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001855 return 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001856 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
Jeff Brownda3d5a92011-03-29 15:11:34 -07001857 if (down && repeatCount == 0) {
Jeff Brown68b909d2011-12-07 16:36:01 -08001858 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
Jeff Brown49ed71d2010-12-06 17:13:33 -08001859 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001860 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001861 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001862
Jeff Brownc1fb48d2010-12-08 16:52:09 -08001863 // Shortcuts are invoked through Search+key, so intercept those here
Jeff Browncaab4d02010-12-09 22:13:41 -08001864 // Any printing key that is chorded with Search should be consumed
1865 // even if no shortcut was invoked. This prevents text from being
1866 // inadvertently inserted when using a keyboard that has built-in macro
1867 // shortcut keys (that emit Search+x) and some of them are not registered.
1868 if (mShortcutKeyPressed != -1) {
1869 final KeyCharacterMap kcm = event.getKeyCharacterMap();
1870 if (kcm.isPrintingKey(keyCode)) {
1871 mConsumeShortcutKeyUp = true;
1872 if (down && repeatCount == 0 && !keyguardOn) {
1873 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
1874 if (shortcutIntent != null) {
1875 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Jeff Brownf0a3cc52011-01-26 18:42:46 -08001876 try {
1877 mContext.startActivity(shortcutIntent);
1878 } catch (ActivityNotFoundException ex) {
1879 Slog.w(TAG, "Dropping shortcut key combination because "
1880 + "the activity to which it is registered was not found: "
1881 + KeyEvent.keyCodeToString(mShortcutKeyPressed)
1882 + "+" + KeyEvent.keyCodeToString(keyCode), ex);
1883 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001884 } else {
1885 Slog.i(TAG, "Dropping unregistered shortcut key combination: "
1886 + KeyEvent.keyCodeToString(mShortcutKeyPressed)
1887 + "+" + KeyEvent.keyCodeToString(keyCode));
Jeff Brown49ed71d2010-12-06 17:13:33 -08001888 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001889 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001890 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001891 }
1892 }
1893
Jeff Brown68b909d2011-12-07 16:36:01 -08001894 // Invoke shortcuts using Meta.
1895 if (down && repeatCount == 0
1896 && (metaState & KeyEvent.META_META_ON) != 0) {
1897 final KeyCharacterMap kcm = event.getKeyCharacterMap();
1898 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
1899 metaState & ~(KeyEvent.META_META_ON
1900 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
1901 if (shortcutIntent != null) {
1902 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1903 try {
1904 mContext.startActivity(shortcutIntent);
1905 } catch (ActivityNotFoundException ex) {
1906 Slog.w(TAG, "Dropping shortcut key combination because "
1907 + "the activity to which it is registered was not found: "
1908 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
1909 }
1910 return -1;
1911 }
1912 }
1913
Jeff Brown6651a632011-11-28 12:59:11 -08001914 // Handle application launch keys.
1915 if (down && repeatCount == 0) {
1916 String category = sApplicationLaunchKeyCategories.get(keyCode);
1917 if (category != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -08001918 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
Jeff Brown6651a632011-11-28 12:59:11 -08001919 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1920 try {
1921 mContext.startActivity(intent);
1922 } catch (ActivityNotFoundException ex) {
1923 Slog.w(TAG, "Dropping application launch key because "
1924 + "the activity to which it is registered was not found: "
1925 + "keyCode=" + keyCode + ", category=" + category, ex);
1926 }
Jeff Brown68b909d2011-12-07 16:36:01 -08001927 return -1;
Jeff Brown6651a632011-11-28 12:59:11 -08001928 }
1929 }
1930
Jeff Brown68b909d2011-12-07 16:36:01 -08001931 // Display task switcher for ALT-TAB or Meta-TAB.
1932 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
1933 if (mRecentAppsDialogHeldModifiers == 0) {
1934 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
1935 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
1936 || KeyEvent.metaStateHasModifiers(
1937 shiftlessModifiers, KeyEvent.META_META_ON)) {
1938 mRecentAppsDialogHeldModifiers = shiftlessModifiers;
1939 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);
1940 return -1;
1941 }
1942 }
1943 } else if (!down && mRecentAppsDialogHeldModifiers != 0
1944 && (metaState & mRecentAppsDialogHeldModifiers) == 0) {
1945 mRecentAppsDialogHeldModifiers = 0;
1946 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);
1947 }
1948
1949 // Let the application handle the key.
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001950 return 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001951 }
1952
Jeff Brown3915bb82010-11-05 15:02:16 -07001953 /** {@inheritDoc} */
1954 @Override
Jeff Brown49ed71d2010-12-06 17:13:33 -08001955 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
Jeff Brown54875002011-04-06 15:33:01 -07001956 // Note: This method is only called if the initial down was unhandled.
Jeff Brown49ed71d2010-12-06 17:13:33 -08001957 if (DEBUG_FALLBACK) {
Jeff Brown1f245102010-11-18 20:53:46 -08001958 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
1959 + ", flags=" + event.getFlags()
1960 + ", keyCode=" + event.getKeyCode()
1961 + ", scanCode=" + event.getScanCode()
1962 + ", metaState=" + event.getMetaState()
1963 + ", repeatCount=" + event.getRepeatCount()
1964 + ", policyFlags=" + policyFlags);
Jeff Brown3915bb82010-11-05 15:02:16 -07001965 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001966
1967 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1968 final KeyCharacterMap kcm = event.getKeyCharacterMap();
Jeff Brownc1fb48d2010-12-08 16:52:09 -08001969 final int keyCode = event.getKeyCode();
1970 final int metaState = event.getMetaState();
Jeff Brown49ed71d2010-12-06 17:13:33 -08001971
Jeff Brown54875002011-04-06 15:33:01 -07001972 // Check for fallback actions specified by the key character map.
Jeff Brown6f2fba42011-02-19 01:08:02 -08001973 if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001974 if (DEBUG_FALLBACK) {
1975 Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
1976 + " metaState=" + Integer.toHexString(mFallbackAction.metaState));
1977 }
1978
1979 int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
1980 KeyEvent fallbackEvent = KeyEvent.obtain(
1981 event.getDownTime(), event.getEventTime(),
1982 event.getAction(), mFallbackAction.keyCode,
1983 event.getRepeatCount(), mFallbackAction.metaState,
1984 event.getDeviceId(), event.getScanCode(),
1985 flags, event.getSource(), null);
1986 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
1987 if ((actions & ACTION_PASS_TO_USER) != 0) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001988 long delayMillis = interceptKeyBeforeDispatching(
1989 win, fallbackEvent, policyFlags);
1990 if (delayMillis == 0) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001991 if (DEBUG_FALLBACK) {
1992 Slog.d(TAG, "Performing fallback.");
1993 }
1994 return fallbackEvent;
1995 }
1996 }
1997 fallbackEvent.recycle();
1998 }
1999 }
2000
2001 if (DEBUG_FALLBACK) {
2002 Slog.d(TAG, "No fallback.");
2003 }
2004 return null;
Jeff Brown3915bb82010-11-05 15:02:16 -07002005 }
2006
Jeff Brown6f2fba42011-02-19 01:08:02 -08002007 private boolean getFallbackAction(KeyCharacterMap kcm, int keyCode, int metaState,
2008 FallbackAction outFallbackAction) {
2009 // Consult the key character map for specific fallback actions.
2010 // For example, map NUMPAD_1 to MOVE_HOME when NUMLOCK is not pressed.
Jeff Browncc0c1592011-02-19 05:07:28 -08002011 return kcm.getFallbackAction(keyCode, metaState, outFallbackAction);
Jeff Brown6f2fba42011-02-19 01:08:02 -08002012 }
2013
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002014 /**
2015 * A home key -> launch home action was detected. Take the appropriate action
2016 * given the situation with the keyguard.
2017 */
2018 void launchHomeFromHotKey() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002019 if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002020 // don't launch home if keyguard showing
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002021 } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002022 // when in keyguard restricted mode, must first verify unlock
2023 // before launching home
2024 mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
2025 public void onKeyguardExitResult(boolean success) {
2026 if (success) {
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07002027 try {
2028 ActivityManagerNative.getDefault().stopAppSwitches();
2029 } catch (RemoteException e) {
2030 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05002031 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002032 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002033 }
2034 }
2035 });
2036 } else {
2037 // no keyguard stuff to worry about, just launch home!
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07002038 try {
2039 ActivityManagerNative.getDefault().stopAppSwitches();
2040 } catch (RemoteException e) {
2041 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05002042 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002043 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002044 }
2045 }
2046
Dianne Hackborne26ab702011-10-16 13:21:33 -07002047 /**
2048 * A delayed callback use to determine when it is okay to re-allow applications
2049 * to use certain system UI flags. This is used to prevent applications from
2050 * spamming system UI changes that prevent the navigation bar from being shown.
2051 */
2052 final Runnable mAllowSystemUiDelay = new Runnable() {
2053 @Override public void run() {
2054 }
2055 };
2056
2057 /**
2058 * Input handler used while nav bar is hidden. Captures any touch on the screen,
2059 * to determine when the nav bar should be shown and prevent applications from
2060 * receiving those touches.
2061 */
Jeff Brown32cbc38552011-12-01 14:01:49 -08002062 final class HideNavInputEventReceiver extends InputEventReceiver {
2063 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
2064 super(inputChannel, looper);
2065 }
2066
Dianne Hackborndf89e652011-10-06 22:35:11 -07002067 @Override
Jeff Brown32cbc38552011-12-01 14:01:49 -08002068 public void onInputEvent(InputEvent event) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002069 boolean handled = false;
2070 try {
Jeff Brown4952dfd2011-11-30 19:23:22 -08002071 if (event instanceof MotionEvent
2072 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
2073 final MotionEvent motionEvent = (MotionEvent)event;
2074 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002075 // When the user taps down, we re-show the nav bar.
2076 boolean changed = false;
2077 synchronized (mLock) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002078 // Any user activity always causes us to show the
2079 // navigation controls, if they had been hidden.
2080 // We also clear the low profile and only content
2081 // flags so that tapping on the screen will atomically
2082 // restore all currently hidden screen decorations.
2083 int newVal = mResettingSystemUiFlags |
2084 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
2085 View.SYSTEM_UI_FLAG_LOW_PROFILE |
2086 View.SYSTEM_UI_FLAG_FULLSCREEN;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002087 if (mResettingSystemUiFlags != newVal) {
2088 mResettingSystemUiFlags = newVal;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002089 changed = true;
2090 }
Dianne Hackborne26ab702011-10-16 13:21:33 -07002091 // We don't allow the system's nav bar to be hidden
2092 // again for 1 second, to prevent applications from
2093 // spamming us and keeping it from being shown.
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002094 newVal = mForceClearedSystemUiFlags |
2095 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002096 if (mForceClearedSystemUiFlags != newVal) {
2097 mForceClearedSystemUiFlags = newVal;
2098 changed = true;
2099 mHandler.postDelayed(new Runnable() {
2100 @Override public void run() {
2101 synchronized (mLock) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002102 // Clear flags.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002103 mForceClearedSystemUiFlags &=
2104 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
2105 }
2106 mWindowManagerFuncs.reevaluateStatusBarVisibility();
2107 }
2108 }, 1000);
2109 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07002110 }
2111 if (changed) {
2112 mWindowManagerFuncs.reevaluateStatusBarVisibility();
2113 }
2114 }
2115 }
2116 } finally {
Jeff Brown32cbc38552011-12-01 14:01:49 -08002117 finishInputEvent(event, handled);
Dianne Hackborndf89e652011-10-06 22:35:11 -07002118 }
2119 }
Jeff Brown32cbc38552011-12-01 14:01:49 -08002120 }
2121 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
2122 new InputEventReceiver.Factory() {
2123 @Override
2124 public InputEventReceiver createInputEventReceiver(
2125 InputChannel inputChannel, Looper looper) {
2126 return new HideNavInputEventReceiver(inputChannel, looper);
2127 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07002128 };
2129
2130 @Override
2131 public int adjustSystemUiVisibilityLw(int visibility) {
2132 // Reset any bits in mForceClearingStatusBarVisibility that
2133 // are now clear.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002134 mResettingSystemUiFlags &= visibility;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002135 // Clear any bits in the new visibility that are currently being
2136 // force cleared, before reporting it.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002137 return visibility & ~mResettingSystemUiFlags
2138 & ~mForceClearedSystemUiFlags;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002139 }
2140
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002141 public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
2142 final int fl = attrs.flags;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002143
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07002144 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002145 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002146 int availRight, availBottom;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002147 if (mCanHideNavigationBar &&
2148 (attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002149 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
2150 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
2151 } else {
2152 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
2153 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
2154 }
2155 if ((attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2156 contentInset.set(mStableLeft, mStableTop,
2157 availRight - mStableRight, availBottom - mStableBottom);
2158 } else if ((attrs.systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
2159 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
2160 contentInset.set(mCurLeft, mCurTop,
2161 availRight - mCurRight, availBottom - mCurBottom);
2162 } else {
2163 contentInset.set(mCurLeft, mCurTop,
2164 availRight - mCurRight, availBottom - mCurBottom);
2165 }
2166 return;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002167 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002168 contentInset.setEmpty();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002169 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002170
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002171 /** {@inheritDoc} */
Dianne Hackborn1f903c32011-09-13 19:18:06 -07002172 public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation) {
Joe Onorato29fc2c92010-11-24 10:26:50 -08002173 mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
2174 mUnrestrictedScreenWidth = displayWidth;
2175 mUnrestrictedScreenHeight = displayHeight;
2176 mRestrictedScreenLeft = mRestrictedScreenTop = 0;
2177 mRestrictedScreenWidth = displayWidth;
2178 mRestrictedScreenHeight = displayHeight;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002179 mDockLeft = mContentLeft = mStableLeft = mCurLeft = 0;
2180 mDockTop = mContentTop = mStableTop = mCurTop = 0;
2181 mDockRight = mContentRight = mStableRight = mCurRight = displayWidth;
2182 mDockBottom = mContentBottom = mStableBottom = mCurBottom = displayHeight;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002183 mDockLayer = 0x10000000;
2184
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002185 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
2186 final Rect pf = mTmpParentFrame;
2187 final Rect df = mTmpDisplayFrame;
2188 final Rect vf = mTmpVisibleFrame;
2189 pf.left = df.left = vf.left = mDockLeft;
2190 pf.top = df.top = vf.top = mDockTop;
2191 pf.right = df.right = vf.right = mDockRight;
2192 pf.bottom = df.bottom = vf.bottom = mDockBottom;
2193
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002194 // For purposes of putting out fake window up to steal focus, we will
2195 // drive nav being hidden only by whether it is requested.
2196 boolean navVisible = (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002197
2198 // When the navigation bar isn't visible, we put up a fake
2199 // input window to catch all touch events. This way we can
2200 // detect when the user presses anywhere to bring back the nav
2201 // bar and ensure the application doesn't see the event.
2202 if (navVisible) {
2203 if (mHideNavFakeWindow != null) {
2204 mHideNavFakeWindow.dismiss();
2205 mHideNavFakeWindow = null;
2206 }
2207 } else if (mHideNavFakeWindow == null) {
2208 mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
Jeff Brown32cbc38552011-12-01 14:01:49 -08002209 mHandler.getLooper(), mHideNavInputEventReceiverFactory,
Dianne Hackborne26ab702011-10-16 13:21:33 -07002210 "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
2211 0, false, false, true);
2212 }
2213
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002214 // For purposes of positioning and showing the nav bar, if we have
2215 // decided that it can't be hidden (because of the screen aspect ratio),
2216 // then take that into account.
2217 navVisible |= !mCanHideNavigationBar;
2218
2219 if (mNavigationBar != null) {
2220 // Force the navigation bar to its appropriate place and
2221 // size. We need to do this directly, instead of relying on
2222 // it to bubble up from the nav bar, because this needs to
2223 // change atomically with screen rotations.
Daniel Sandler4a066c52012-04-20 14:49:13 -04002224 mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002225 if (mNavigationBarOnBottom) {
2226 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
Daniel Sandler4a066c52012-04-20 14:49:13 -04002227 int top = displayHeight - mNavigationBarHeightForRotation[displayRotation];
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002228 if (mHdmiPlugged) {
2229 if (top > mExternalDisplayHeight) {
2230 top = mExternalDisplayHeight;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002231 }
2232 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002233 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
2234 mStableBottom = mTmpNavigationFrame.top;
2235 if (navVisible) {
2236 mNavigationBar.showLw(true);
2237 mDockBottom = mTmpNavigationFrame.top;
2238 mRestrictedScreenHeight = mDockBottom - mDockTop;
2239 } else {
2240 // We currently want to hide the navigation UI.
2241 mNavigationBar.hideLw(true);
2242 }
2243 } else {
2244 // Landscape screen; nav bar goes to the right.
Daniel Sandler4a066c52012-04-20 14:49:13 -04002245 int left = displayWidth - mNavigationBarWidthForRotation[displayRotation];
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002246 if (mHdmiPlugged) {
2247 if (left > mExternalDisplayWidth) {
2248 left = mExternalDisplayWidth;
2249 }
2250 }
2251 mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight);
2252 mStableRight = mTmpNavigationFrame.left;
2253 if (navVisible) {
2254 mNavigationBar.showLw(true);
2255 mDockRight = mTmpNavigationFrame.left;
2256 mRestrictedScreenWidth = mDockRight - mDockLeft;
2257 } else {
2258 // We currently want to hide the navigation UI.
2259 mNavigationBar.hideLw(true);
2260 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002261 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002262 // Make sure the content and current rectangles are updated to
2263 // account for the restrictions from the navigation bar.
2264 mContentTop = mCurTop = mDockTop;
2265 mContentBottom = mCurBottom = mDockBottom;
2266 mContentLeft = mCurLeft = mDockLeft;
2267 mContentRight = mCurRight = mDockRight;
2268 // And compute the final frame.
2269 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
2270 mTmpNavigationFrame, mTmpNavigationFrame);
2271 if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
2272 }
2273 if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
2274 mDockLeft, mDockTop, mDockRight, mDockBottom));
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002275
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002276 // decide where the status bar goes ahead of time
2277 if (mStatusBar != null) {
2278 // apply any navigation bar insets
Dianne Hackborn98014352012-04-05 18:31:41 -07002279 pf.left = df.left = mUnrestrictedScreenLeft;
2280 pf.top = df.top = mUnrestrictedScreenTop;
2281 pf.right = df.right = mUnrestrictedScreenWidth - mUnrestrictedScreenLeft;
2282 pf.bottom = df.bottom = mUnrestrictedScreenHeight - mUnrestrictedScreenTop;
2283 vf.left = mStableLeft;
2284 vf.top = mStableTop;
2285 vf.right = mStableRight;
2286 vf.bottom = mStableBottom;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002287
Dianne Hackbornde368ff2012-04-10 18:35:54 -07002288 // Let the status bar determine its size.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002289 mStatusBar.computeFrameLw(pf, df, vf, vf);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002290
Dianne Hackbornde368ff2012-04-10 18:35:54 -07002291 // For layout, the status bar is always at the top with our fixed height.
2292 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002293
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002294 // If the status bar is hidden, we don't want to cause
2295 // windows behind it to scroll.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002296 if (mStatusBar.isVisibleLw()) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002297 // Status bar may go away, so the screen area it occupies
2298 // is available to apps but just covering them when the
2299 // status bar is visible.
Dianne Hackbornde368ff2012-04-10 18:35:54 -07002300 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002301
2302 mContentTop = mCurTop = mDockTop;
2303 mContentBottom = mCurBottom = mDockBottom;
2304 mContentLeft = mCurLeft = mDockLeft;
2305 mContentRight = mCurRight = mDockRight;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002306
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002307 if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
2308 String.format(
2309 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
2310 mDockLeft, mDockTop, mDockRight, mDockBottom,
2311 mContentLeft, mContentTop, mContentRight, mContentBottom,
2312 mCurLeft, mCurTop, mCurRight, mCurBottom));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002313 }
2314 }
2315 }
2316
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002317 void setAttachedWindowFrames(WindowState win, int fl, int adjust,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002318 WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
2319 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
2320 // Here's a special case: if this attached window is a panel that is
2321 // above the dock window, and the window it is attached to is below
2322 // the dock window, then the frames we computed for the window it is
2323 // attached to can not be used because the dock is effectively part
2324 // of the underlying window and the attached window is floating on top
2325 // of the whole thing. So, we ignore the attached window and explicitly
2326 // compute the frames that would be appropriate without the dock.
2327 df.left = cf.left = vf.left = mDockLeft;
2328 df.top = cf.top = vf.top = mDockTop;
2329 df.right = cf.right = vf.right = mDockRight;
2330 df.bottom = cf.bottom = vf.bottom = mDockBottom;
2331 } else {
2332 // The effective display frame of the attached window depends on
2333 // whether it is taking care of insetting its content. If not,
2334 // we need to use the parent's content frame so that the entire
2335 // window is positioned within that content. Otherwise we can use
2336 // the display frame and let the attached window take care of
2337 // positioning its content appropriately.
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002338 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002339 cf.set(attached.getDisplayFrameLw());
2340 } else {
2341 // If the window is resizing, then we want to base the content
2342 // frame on our attached content frame to resize... however,
2343 // things can be tricky if the attached window is NOT in resize
2344 // mode, in which case its content frame will be larger.
2345 // Ungh. So to deal with that, make sure the content frame
2346 // we end up using is not covering the IM dock.
2347 cf.set(attached.getContentFrameLw());
2348 if (attached.getSurfaceLayer() < mDockLayer) {
2349 if (cf.left < mContentLeft) cf.left = mContentLeft;
2350 if (cf.top < mContentTop) cf.top = mContentTop;
2351 if (cf.right > mContentRight) cf.right = mContentRight;
2352 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
2353 }
2354 }
2355 df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
2356 vf.set(attached.getVisibleFrameLw());
2357 }
2358 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
2359 // window should be positioned relative to its parent or the entire
2360 // screen.
2361 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
2362 ? attached.getFrameLw() : df);
2363 }
2364
2365 /** {@inheritDoc} */
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07002366 public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
2367 WindowState attached) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002368 // we've already done the status bar
Dianne Hackborn1f903c32011-09-13 19:18:06 -07002369 if (win == mStatusBar || win == mNavigationBar) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002370 return;
2371 }
2372
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002373 final int fl = attrs.flags;
2374 final int sim = attrs.softInputMode;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002375 final int sysUiFl = win.getSystemUiVisibility();
2376
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002377 final Rect pf = mTmpParentFrame;
2378 final Rect df = mTmpDisplayFrame;
2379 final Rect cf = mTmpContentFrame;
2380 final Rect vf = mTmpVisibleFrame;
2381
Daniel Sandler36412a72011-08-04 09:35:13 -04002382 final boolean hasNavBar = (mHasNavigationBar
2383 && mNavigationBar != null && mNavigationBar.isVisibleLw());
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002384
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002385 if (attrs.type == TYPE_INPUT_METHOD) {
2386 pf.left = df.left = cf.left = vf.left = mDockLeft;
2387 pf.top = df.top = cf.top = vf.top = mDockTop;
2388 pf.right = df.right = cf.right = vf.right = mDockRight;
2389 pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
2390 // IM dock windows always go to the bottom of the screen.
2391 attrs.gravity = Gravity.BOTTOM;
2392 mDockLayer = win.getSurfaceLayer();
2393 } else {
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002394 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
2395
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07002396 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002397 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)
2398 && (sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002399 if (DEBUG_LAYOUT)
2400 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2401 + "): IN_SCREEN, INSET_DECOR, !FULLSCREEN");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002402 // This is the case for a normal activity window: we want it
2403 // to cover all of the screen space, and it can take care of
2404 // moving its contents to account for screen decorations that
2405 // intrude into that space.
2406 if (attached != null) {
2407 // If this window is attached to another, our display
2408 // frame is the same as the one we are attached to.
2409 setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
2410 } else {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002411 if (attrs.type == TYPE_STATUS_BAR_PANEL
2412 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
Joe Onorato29fc2c92010-11-24 10:26:50 -08002413 // Status bar panels are the only windows who can go on top of
2414 // the status bar. They are protected by the STATUS_BAR_SERVICE
2415 // permission, so they have the same privileges as the status
2416 // bar itself.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002417 //
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002418 // However, they should still dodge the navigation bar if it exists.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002419
2420 pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002421 pf.top = df.top = mUnrestrictedScreenTop;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002422 pf.right = df.right = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002423 ? mRestrictedScreenLeft+mRestrictedScreenWidth
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002424 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2425 pf.bottom = df.bottom = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002426 ? mRestrictedScreenTop+mRestrictedScreenHeight
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002427 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
2428
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002429 if (DEBUG_LAYOUT) {
2430 Log.v(TAG, String.format(
2431 "Laying out status bar window: (%d,%d - %d,%d)",
2432 pf.left, pf.top, pf.right, pf.bottom));
2433 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002434 } else if (mCanHideNavigationBar
2435 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002436 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
2437 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
2438 // Asking for layout as if the nav bar is hidden, lets the
2439 // application extend into the unrestricted screen area. We
2440 // only do this for application windows to ensure no window that
2441 // can be above the nav bar can do this.
2442 pf.left = df.left = mUnrestrictedScreenLeft;
2443 pf.top = df.top = mUnrestrictedScreenTop;
2444 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2445 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002446 } else {
2447 pf.left = df.left = mRestrictedScreenLeft;
2448 pf.top = df.top = mRestrictedScreenTop;
2449 pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2450 pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
2451 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002452 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002453 cf.left = mDockLeft;
2454 cf.top = mDockTop;
2455 cf.right = mDockRight;
2456 cf.bottom = mDockBottom;
2457 } else {
2458 cf.left = mContentLeft;
2459 cf.top = mContentTop;
2460 cf.right = mContentRight;
2461 cf.bottom = mContentBottom;
2462 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002463 if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2464 // If app is requesting a stable layout, don't let the
2465 // content insets go below the stable values.
2466 if (cf.left < mStableLeft) cf.left = mStableLeft;
2467 if (cf.top < mStableTop) cf.top = mStableTop;
2468 if (cf.right > mStableRight) cf.right = mStableRight;
2469 if (cf.bottom > mStableBottom) cf.bottom = mStableBottom;
2470 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002471 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2472 vf.left = mCurLeft;
2473 vf.top = mCurTop;
2474 vf.right = mCurRight;
2475 vf.bottom = mCurBottom;
2476 } else {
2477 vf.set(cf);
2478 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002479 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002480 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
2481 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
2482 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002483 if (DEBUG_LAYOUT)
2484 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002485 // A window that has requested to fill the entire screen just
2486 // gets everything, period.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002487 if (attrs.type == TYPE_STATUS_BAR_PANEL
2488 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
2489 pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002490 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002491 pf.right = df.right = cf.right = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002492 ? mRestrictedScreenLeft+mRestrictedScreenWidth
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002493 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2494 pf.bottom = df.bottom = cf.bottom = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002495 ? mRestrictedScreenTop+mRestrictedScreenHeight
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002496 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Daniel Sandler36412a72011-08-04 09:35:13 -04002497 if (DEBUG_LAYOUT) {
2498 Log.v(TAG, String.format(
2499 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
2500 pf.left, pf.top, pf.right, pf.bottom));
2501 }
Jim Millere898ac52012-04-06 17:10:57 -07002502 } else if (attrs.type == TYPE_NAVIGATION_BAR
2503 || attrs.type == TYPE_NAVIGATION_BAR_PANEL) {
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002504 // The navigation bar has Real Ultimate Power.
2505 pf.left = df.left = mUnrestrictedScreenLeft;
2506 pf.top = df.top = mUnrestrictedScreenTop;
2507 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2508 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
2509 if (DEBUG_LAYOUT) {
2510 Log.v(TAG, String.format(
2511 "Laying out navigation bar window: (%d,%d - %d,%d)",
2512 pf.left, pf.top, pf.right, pf.bottom));
2513 }
Dianne Hackborn01011c32012-02-21 13:54:21 -08002514 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
2515 || attrs.type == TYPE_BOOT_PROGRESS)
Jeff Brownbfcb60a2011-09-08 18:51:14 -07002516 && ((fl & FLAG_FULLSCREEN) != 0)) {
2517 // Fullscreen secure system overlays get what they ask for.
2518 pf.left = df.left = mUnrestrictedScreenLeft;
2519 pf.top = df.top = mUnrestrictedScreenTop;
2520 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2521 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Dianne Hackborn01011c32012-02-21 13:54:21 -08002522 } else if (attrs.type == TYPE_BOOT_PROGRESS) {
2523 // Boot progress screen always covers entire display.
2524 pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
2525 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
2526 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2527 pf.bottom = df.bottom = cf.bottom
2528 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002529 } else if (mCanHideNavigationBar
2530 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002531 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
2532 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
2533 // Asking for layout as if the nav bar is hidden, lets the
2534 // application extend into the unrestricted screen area. We
2535 // only do this for application windows to ensure no window that
2536 // can be above the nav bar can do this.
2537 // XXX This assumes that an app asking for this will also
2538 // ask for layout in only content. We can't currently figure out
2539 // what the screen would be if only laying out to hide the nav bar.
2540 pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
2541 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
2542 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2543 pf.bottom = df.bottom = cf.bottom
2544 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002545 } else {
2546 pf.left = df.left = cf.left = mRestrictedScreenLeft;
2547 pf.top = df.top = cf.top = mRestrictedScreenTop;
2548 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2549 pf.bottom = df.bottom = cf.bottom
2550 = mRestrictedScreenTop+mRestrictedScreenHeight;
2551 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002552 if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2553 // If app is requesting a stable layout, don't let the
2554 // content insets go below the stable values.
2555 if (cf.left < mStableLeft) cf.left = mStableLeft;
2556 if (cf.top < mStableTop) cf.top = mStableTop;
2557 if (cf.right > mStableRight) cf.right = mStableRight;
2558 if (cf.bottom > mStableBottom) cf.bottom = mStableBottom;
2559 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002560 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2561 vf.left = mCurLeft;
2562 vf.top = mCurTop;
2563 vf.right = mCurRight;
2564 vf.bottom = mCurBottom;
2565 } else {
2566 vf.set(cf);
2567 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002568 } else if (attached != null) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002569 if (DEBUG_LAYOUT)
2570 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): attached to " + attached);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002571 // A child window should be placed inside of the same visible
2572 // frame that its parent had.
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002573 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002574 } else {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002575 if (DEBUG_LAYOUT)
2576 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002577 // Otherwise, a normal window must be placed inside the content
2578 // of all screen decorations.
Dianne Hackborna239c842011-06-01 12:28:20 -07002579 if (attrs.type == TYPE_STATUS_BAR_PANEL) {
2580 // Status bar panels are the only windows who can go on top of
2581 // the status bar. They are protected by the STATUS_BAR_SERVICE
2582 // permission, so they have the same privileges as the status
2583 // bar itself.
Dianne Hackborn7d049322011-06-14 15:00:32 -07002584 pf.left = df.left = cf.left = mRestrictedScreenLeft;
2585 pf.top = df.top = cf.top = mRestrictedScreenTop;
2586 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2587 pf.bottom = df.bottom = cf.bottom
2588 = mRestrictedScreenTop+mRestrictedScreenHeight;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002589 } else {
Dianne Hackborna239c842011-06-01 12:28:20 -07002590 pf.left = mContentLeft;
2591 pf.top = mContentTop;
2592 pf.right = mContentRight;
2593 pf.bottom = mContentBottom;
2594 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
2595 df.left = cf.left = mDockLeft;
2596 df.top = cf.top = mDockTop;
2597 df.right = cf.right = mDockRight;
2598 df.bottom = cf.bottom = mDockBottom;
2599 } else {
2600 df.left = cf.left = mContentLeft;
2601 df.top = cf.top = mContentTop;
2602 df.right = cf.right = mContentRight;
2603 df.bottom = cf.bottom = mContentBottom;
2604 }
2605 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2606 vf.left = mCurLeft;
2607 vf.top = mCurTop;
2608 vf.right = mCurRight;
2609 vf.bottom = mCurBottom;
2610 } else {
2611 vf.set(cf);
2612 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002613 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002614 }
2615 }
2616
2617 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
2618 df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
2619 df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
2620 }
2621
The Android Open Source Project11267662009-03-18 17:39:47 -07002622 if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
2623 + ": sim=#" + Integer.toHexString(sim)
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002624 + " attach=" + attached + " type=" + attrs.type
2625 + String.format(" flags=0x%08x", fl)
The Android Open Source Project11267662009-03-18 17:39:47 -07002626 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
2627 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
2628
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002629 win.computeFrameLw(pf, df, cf, vf);
2630
2631 // Dock windows carve out the bottom of the screen, so normal windows
2632 // can't appear underneath them.
2633 if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
2634 int top = win.getContentFrameLw().top;
2635 top += win.getGivenContentInsetsLw().top;
2636 if (mContentBottom > top) {
2637 mContentBottom = top;
2638 }
2639 top = win.getVisibleFrameLw().top;
2640 top += win.getGivenVisibleInsetsLw().top;
2641 if (mCurBottom > top) {
2642 mCurBottom = top;
2643 }
The Android Open Source Project11267662009-03-18 17:39:47 -07002644 if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom="
2645 + mDockBottom + " mContentBottom="
2646 + mContentBottom + " mCurBottom=" + mCurBottom);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002647 }
2648 }
2649
2650 /** {@inheritDoc} */
Craig Mautner61ac6bb2012-02-02 17:29:33 -08002651 @Override
2652 public void finishLayoutLw() {
2653 return;
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002654 }
2655
2656 /** {@inheritDoc} */
2657 public void beginAnimationLw(int displayWidth, int displayHeight) {
2658 mTopFullscreenOpaqueWindowState = null;
2659 mForceStatusBar = false;
2660
2661 mHideLockScreen = false;
2662 mAllowLockscreenWhenOn = false;
2663 mDismissKeyguard = false;
2664 }
2665
2666 /** {@inheritDoc} */
2667 public void animatingWindowLw(WindowState win,
2668 WindowManager.LayoutParams attrs) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002669 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
2670 + win.isVisibleOrBehindKeyguardLw());
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002671 if (mTopFullscreenOpaqueWindowState == null &&
Dianne Hackborn01b02a72012-01-12 14:05:03 -08002672 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002673 if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
2674 mForceStatusBar = true;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002675 }
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002676 if (attrs.type >= FIRST_APPLICATION_WINDOW
2677 && attrs.type <= LAST_APPLICATION_WINDOW
Dianne Hackborn6493e642010-10-01 13:06:30 -07002678 && attrs.x == 0 && attrs.y == 0
2679 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
2680 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002681 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win);
2682 mTopFullscreenOpaqueWindowState = win;
2683 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2684 if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
2685 mHideLockScreen = true;
2686 }
2687 if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2688 if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win);
2689 mDismissKeyguard = true;
2690 }
2691 if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
2692 mAllowLockscreenWhenOn = true;
2693 }
2694 }
2695 }
2696 }
2697
2698 /** {@inheritDoc} */
2699 public int finishAnimationLw() {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002700 int changes = 0;
Joe Onorato93056472010-09-10 10:30:46 -04002701 boolean topIsFullscreen = false;
Daniel Sandlere02d8082010-10-08 15:13:22 -04002702
2703 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
2704 ? mTopFullscreenOpaqueWindowState.getAttrs()
2705 : null;
2706
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002707 if (mStatusBar != null) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002708 if (DEBUG_LAYOUT) Log.i(TAG, "force=" + mForceStatusBar
Dianne Hackbornd70bc2f2009-10-06 23:25:51 -07002709 + " top=" + mTopFullscreenOpaqueWindowState);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002710 if (mForceStatusBar) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002711 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: forced");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002712 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002713 } else if (mTopFullscreenOpaqueWindowState != null) {
Joe Onorato93056472010-09-10 10:30:46 -04002714 if (localLOGV) {
2715 Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
2716 + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
2717 Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
2718 + " lp.flags=0x" + Integer.toHexString(lp.flags));
2719 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002720 topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
2721 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
Joe Onorato93056472010-09-10 10:30:46 -04002722 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
2723 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
2724 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
2725 // case though.
2726 if (topIsFullscreen) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002727 if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar");
2728 if (mStatusBar.hideLw(true)) {
2729 changes |= FINISH_LAYOUT_REDO_LAYOUT;
Daniel Sandler9c00d5b2011-09-13 14:04:26 -04002730
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002731 mHandler.post(new Runnable() { public void run() {
2732 if (mStatusBarService != null) {
2733 try {
2734 mStatusBarService.collapse();
2735 } catch (RemoteException ex) {}
2736 }
2737 }});
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002738 } else if (DEBUG_LAYOUT) {
Daniel Sandler40427442010-07-16 11:44:52 -04002739 Log.v(TAG, "Preventing status bar from hiding by policy");
2740 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002741 } else {
Dianne Hackborn01b02a72012-01-12 14:05:03 -08002742 if (DEBUG_LAYOUT) Log.v(TAG, "** SHOWING status bar: top is not fullscreen");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002743 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002744 }
2745 }
2746 }
Daniel Sandlere02d8082010-10-08 15:13:22 -04002747
Joe Onorato644f9c32011-01-25 12:06:23 -08002748 mTopIsFullscreen = topIsFullscreen;
Daniel Sandlere02d8082010-10-08 15:13:22 -04002749
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002750 // Hide the key guard if a visible window explicitly specifies that it wants to be displayed
2751 // when the screen is locked
2752 if (mKeyguard != null) {
Joe Onorato93056472010-09-10 10:30:46 -04002753 if (localLOGV) Log.v(TAG, "finishAnimationLw::mHideKeyguard="+mHideLockScreen);
Dianne Hackborn05726582009-09-22 17:28:24 -07002754 if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
Dianne Hackborn08743722009-12-21 12:16:51 -08002755 if (mKeyguard.hideLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002756 changes |= FINISH_LAYOUT_REDO_LAYOUT
2757 | FINISH_LAYOUT_REDO_CONFIG
2758 | FINISH_LAYOUT_REDO_WALLPAPER;
2759 }
Dianne Hackborn05726582009-09-22 17:28:24 -07002760 if (mKeyguardMediator.isShowing()) {
Dianne Hackbornb446e972009-09-20 15:23:25 -07002761 mHandler.post(new Runnable() {
2762 public void run() {
Dianne Hackborn05726582009-09-22 17:28:24 -07002763 mKeyguardMediator.keyguardDone(false, false);
Dianne Hackbornb446e972009-09-20 15:23:25 -07002764 }
2765 });
2766 }
Dianne Hackborn05726582009-09-22 17:28:24 -07002767 } else if (mHideLockScreen) {
Dianne Hackborn08743722009-12-21 12:16:51 -08002768 if (mKeyguard.hideLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002769 changes |= FINISH_LAYOUT_REDO_LAYOUT
2770 | FINISH_LAYOUT_REDO_CONFIG
2771 | FINISH_LAYOUT_REDO_WALLPAPER;
2772 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05002773 mKeyguardMediator.setHidden(true);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002774 } else {
Dianne Hackborn08743722009-12-21 12:16:51 -08002775 if (mKeyguard.showLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002776 changes |= FINISH_LAYOUT_REDO_LAYOUT
2777 | FINISH_LAYOUT_REDO_CONFIG
2778 | FINISH_LAYOUT_REDO_WALLPAPER;
2779 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05002780 mKeyguardMediator.setHidden(false);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002781 }
2782 }
Joe Onorato664644d2011-01-23 17:53:23 -08002783
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002784 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002785 // If the navigation bar has been hidden or shown, we need to do another
2786 // layout pass to update that window.
2787 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2788 }
Joe Onorato664644d2011-01-23 17:53:23 -08002789
Mike Lockwood28569302010-01-28 11:54:40 -05002790 // update since mAllowLockscreenWhenOn might have changed
2791 updateLockScreenTimeout();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002792 return changes;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002793 }
2794
Dianne Hackborn08743722009-12-21 12:16:51 -08002795 public boolean allowAppAnimationsLw() {
2796 if (mKeyguard != null && mKeyguard.isVisibleLw()) {
2797 // If keyguard is currently visible, no reason to animate
2798 // behind it.
2799 return false;
2800 }
Dianne Hackborn08743722009-12-21 12:16:51 -08002801 return true;
2802 }
2803
Dianne Hackborndf89e652011-10-06 22:35:11 -07002804 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
Joe Onorato664644d2011-01-23 17:53:23 -08002805 mFocusedWindow = newFocus;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002806 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002807 // If the navigation bar has been hidden or shown, we need to do another
2808 // layout pass to update that window.
2809 return FINISH_LAYOUT_REDO_LAYOUT;
2810 }
2811 return 0;
Joe Onorato664644d2011-01-23 17:53:23 -08002812 }
2813
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07002814 /** {@inheritDoc} */
Jeff Brown46b9ac02010-04-22 18:58:52 -07002815 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002816 // do nothing if headless
Mike Lockwoodd747dc82011-09-13 16:28:22 -04002817 if (mHeadless) return;
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002818
Jeff Brown46b9ac02010-04-22 18:58:52 -07002819 // lid changed state
Jeff Brownc458ce92012-04-30 14:58:40 -07002820 final int newLidState = lidOpen ? LID_OPEN : LID_CLOSED;
2821 if (newLidState == mLidState) {
2822 return;
2823 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07002824
Jeff Brownc458ce92012-04-30 14:58:40 -07002825 mLidState = newLidState;
2826 applyLidSwitchState();
Jeff Brown01a98dd2011-09-20 15:08:29 -07002827 updateRotation(true);
Jeff Brownc458ce92012-04-30 14:58:40 -07002828
2829 if (lidOpen) {
2830 if (keyguardIsShowingTq()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002831 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
Jeff Brown43150bf2011-11-08 20:22:03 -08002832 KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002833 } else {
2834 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
Jeff Brownc458ce92012-04-30 14:58:40 -07002835 LocalPowerManager.BUTTON_EVENT);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002836 }
Jeff Brownc458ce92012-04-30 14:58:40 -07002837 } else if (!mLidControlsSleep) {
2838 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
2839 LocalPowerManager.OTHER_EVENT);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002840 }
2841 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002842
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002843 void setHdmiPlugged(boolean plugged) {
2844 if (mHdmiPlugged != plugged) {
2845 mHdmiPlugged = plugged;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002846 if (plugged && mDisplay != null) {
2847 mExternalDisplayWidth = mDisplay.getRawExternalWidth();
2848 mExternalDisplayHeight = mDisplay.getRawExternalHeight();
2849 }
2850 updateRotation(true, true);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002851 Intent intent = new Intent(ACTION_HDMI_PLUGGED);
Joe Onoratodc100302011-01-11 17:07:41 -08002852 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002853 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
2854 mContext.sendStickyBroadcast(intent);
2855 }
2856 }
2857
Joe Onoratoea495d42011-04-06 11:41:11 -07002858 void initializeHdmiState() {
Joe Onorato7ba631f2011-05-04 15:28:00 -07002859 boolean plugged = false;
Joe Onoratoea495d42011-04-06 11:41:11 -07002860 // watch for HDMI plug messages if the hdmi switch exists
2861 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
2862 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
2863
Joe Onoratoea495d42011-04-06 11:41:11 -07002864 final String filename = "/sys/class/switch/hdmi/state";
2865 FileReader reader = null;
2866 try {
2867 reader = new FileReader(filename);
2868 char[] buf = new char[15];
2869 int n = reader.read(buf);
2870 if (n > 1) {
2871 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
2872 }
2873 } catch (IOException ex) {
2874 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
2875 } catch (NumberFormatException ex) {
2876 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
2877 } finally {
2878 if (reader != null) {
2879 try {
2880 reader.close();
2881 } catch (IOException ex) {
2882 }
Joe Onoratodc100302011-01-11 17:07:41 -08002883 }
2884 }
2885 }
Joe Onorato7ba631f2011-05-04 15:28:00 -07002886 // This dance forces the code in setHdmiPlugged to run.
2887 // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
2888 mHdmiPlugged = !plugged;
2889 setHdmiPlugged(!mHdmiPlugged);
Joe Onoratodc100302011-01-11 17:07:41 -08002890 }
2891
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002892 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002893 * @return Whether music is being played right now.
2894 */
2895 boolean isMusicActive() {
Eric Laurent413cb9d2009-07-17 11:52:43 -07002896 final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
2897 if (am == null) {
2898 Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002899 return false;
2900 }
Eric Laurent413cb9d2009-07-17 11:52:43 -07002901 return am.isMusicActive();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002902 }
2903
2904 /**
2905 * Tell the audio service to adjust the volume appropriate to the event.
2906 * @param keycode
2907 */
Mike Lockwooda53e3812009-09-25 10:51:39 -04002908 void handleVolumeKey(int stream, int keycode) {
Jeff Brown4d396052010-10-29 21:50:21 -07002909 IAudioService audioService = getAudioService();
2910 if (audioService == null) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002911 return;
2912 }
2913 try {
2914 // since audio is playing, we shouldn't have to hold a wake lock
2915 // during the call, but we do it as a precaution for the rare possibility
2916 // that the music stops right before we call this
Jeff Brownb0418da2010-11-01 15:24:01 -07002917 // TODO: Actually handle MUTE.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002918 mBroadcastWakeLock.acquire();
Jeff Brown4d396052010-10-29 21:50:21 -07002919 audioService.adjustStreamVolume(stream,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002920 keycode == KeyEvent.KEYCODE_VOLUME_UP
2921 ? AudioManager.ADJUST_RAISE
2922 : AudioManager.ADJUST_LOWER,
2923 0);
2924 } catch (RemoteException e) {
2925 Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e);
2926 } finally {
2927 mBroadcastWakeLock.release();
2928 }
2929 }
Jeff Brown4d396052010-10-29 21:50:21 -07002930
Dianne Hackbornc0e3f242011-08-19 14:19:10 -07002931 final Object mScreenshotLock = new Object();
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07002932 ServiceConnection mScreenshotConnection = null;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07002933
Jeff Brownd5bb82d2011-10-12 13:57:59 -07002934 final Runnable mScreenshotTimeout = new Runnable() {
2935 @Override public void run() {
2936 synchronized (mScreenshotLock) {
2937 if (mScreenshotConnection != null) {
2938 mContext.unbindService(mScreenshotConnection);
2939 mScreenshotConnection = null;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07002940 }
Winson Chung9112ec32011-06-27 13:15:32 -07002941 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07002942 }
2943 };
2944
2945 // Assume this is called from the Handler thread.
2946 private void takeScreenshot() {
2947 synchronized (mScreenshotLock) {
2948 if (mScreenshotConnection != null) {
2949 return;
2950 }
2951 ComponentName cn = new ComponentName("com.android.systemui",
2952 "com.android.systemui.screenshot.TakeScreenshotService");
2953 Intent intent = new Intent();
2954 intent.setComponent(cn);
2955 ServiceConnection conn = new ServiceConnection() {
2956 @Override
2957 public void onServiceConnected(ComponentName name, IBinder service) {
2958 synchronized (mScreenshotLock) {
2959 if (mScreenshotConnection != this) {
2960 return;
2961 }
2962 Messenger messenger = new Messenger(service);
2963 Message msg = Message.obtain(null, 1);
2964 final ServiceConnection myConn = this;
2965 Handler h = new Handler(mHandler.getLooper()) {
2966 @Override
2967 public void handleMessage(Message msg) {
2968 synchronized (mScreenshotLock) {
2969 if (mScreenshotConnection == myConn) {
2970 mContext.unbindService(mScreenshotConnection);
2971 mScreenshotConnection = null;
2972 mHandler.removeCallbacks(mScreenshotTimeout);
2973 }
2974 }
2975 }
2976 };
2977 msg.replyTo = new Messenger(h);
Winson Chunga63bb842011-10-17 10:26:28 -07002978 msg.arg1 = msg.arg2 = 0;
2979 if (mStatusBar != null && mStatusBar.isVisibleLw())
2980 msg.arg1 = 1;
2981 if (mNavigationBar != null && mNavigationBar.isVisibleLw())
2982 msg.arg2 = 1;
Jeff Brownd5bb82d2011-10-12 13:57:59 -07002983 try {
2984 messenger.send(msg);
2985 } catch (RemoteException e) {
2986 }
2987 }
2988 }
2989 @Override
2990 public void onServiceDisconnected(ComponentName name) {}
2991 };
2992 if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
2993 mScreenshotConnection = conn;
2994 mHandler.postDelayed(mScreenshotTimeout, 10000);
2995 }
2996 }
Winson Chung9112ec32011-06-27 13:15:32 -07002997 }
2998
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002999 /** {@inheritDoc} */
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003000 @Override
Jeff Brown1f245102010-11-18 20:53:46 -08003001 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
3002 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3003 final boolean canceled = event.isCanceled();
3004 final int keyCode = event.getKeyCode();
Jeff Browne20c9e02010-10-11 14:20:19 -07003005
Jeff Brown3122e442010-10-11 23:32:49 -07003006 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
Jeff Brown3122e442010-10-11 23:32:49 -07003007
Mike Lockwoodc72b15f2009-11-28 20:58:22 -05003008 // If screen is off then we treat the case where the keyguard is open but hidden
3009 // the same as if it were open and in front.
3010 // This will prevent any keys other than the power button from waking the screen
3011 // when the keyguard is hidden by another activity.
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003012 final boolean keyguardActive = (mKeyguardMediator == null ? false :
3013 (isScreenOn ?
3014 mKeyguardMediator.isShowingAndNotHidden() :
3015 mKeyguardMediator.isShowing()));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003016
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07003017 if (!mSystemBooted) {
3018 // If we have not yet booted, don't let key events do anything.
3019 return 0;
3020 }
3021
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003022 if (false) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003023 Log.d(TAG, "interceptKeyTq keycode=" + keyCode
3024 + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003025 }
3026
Jeff Brown98392ef2011-09-12 18:24:59 -07003027 if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
3028 && event.getRepeatCount() == 0) {
Jeff Brown4d396052010-10-29 21:50:21 -07003029 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
3030 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003031
Jeff Brownbc072da2011-11-15 12:56:55 -08003032 if (keyCode == KeyEvent.KEYCODE_POWER) {
3033 policyFlags |= WindowManagerPolicy.FLAG_WAKE;
3034 }
3035 final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
3036 | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
3037
Jeff Brown4d396052010-10-29 21:50:21 -07003038 // Basic policy based on screen state and keyguard.
3039 // FIXME: This policy isn't quite correct. We shouldn't care whether the screen
3040 // is on or off, really. We should care about whether the device is in an
3041 // interactive state or is in suspend pretending to be "off".
3042 // The primary screen might be turned off due to proximity sensor or
3043 // because we are presenting media on an auxiliary screen or remotely controlling
3044 // the device some other way (which is why we have an exemption here for injected
3045 // events).
3046 int result;
Mike Lockwoodd747dc82011-09-13 16:28:22 -04003047 if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) {
Jeff Brown4d396052010-10-29 21:50:21 -07003048 // When the screen is on or if the key is injected pass the key to the application.
3049 result = ACTION_PASS_TO_USER;
3050 } else {
3051 // When the screen is off and the key is not injected, determine whether
3052 // to wake the device but don't pass the key to the application.
3053 result = 0;
Jeff Brown4d396052010-10-29 21:50:21 -07003054 if (down && isWakeKey) {
3055 if (keyguardActive) {
3056 // If the keyguard is showing, let it decide what to do with the wake key.
Jeff Brown43150bf2011-11-08 20:22:03 -08003057 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode,
3058 mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
Jeff Brown4d396052010-10-29 21:50:21 -07003059 } else {
3060 // Otherwise, wake the device ourselves.
3061 result |= ACTION_POKE_USER_ACTIVITY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003062 }
3063 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003064 }
3065
Jeff Brown4d396052010-10-29 21:50:21 -07003066 // Handle special keys.
3067 switch (keyCode) {
3068 case KeyEvent.KEYCODE_VOLUME_DOWN:
Jeff Brownb0418da2010-11-01 15:24:01 -07003069 case KeyEvent.KEYCODE_VOLUME_UP:
3070 case KeyEvent.KEYCODE_VOLUME_MUTE: {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003071 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
3072 if (down) {
3073 if (isScreenOn && !mVolumeDownKeyTriggered
3074 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3075 mVolumeDownKeyTriggered = true;
3076 mVolumeDownKeyTime = event.getDownTime();
3077 mVolumeDownKeyConsumedByScreenshotChord = false;
3078 cancelPendingPowerKeyAction();
3079 interceptScreenshotChord();
3080 }
3081 } else {
3082 mVolumeDownKeyTriggered = false;
3083 cancelPendingScreenshotChordAction();
3084 }
3085 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
3086 if (down) {
3087 if (isScreenOn && !mVolumeUpKeyTriggered
3088 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3089 mVolumeUpKeyTriggered = true;
3090 cancelPendingPowerKeyAction();
3091 cancelPendingScreenshotChordAction();
3092 }
3093 } else {
3094 mVolumeUpKeyTriggered = false;
3095 cancelPendingScreenshotChordAction();
3096 }
3097 }
Jeff Brown4d396052010-10-29 21:50:21 -07003098 if (down) {
3099 ITelephony telephonyService = getTelephonyService();
3100 if (telephonyService != null) {
3101 try {
3102 if (telephonyService.isRinging()) {
3103 // If an incoming call is ringing, either VOLUME key means
3104 // "silence ringer". We handle these keys here, rather than
3105 // in the InCallScreen, to make sure we'll respond to them
3106 // even if the InCallScreen hasn't come to the foreground yet.
3107 // Look for the DOWN event here, to agree with the "fallback"
3108 // behavior in the InCallScreen.
3109 Log.i(TAG, "interceptKeyBeforeQueueing:"
3110 + " VOLUME key-down while ringing: Silence ringer!");
3111
3112 // Silence the ringer. (It's safe to call this
3113 // even if the ringer has already been silenced.)
3114 telephonyService.silenceRinger();
3115
3116 // And *don't* pass this key thru to the current activity
3117 // (which is probably the InCallScreen.)
3118 result &= ~ACTION_PASS_TO_USER;
3119 break;
3120 }
3121 if (telephonyService.isOffhook()
3122 && (result & ACTION_PASS_TO_USER) == 0) {
3123 // If we are in call but we decided not to pass the key to
3124 // the application, handle the volume change here.
3125 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
3126 break;
3127 }
3128 } catch (RemoteException ex) {
3129 Log.w(TAG, "ITelephony threw RemoteException", ex);
3130 }
3131 }
3132
3133 if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) {
3134 // If music is playing but we decided not to pass the key to the
3135 // application, handle the volume change here.
3136 handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
3137 break;
3138 }
3139 }
3140 break;
3141 }
3142
3143 case KeyEvent.KEYCODE_ENDCALL: {
3144 result &= ~ACTION_PASS_TO_USER;
3145 if (down) {
3146 ITelephony telephonyService = getTelephonyService();
3147 boolean hungUp = false;
3148 if (telephonyService != null) {
3149 try {
3150 hungUp = telephonyService.endCall();
3151 } catch (RemoteException ex) {
3152 Log.w(TAG, "ITelephony threw RemoteException", ex);
3153 }
3154 }
3155 interceptPowerKeyDown(!isScreenOn || hungUp);
3156 } else {
3157 if (interceptPowerKeyUp(canceled)) {
3158 if ((mEndcallBehavior
3159 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
3160 if (goHome()) {
3161 break;
Dianne Hackborn0041e972009-07-24 17:14:43 -07003162 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003163 }
Jeff Brown4d396052010-10-29 21:50:21 -07003164 if ((mEndcallBehavior
3165 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
3166 result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
3167 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003168 }
Jeff Brown4d396052010-10-29 21:50:21 -07003169 }
3170 break;
3171 }
3172
3173 case KeyEvent.KEYCODE_POWER: {
3174 result &= ~ACTION_PASS_TO_USER;
3175 if (down) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003176 if (isScreenOn && !mPowerKeyTriggered
3177 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3178 mPowerKeyTriggered = true;
3179 mPowerKeyTime = event.getDownTime();
3180 interceptScreenshotChord();
Winson Chung9112ec32011-06-27 13:15:32 -07003181 }
Winson Chung9112ec32011-06-27 13:15:32 -07003182
Jeff Brown4d396052010-10-29 21:50:21 -07003183 ITelephony telephonyService = getTelephonyService();
3184 boolean hungUp = false;
3185 if (telephonyService != null) {
3186 try {
3187 if (telephonyService.isRinging()) {
3188 // Pressing Power while there's a ringing incoming
3189 // call should silence the ringer.
3190 telephonyService.silenceRinger();
3191 } else if ((mIncallPowerBehavior
3192 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
3193 && telephonyService.isOffhook()) {
3194 // Otherwise, if "Power button ends call" is enabled,
3195 // the Power button will hang up any current active call.
3196 hungUp = telephonyService.endCall();
3197 }
3198 } catch (RemoteException ex) {
3199 Log.w(TAG, "ITelephony threw RemoteException", ex);
3200 }
3201 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003202 interceptPowerKeyDown(!isScreenOn || hungUp
3203 || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003204 } else {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003205 mPowerKeyTriggered = false;
3206 cancelPendingScreenshotChordAction();
3207 if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
Jeff Brown4d396052010-10-29 21:50:21 -07003208 result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003209 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003210 mPendingPowerKeyUpCanceled = false;
Jeff Brown4d396052010-10-29 21:50:21 -07003211 }
3212 break;
3213 }
3214
3215 case KeyEvent.KEYCODE_MEDIA_PLAY:
3216 case KeyEvent.KEYCODE_MEDIA_PAUSE:
3217 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
3218 if (down) {
3219 ITelephony telephonyService = getTelephonyService();
3220 if (telephonyService != null) {
3221 try {
3222 if (!telephonyService.isIdle()) {
3223 // Suppress PLAY/PAUSE toggle when phone is ringing or in-call
3224 // to avoid music playback.
3225 break;
3226 }
3227 } catch (RemoteException ex) {
3228 Log.w(TAG, "ITelephony threw RemoteException", ex);
Jeff Brown3122e442010-10-11 23:32:49 -07003229 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003230 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003231 }
Jeff Brown4d396052010-10-29 21:50:21 -07003232 case KeyEvent.KEYCODE_HEADSETHOOK:
3233 case KeyEvent.KEYCODE_MUTE:
3234 case KeyEvent.KEYCODE_MEDIA_STOP:
3235 case KeyEvent.KEYCODE_MEDIA_NEXT:
3236 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
3237 case KeyEvent.KEYCODE_MEDIA_REWIND:
3238 case KeyEvent.KEYCODE_MEDIA_RECORD:
3239 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
3240 if ((result & ACTION_PASS_TO_USER) == 0) {
3241 // Only do this if we would otherwise not pass it to the user. In that
3242 // case, the PhoneWindow class will do the same thing, except it will
3243 // only do it if the showing app doesn't process the key on its own.
Jeff Brown4d396052010-10-29 21:50:21 -07003244 mBroadcastWakeLock.acquire();
Jeff Brown1f245102010-11-18 20:53:46 -08003245 mHandler.post(new PassHeadsetKey(new KeyEvent(event)));
Jeff Brown4d396052010-10-29 21:50:21 -07003246 }
3247 break;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003248 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003249
Jeff Brown4d396052010-10-29 21:50:21 -07003250 case KeyEvent.KEYCODE_CALL: {
3251 if (down) {
3252 ITelephony telephonyService = getTelephonyService();
3253 if (telephonyService != null) {
3254 try {
3255 if (telephonyService.isRinging()) {
3256 Log.i(TAG, "interceptKeyBeforeQueueing:"
3257 + " CALL key-down while ringing: Answer the call!");
3258 telephonyService.answerRingingCall();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003259
Jeff Brown4d396052010-10-29 21:50:21 -07003260 // And *don't* pass this key thru to the current activity
3261 // (which is presumably the InCallScreen.)
3262 result &= ~ACTION_PASS_TO_USER;
3263 }
3264 } catch (RemoteException ex) {
3265 Log.w(TAG, "ITelephony threw RemoteException", ex);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003266 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003267 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003268 }
Jeff Brown4d396052010-10-29 21:50:21 -07003269 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003270 }
3271 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003272 return result;
3273 }
3274
Jeff Brown56194eb2011-03-02 19:23:13 -08003275 /** {@inheritDoc} */
3276 @Override
3277 public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
3278 int result = 0;
3279
3280 final boolean isWakeMotion = (policyFlags
3281 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
3282 if (isWakeMotion) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003283 if (mKeyguardMediator != null && mKeyguardMediator.isShowing()) {
Jeff Brown56194eb2011-03-02 19:23:13 -08003284 // If the keyguard is showing, let it decide what to do with the wake motion.
3285 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
3286 } else {
3287 // Otherwise, wake the device ourselves.
3288 result |= ACTION_POKE_USER_ACTIVITY;
3289 }
3290 }
3291 return result;
3292 }
3293
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003294 class PassHeadsetKey implements Runnable {
3295 KeyEvent mKeyEvent;
3296
3297 PassHeadsetKey(KeyEvent keyEvent) {
3298 mKeyEvent = keyEvent;
3299 }
3300
3301 public void run() {
3302 if (ActivityManagerNative.isSystemReady()) {
3303 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
3304 intent.putExtra(Intent.EXTRA_KEY_EVENT, mKeyEvent);
3305 mContext.sendOrderedBroadcast(intent, null, mBroadcastDone,
3306 mHandler, Activity.RESULT_OK, null, null);
3307 }
3308 }
3309 }
3310
3311 BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
3312 public void onReceive(Context context, Intent intent) {
3313 mBroadcastWakeLock.release();
3314 }
3315 };
Mike Lockwood1753f7f2009-08-24 14:49:07 -07003316
3317 BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
3318 public void onReceive(Context context, Intent intent) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07003319 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
3320 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
3321 Intent.EXTRA_DOCK_STATE_UNDOCKED);
3322 } else {
3323 try {
3324 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
3325 ServiceManager.getService(Context.UI_MODE_SERVICE));
3326 mUiMode = uiModeService.getCurrentModeType();
3327 } catch (RemoteException e) {
3328 }
Dianne Hackborn80fa1662009-10-07 14:02:10 -07003329 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003330 updateRotation(true);
Mike Lockwoode9867d22009-09-20 01:59:02 -04003331 updateOrientationListenerLp();
Mike Lockwood1753f7f2009-08-24 14:49:07 -07003332 }
3333 };
3334
Daniel Sandler7e37df52011-11-16 22:08:23 -08003335 BroadcastReceiver mPowerReceiver = new BroadcastReceiver() {
3336 public void onReceive(Context context, Intent intent) {
3337 if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
3338 mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
3339 if (localLOGV) Log.v(TAG, "BATTERY_CHANGED: " + intent + " plugged=" + mPluggedIn);
3340 }
3341 }
3342 };
3343
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003344 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003345 public void screenTurnedOff(int why) {
Dianne Hackborn74489012009-03-24 20:50:09 -07003346 EventLog.writeEvent(70000, 0);
The Android Open Source Project0727d222009-03-11 12:11:58 -07003347 synchronized (mLock) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003348 mScreenOnEarly = false;
3349 mScreenOnFully = false;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003350 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003351 if (mKeyguardMediator != null) {
3352 mKeyguardMediator.onScreenTurnedOff(why);
3353 }
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003354 synchronized (mLock) {
The Android Open Source Project0727d222009-03-11 12:11:58 -07003355 updateOrientationListenerLp();
Mike Lockwood28569302010-01-28 11:54:40 -05003356 updateLockScreenTimeout();
The Android Open Source Project0727d222009-03-11 12:11:58 -07003357 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003358 }
3359
3360 /** {@inheritDoc} */
Dianne Hackborn38e29a62011-09-18 14:43:08 -07003361 public void screenTurningOn(final ScreenOnListener screenOnListener) {
Dianne Hackborn74489012009-03-24 20:50:09 -07003362 EventLog.writeEvent(70000, 1);
Dianne Hackborn40011092011-09-22 13:37:48 -07003363 if (false) {
3364 RuntimeException here = new RuntimeException("here");
3365 here.fillInStackTrace();
3366 Slog.i(TAG, "Screen turning on...", here);
3367 }
3368 if (screenOnListener != null) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003369 if (mKeyguardMediator != null) {
3370 mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
3371 @Override public void onShown(IBinder windowToken) {
3372 if (windowToken != null) {
3373 try {
3374 mWindowManager.waitForWindowDrawn(windowToken,
3375 new IRemoteCallback.Stub() {
3376 @Override public void sendResult(Bundle data) {
3377 Slog.i(TAG, "Lock screen displayed!");
3378 screenOnListener.onScreenOn();
3379 synchronized (mLock) {
3380 mScreenOnFully = true;
3381 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003382 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003383 });
3384 } catch (RemoteException e) {
3385 }
3386 } else {
3387 Slog.i(TAG, "No lock screen!");
3388 screenOnListener.onScreenOn();
3389 synchronized (mLock) {
3390 mScreenOnFully = true;
3391 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003392 }
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003393 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003394 });
3395 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003396 } else {
3397 synchronized (mLock) {
3398 mScreenOnFully = true;
Dianne Hackborn38e29a62011-09-18 14:43:08 -07003399 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003400 }
The Android Open Source Project0727d222009-03-11 12:11:58 -07003401 synchronized (mLock) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003402 mScreenOnEarly = true;
The Android Open Source Project0727d222009-03-11 12:11:58 -07003403 updateOrientationListenerLp();
Mike Lockwood28569302010-01-28 11:54:40 -05003404 updateLockScreenTimeout();
The Android Open Source Project0727d222009-03-11 12:11:58 -07003405 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003406 }
3407
3408 /** {@inheritDoc} */
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003409 public boolean isScreenOnEarly() {
3410 return mScreenOnEarly;
3411 }
3412
3413 /** {@inheritDoc} */
3414 public boolean isScreenOnFully() {
3415 return mScreenOnFully;
Dianne Hackborn08743722009-12-21 12:16:51 -08003416 }
3417
3418 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003419 public void enableKeyguard(boolean enabled) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003420 if (mKeyguardMediator != null) {
3421 mKeyguardMediator.setKeyguardEnabled(enabled);
3422 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003423 }
3424
3425 /** {@inheritDoc} */
3426 public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003427 if (mKeyguardMediator != null) {
3428 mKeyguardMediator.verifyUnlock(callback);
3429 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003430 }
3431
Mike Lockwoodf7913302009-11-28 22:27:10 -05003432 private boolean keyguardIsShowingTq() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003433 if (mKeyguardMediator == null) return false;
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08003434 return mKeyguardMediator.isShowingAndNotHidden();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003435 }
3436
Mike Lockwood520d8bc2011-02-18 13:23:13 -05003437
3438 /** {@inheritDoc} */
3439 public boolean isKeyguardLocked() {
3440 return keyguardOn();
3441 }
3442
3443 /** {@inheritDoc} */
3444 public boolean isKeyguardSecure() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003445 if (mKeyguardMediator == null) return false;
Mike Lockwood520d8bc2011-02-18 13:23:13 -05003446 return mKeyguardMediator.isSecure();
3447 }
3448
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003449 /** {@inheritDoc} */
3450 public boolean inKeyguardRestrictedKeyInputMode() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003451 if (mKeyguardMediator == null) return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003452 return mKeyguardMediator.isInputRestricted();
3453 }
3454
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003455 public void dismissKeyguardLw() {
3456 if (!mKeyguardMediator.isSecure()) {
3457 if (mKeyguardMediator.isShowing()) {
3458 mHandler.post(new Runnable() {
3459 public void run() {
3460 mKeyguardMediator.keyguardDone(false, true);
3461 }
3462 });
3463 }
3464 }
3465 }
3466
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003467 void sendCloseSystemWindows() {
3468 sendCloseSystemWindows(mContext, null);
3469 }
3470
3471 void sendCloseSystemWindows(String reason) {
3472 sendCloseSystemWindows(mContext, reason);
3473 }
3474
3475 static void sendCloseSystemWindows(Context context, String reason) {
3476 if (ActivityManagerNative.isSystemReady()) {
Dianne Hackborn94a679d2009-07-28 17:51:07 -07003477 try {
3478 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
3479 } catch (RemoteException e) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003480 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003481 }
3482 }
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07003483
Jeff Brown01a98dd2011-09-20 15:08:29 -07003484 @Override
3485 public int rotationForOrientationLw(int orientation, int lastRotation) {
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003486 if (false) {
3487 Slog.v(TAG, "rotationForOrientationLw(orient="
3488 + orientation + ", last=" + lastRotation
3489 + "); user=" + mUserRotation + " "
3490 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
3491 ? "USER_ROTATION_LOCKED" : "")
3492 );
3493 }
3494
The Android Open Source Project0727d222009-03-11 12:11:58 -07003495 synchronized (mLock) {
Jeff Brownc0347aa2011-09-23 17:26:09 -07003496 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
3497 if (sensorRotation < 0) {
3498 sensorRotation = lastRotation;
3499 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003500
Jeff Browndec6cf42011-11-15 14:08:20 -08003501 final int preferredRotation;
Jeff Brown2e7760e2012-04-11 15:14:55 -07003502 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003503 // Ignore sensor when lid switch is open and rotation is forced.
3504 preferredRotation = mLidOpenRotation;
3505 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
Jeff Brownc0347aa2011-09-23 17:26:09 -07003506 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003507 // Ignore sensor when in car dock unless explicitly enabled.
3508 // This case can override the behavior of NOSENSOR, and can also
3509 // enable 180 degree rotation while docked.
Jeff Brownc0347aa2011-09-23 17:26:09 -07003510 preferredRotation = mCarDockEnablesAccelerometer
Jeff Brown01a98dd2011-09-20 15:08:29 -07003511 ? sensorRotation : mCarDockRotation;
Jeff Brown1a693182011-11-08 14:44:16 -08003512 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
3513 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
3514 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
Jeff Brownc0347aa2011-09-23 17:26:09 -07003515 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003516 // Ignore sensor when in desk dock unless explicitly enabled.
3517 // This case can override the behavior of NOSENSOR, and can also
3518 // enable 180 degree rotation while docked.
Jeff Brownc0347aa2011-09-23 17:26:09 -07003519 preferredRotation = mDeskDockEnablesAccelerometer
Jeff Brown01a98dd2011-09-20 15:08:29 -07003520 ? sensorRotation : mDeskDockRotation;
Jeff Browneb3e4b92011-12-06 19:54:24 -08003521 } else if (mHdmiPlugged) {
3522 // Ignore sensor when plugged into HDMI.
3523 // Note that the dock orientation overrides the HDMI orientation.
3524 preferredRotation = mHdmiRotation;
Jeff Brown4dfce202011-10-05 12:00:10 -07003525 } else if ((mAccelerometerDefault != 0 /* implies not rotation locked */
Jeff Brown01a98dd2011-09-20 15:08:29 -07003526 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
3527 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED))
3528 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
3529 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
3530 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
3531 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
3532 // Otherwise, use sensor only if requested by the application or enabled
3533 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR.
Jeff Brownd3187e32011-09-21 19:26:44 -07003534 if (mAllowAllRotations < 0) {
3535 // Can't read this during init() because the context doesn't
3536 // have display metrics at that time so we cannot determine
3537 // tablet vs. phone then.
3538 mAllowAllRotations = mContext.getResources().getBoolean(
3539 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
3540 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003541 if (sensorRotation != Surface.ROTATION_180
Jeff Brownd3187e32011-09-21 19:26:44 -07003542 || mAllowAllRotations == 1
Jeff Brown01a98dd2011-09-20 15:08:29 -07003543 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) {
3544 preferredRotation = sensorRotation;
3545 } else {
3546 preferredRotation = lastRotation;
3547 }
Jeff Brown4dfce202011-10-05 12:00:10 -07003548 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
3549 // Apply rotation lock.
3550 preferredRotation = mUserRotation;
Jeff Browndec6cf42011-11-15 14:08:20 -08003551 } else {
3552 // No overriding preference.
3553 // We will do exactly what the application asked us to do.
3554 preferredRotation = -1;
Jeff Brown01a98dd2011-09-20 15:08:29 -07003555 }
3556
Dianne Hackborne5439f22010-10-02 16:53:50 -07003557 switch (orientation) {
3558 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
Jeff Browndec6cf42011-11-15 14:08:20 -08003559 // Return portrait unless overridden.
3560 if (isAnyPortrait(preferredRotation)) {
3561 return preferredRotation;
3562 }
Dianne Hackborne5439f22010-10-02 16:53:50 -07003563 return mPortraitRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003564
Jeff Brown01a98dd2011-09-20 15:08:29 -07003565 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
Jeff Browndec6cf42011-11-15 14:08:20 -08003566 // Return landscape unless overridden.
3567 if (isLandscapeOrSeascape(preferredRotation)) {
3568 return preferredRotation;
3569 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003570 return mLandscapeRotation;
3571
3572 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
Jeff Browndec6cf42011-11-15 14:08:20 -08003573 // Return reverse portrait unless overridden.
3574 if (isAnyPortrait(preferredRotation)) {
3575 return preferredRotation;
3576 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003577 return mUpsideDownRotation;
3578
3579 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
Jeff Browndec6cf42011-11-15 14:08:20 -08003580 // Return seascape unless overridden.
3581 if (isLandscapeOrSeascape(preferredRotation)) {
3582 return preferredRotation;
3583 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003584 return mSeascapeRotation;
3585
3586 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
3587 // Return either landscape rotation.
3588 if (isLandscapeOrSeascape(preferredRotation)) {
3589 return preferredRotation;
3590 }
3591 if (isLandscapeOrSeascape(lastRotation)) {
Jeff Brown4519f072011-01-23 13:16:01 -08003592 return lastRotation;
3593 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003594 return mLandscapeRotation;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003595
Jeff Brown01a98dd2011-09-20 15:08:29 -07003596 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
3597 // Return either portrait rotation.
3598 if (isAnyPortrait(preferredRotation)) {
3599 return preferredRotation;
3600 }
3601 if (isAnyPortrait(lastRotation)) {
3602 return lastRotation;
3603 }
3604 return mPortraitRotation;
3605
3606 default:
Jeff Brown4dfce202011-10-05 12:00:10 -07003607 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
3608 // just return the preferred orientation we already calculated.
Jeff Brown01a98dd2011-09-20 15:08:29 -07003609 if (preferredRotation >= 0) {
3610 return preferredRotation;
3611 }
Dianne Hackborndacea8c2011-04-21 17:26:39 -07003612 return Surface.ROTATION_0;
Daniel Sandlere7e5ac22011-02-22 16:10:21 -05003613 }
3614 }
Steve Howarda7bfe6a2010-09-23 16:47:49 -07003615 }
3616
Jeff Brown01a98dd2011-09-20 15:08:29 -07003617 @Override
3618 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
3619 switch (orientation) {
3620 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
3621 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
3622 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
3623 return isAnyPortrait(rotation);
3624
3625 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
3626 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
3627 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
3628 return isLandscapeOrSeascape(rotation);
3629
3630 default:
3631 return true;
3632 }
Steve Howarda7bfe6a2010-09-23 16:47:49 -07003633 }
3634
Jeff Brownc0347aa2011-09-23 17:26:09 -07003635 @Override
3636 public void setRotationLw(int rotation) {
3637 mOrientationListener.setCurrentRotation(rotation);
3638 }
3639
Jeff Brown01a98dd2011-09-20 15:08:29 -07003640 private boolean isLandscapeOrSeascape(int rotation) {
3641 return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003642 }
3643
Jeff Brown01a98dd2011-09-20 15:08:29 -07003644 private boolean isAnyPortrait(int rotation) {
3645 return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003646 }
3647
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003648
3649 // User rotation: to be used when all else fails in assigning an orientation to the device
3650 public void setUserRotationMode(int mode, int rot) {
3651 ContentResolver res = mContext.getContentResolver();
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003652
3653 // mUserRotationMode and mUserRotation will be assigned by the content observer
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003654 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003655 Settings.System.putInt(res,
3656 Settings.System.USER_ROTATION,
3657 rot);
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003658 Settings.System.putInt(res,
3659 Settings.System.ACCELEROMETER_ROTATION,
3660 0);
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003661 } else {
3662 Settings.System.putInt(res,
3663 Settings.System.ACCELEROMETER_ROTATION,
3664 1);
3665 }
3666 }
3667
Jeff Brownac143512012-04-05 18:57:33 -07003668 public void setSafeMode(boolean safeMode) {
3669 mSafeMode = safeMode;
3670 performHapticFeedbackLw(null, safeMode
3671 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
3672 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003673 }
3674
Dianne Hackborn181ceb52009-08-27 22:16:40 -07003675 static long[] getLongIntArray(Resources r, int resid) {
3676 int[] ar = r.getIntArray(resid);
3677 if (ar == null) {
3678 return null;
3679 }
3680 long[] out = new long[ar.length];
3681 for (int i=0; i<ar.length; i++) {
3682 out[i] = ar[i];
3683 }
3684 return out;
3685 }
3686
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003687 /** {@inheritDoc} */
3688 public void systemReady() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003689 if (mKeyguardMediator != null) {
3690 // tell the keyguard
3691 mKeyguardMediator.onSystemReady();
3692 }
Dianne Hackbornb1a79802009-09-29 15:18:31 -07003693 synchronized (mLock) {
3694 updateOrientationListenerLp();
Dianne Hackbornc777e072010-02-12 13:07:59 -08003695 mSystemReady = true;
3696 mHandler.post(new Runnable() {
3697 public void run() {
3698 updateSettings();
3699 }
3700 });
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003701 }
3702 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07003703
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07003704 /** {@inheritDoc} */
3705 public void systemBooted() {
3706 synchronized (mLock) {
3707 mSystemBooted = true;
3708 }
3709 }
3710
Dianne Hackborn661cd522011-08-22 00:26:20 -07003711 ProgressDialog mBootMsgDialog = null;
3712
3713 /** {@inheritDoc} */
3714 public void showBootMessage(final CharSequence msg, final boolean always) {
Mike Lockwoodaa5bf142011-09-21 13:03:40 -04003715 if (mHeadless) return;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003716 mHandler.post(new Runnable() {
3717 @Override public void run() {
3718 if (mBootMsgDialog == null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07003719 mBootMsgDialog = new ProgressDialog(mContext) {
3720 // This dialog will consume all events coming in to
3721 // it, to avoid it trying to do things too early in boot.
3722 @Override public boolean dispatchKeyEvent(KeyEvent event) {
3723 return true;
3724 }
3725 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
3726 return true;
3727 }
3728 @Override public boolean dispatchTouchEvent(MotionEvent ev) {
3729 return true;
3730 }
3731 @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
3732 return true;
3733 }
3734 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
3735 return true;
3736 }
3737 @Override public boolean dispatchPopulateAccessibilityEvent(
3738 AccessibilityEvent event) {
3739 return true;
3740 }
3741 };
Dianne Hackborn661cd522011-08-22 00:26:20 -07003742 mBootMsgDialog.setTitle(R.string.android_upgrading_title);
3743 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
3744 mBootMsgDialog.setIndeterminate(true);
3745 mBootMsgDialog.getWindow().setType(
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003746 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
Dianne Hackborn661cd522011-08-22 00:26:20 -07003747 mBootMsgDialog.getWindow().addFlags(
3748 WindowManager.LayoutParams.FLAG_DIM_BEHIND
3749 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
3750 mBootMsgDialog.getWindow().setDimAmount(1);
Dianne Hackbornd9efb952011-12-07 14:56:51 -08003751 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
3752 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
3753 mBootMsgDialog.getWindow().setAttributes(lp);
Dianne Hackborn661cd522011-08-22 00:26:20 -07003754 mBootMsgDialog.setCancelable(false);
3755 mBootMsgDialog.show();
3756 }
3757 mBootMsgDialog.setMessage(msg);
3758 }
3759 });
3760 }
3761
3762 /** {@inheritDoc} */
3763 public void hideBootMessages() {
3764 mHandler.post(new Runnable() {
3765 @Override public void run() {
3766 if (mBootMsgDialog != null) {
3767 mBootMsgDialog.dismiss();
3768 mBootMsgDialog = null;
3769 }
3770 }
3771 });
3772 }
3773
Mike Lockwood28569302010-01-28 11:54:40 -05003774 /** {@inheritDoc} */
3775 public void userActivity() {
Dianne Hackborndf89e652011-10-06 22:35:11 -07003776 // ***************************************
3777 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
3778 // ***************************************
3779 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
3780 // WITH ITS LOCKS HELD.
3781 //
3782 // This code must be VERY careful about the locks
3783 // it acquires.
3784 // In fact, the current code acquires way too many,
3785 // and probably has lurking deadlocks.
3786
Mike Lockwood28569302010-01-28 11:54:40 -05003787 synchronized (mScreenLockTimeout) {
3788 if (mLockScreenTimerActive) {
3789 // reset the timer
3790 mHandler.removeCallbacks(mScreenLockTimeout);
3791 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
3792 }
3793 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003794 }
3795
Daniel Sandler7d276c32012-01-30 14:33:52 -05003796 private IDreamManager getDreamManager() {
3797 if (!mScreenSaverFeatureAvailable) {
3798 return null;
3799 }
3800
3801 IDreamManager sandman = IDreamManager.Stub.asInterface(
3802 ServiceManager.checkService("dreams"));
3803 if (sandman == null) {
3804 Log.w(TAG, "Unable to find IDreamManager");
3805 }
3806 return sandman;
3807 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003808
Daniel Sandler7d276c32012-01-30 14:33:52 -05003809 @Override
3810 public boolean isScreenSaverEnabled() {
3811 return (mScreenSaverFeatureAvailable && mScreenSaverEnabledByUser
3812 && mScreenSaverMayRun && mScreenOnEarly && mPluggedIn);
3813 }
Daniel Sandler7e37df52011-11-16 22:08:23 -08003814
Daniel Sandler7d276c32012-01-30 14:33:52 -05003815 @Override
3816 public boolean startScreenSaver() {
3817 synchronized (mLock) {
3818 if (isScreenSaverEnabled()) {
3819 IDreamManager dm = getDreamManager();
3820 if (dm == null) return false;
3821
3822 try {
3823 if (localLOGV) Log.v(TAG, "startScreenSaver: entering dreamland...");
3824
3825 dm.dream();
3826 return true;
3827 } catch (RemoteException ex) {
3828 // too bad, so sad, oh mom, oh dad
Daniel Sandlerc224f762011-11-15 22:55:03 -08003829 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003830 }
3831 }
Daniel Sandler7d276c32012-01-30 14:33:52 -05003832 return false;
3833 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003834
Daniel Sandler7d276c32012-01-30 14:33:52 -05003835 @Override
3836 public void stopScreenSaver() {
3837 synchronized (mLock) {
3838 IDreamManager dm = getDreamManager();
3839 if (dm == null) return;
3840
3841 try {
3842 if (localLOGV) Log.v(TAG, "startScreenSaver: awakening...");
3843
3844 dm.awaken();
3845 } catch (RemoteException ex) {
Daniel Sandler0601eb72011-04-13 01:01:32 -04003846 }
3847 }
Mike Lockwood28569302010-01-28 11:54:40 -05003848 }
3849
3850 Runnable mScreenLockTimeout = new Runnable() {
3851 public void run() {
3852 synchronized (this) {
3853 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003854 if (mKeyguardMediator != null) {
3855 mKeyguardMediator.doKeyguardTimeout();
3856 }
Mike Lockwood28569302010-01-28 11:54:40 -05003857 mLockScreenTimerActive = false;
3858 }
3859 }
3860 };
3861
Jim Miller93c518e2012-01-17 15:55:31 -08003862 public void lockNow() {
3863 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
3864 mHandler.removeCallbacks(mScreenLockTimeout);
3865 mHandler.post(mScreenLockTimeout);
3866 }
3867
Mike Lockwood28569302010-01-28 11:54:40 -05003868 private void updateLockScreenTimeout() {
3869 synchronized (mScreenLockTimeout) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003870 boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly &&
3871 mKeyguardMediator != null && mKeyguardMediator.isSecure());
Mike Lockwood28569302010-01-28 11:54:40 -05003872 if (mLockScreenTimerActive != enable) {
3873 if (enable) {
3874 if (localLOGV) Log.v(TAG, "setting lockscreen timer");
3875 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
3876 } else {
3877 if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
3878 mHandler.removeCallbacks(mScreenLockTimeout);
3879 }
3880 mLockScreenTimerActive = enable;
3881 }
3882 }
3883 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003884
3885 /** {@inheritDoc} */
3886 public void enableScreenAfterBoot() {
3887 readLidState();
Jeff Brownc458ce92012-04-30 14:58:40 -07003888 applyLidSwitchState();
Jeff Brown01a98dd2011-09-20 15:08:29 -07003889 updateRotation(true);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003890 }
Dianne Hackbornf54c8f92009-09-19 14:03:57 -07003891
Jeff Brownc458ce92012-04-30 14:58:40 -07003892 private void applyLidSwitchState() {
3893 mPowerManager.setKeyboardVisibility(isKeyboardVisible());
3894 if (mLidState == LID_CLOSED && mLidControlsSleep) {
3895 mPowerManager.goToSleep(SystemClock.uptimeMillis());
3896 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003897 }
3898
3899 void updateRotation(boolean alwaysSendConfiguration) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003900 try {
3901 //set orientation on WindowManager
Dianne Hackbornf87d1962012-04-04 12:48:24 -07003902 mWindowManager.updateRotation(alwaysSendConfiguration, false);
3903 } catch (RemoteException e) {
3904 // Ignore
3905 }
3906 }
3907
3908 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
3909 try {
3910 //set orientation on WindowManager
3911 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003912 } catch (RemoteException e) {
3913 // Ignore
3914 }
3915 }
3916
3917 /**
Daniel Sandler11ddf532011-11-16 11:10:03 -08003918 * Return an Intent to launch the currently active dock app as home. Returns
3919 * null if the standard home should be launched, which is the case if any of the following is
3920 * true:
3921 * <ul>
3922 * <li>The device is not in either car mode or desk mode
3923 * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
3924 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
3925 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
3926 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
3927 * </ul>
Dianne Hackborn39c2d712009-09-22 11:41:31 -07003928 * @return
3929 */
3930 Intent createHomeDockIntent() {
Daniel Sandler11ddf532011-11-16 11:10:03 -08003931 Intent intent = null;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07003932
3933 // What home does is based on the mode, not the dock state. That
3934 // is, when in car mode you should be taken to car home regardless
3935 // of whether we are actually in a car dock.
Dianne Hackborn78968392010-03-04 20:47:56 -08003936 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
Daniel Sandler11ddf532011-11-16 11:10:03 -08003937 if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
3938 intent = mCarDockIntent;
3939 }
Dianne Hackborn78968392010-03-04 20:47:56 -08003940 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
Daniel Sandler11ddf532011-11-16 11:10:03 -08003941 if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
3942 intent = mDeskDockIntent;
3943 }
3944 }
3945
3946 if (intent == null) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07003947 return null;
3948 }
3949
3950 ActivityInfo ai = intent.resolveActivityInfo(
3951 mContext.getPackageManager(), PackageManager.GET_META_DATA);
3952 if (ai == null) {
3953 return null;
3954 }
3955
3956 if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
3957 intent = new Intent(intent);
3958 intent.setClassName(ai.packageName, ai.name);
3959 return intent;
3960 }
3961
3962 return null;
3963 }
3964
3965 void startDockOrHome() {
3966 Intent dock = createHomeDockIntent();
3967 if (dock != null) {
3968 try {
3969 mContext.startActivity(dock);
3970 return;
3971 } catch (ActivityNotFoundException e) {
3972 }
3973 }
3974 mContext.startActivity(mHomeIntent);
3975 }
3976
3977 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003978 * goes to the home screen
3979 * @return whether it did anything
3980 */
3981 boolean goHome() {
3982 if (false) {
3983 // This code always brings home to the front.
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07003984 try {
3985 ActivityManagerNative.getDefault().stopAppSwitches();
3986 } catch (RemoteException e) {
3987 }
Dianne Hackborn94a679d2009-07-28 17:51:07 -07003988 sendCloseSystemWindows();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07003989 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003990 } else {
3991 // This code brings home to the front or, if it is already
3992 // at the front, puts the device to sleep.
3993 try {
Wink Savilled2e6a332010-02-12 12:12:06 -08003994 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
3995 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
3996 Log.d(TAG, "UTS-TEST-MODE");
3997 } else {
3998 ActivityManagerNative.getDefault().stopAppSwitches();
3999 sendCloseSystemWindows();
4000 Intent dock = createHomeDockIntent();
4001 if (dock != null) {
4002 int result = ActivityManagerNative.getDefault()
4003 .startActivity(null, dock,
4004 dock.resolveTypeIfNeeded(mContext.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07004005 null, null, 0,
4006 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
4007 null, null, null);
4008 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
Wink Savilled2e6a332010-02-12 12:12:06 -08004009 return false;
4010 }
Dianne Hackborn39c2d712009-09-22 11:41:31 -07004011 }
4012 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004013 int result = ActivityManagerNative.getDefault()
4014 .startActivity(null, mHomeIntent,
4015 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07004016 null, null, 0,
4017 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
4018 null, null, null);
4019 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004020 return false;
4021 }
4022 } catch (RemoteException ex) {
4023 // bummer, the activity manager, which is in this process, is dead
4024 }
4025 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004026 return true;
4027 }
4028
The Android Open Source Project0727d222009-03-11 12:11:58 -07004029 public void setCurrentOrientationLw(int newOrientation) {
4030 synchronized (mLock) {
4031 if (newOrientation != mCurrentAppOrientation) {
4032 mCurrentAppOrientation = newOrientation;
4033 updateOrientationListenerLp();
4034 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004035 }
4036 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004037
The Android Open Source Project0727d222009-03-11 12:11:58 -07004038 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
Jim Miller89b17222009-10-27 14:54:09 -07004039 final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
4040 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08004041 if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004042 return false;
4043 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004044 long[] pattern = null;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004045 switch (effectId) {
4046 case HapticFeedbackConstants.LONG_PRESS:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004047 pattern = mLongPressVibePattern;
4048 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004049 case HapticFeedbackConstants.VIRTUAL_KEY:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004050 pattern = mVirtualKeyVibePattern;
4051 break;
4052 case HapticFeedbackConstants.KEYBOARD_TAP:
4053 pattern = mKeyboardTapVibePattern;
4054 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004055 case HapticFeedbackConstants.SAFE_MODE_DISABLED:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004056 pattern = mSafeModeDisabledVibePattern;
4057 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004058 case HapticFeedbackConstants.SAFE_MODE_ENABLED:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004059 pattern = mSafeModeEnabledVibePattern;
4060 break;
Amith Yamasanic33cb712010-02-10 15:21:49 -08004061 default:
4062 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004063 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004064 if (pattern.length == 1) {
4065 // One-shot vibration
4066 mVibrator.vibrate(pattern[0]);
4067 } else {
4068 // Pattern vibration
4069 mVibrator.vibrate(pattern, -1);
4070 }
4071 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004072 }
4073
Daniel Sandler0601eb72011-04-13 01:01:32 -04004074 public void screenOnStartedLw() {
4075 // The window manager has just grabbed a wake lock. This is our cue to disable the screen
4076 // saver.
4077 synchronized (mLock) {
Daniel Sandler2d545362011-11-17 10:38:37 -08004078 mScreenSaverMayRun = false;
Daniel Sandler0601eb72011-04-13 01:01:32 -04004079 }
4080 }
4081
The Android Open Source Project0727d222009-03-11 12:11:58 -07004082 public void screenOnStoppedLw() {
Daniel Sandler0601eb72011-04-13 01:01:32 -04004083 if (mPowerManager.isScreenOn()) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07004084 if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
Daniel Sandler0601eb72011-04-13 01:01:32 -04004085 long curTime = SystemClock.uptimeMillis();
4086 mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
4087 }
4088
4089 synchronized (mLock) {
4090 // even if the keyguard is up, now that all the wakelocks have been released, we
4091 // should re-enable the screen saver
Daniel Sandler2d545362011-11-17 10:38:37 -08004092 mScreenSaverMayRun = true;
Daniel Sandler0601eb72011-04-13 01:01:32 -04004093 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004094 }
4095 }
Mike Lockwoodfcb39242009-10-21 23:01:07 -04004096
4097 public boolean allowKeyRepeat() {
4098 // disable key repeat when screen is off
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07004099 return mScreenOnEarly;
Mike Lockwoodfcb39242009-10-21 23:01:07 -04004100 }
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004101
Dianne Hackborndf89e652011-10-06 22:35:11 -07004102 private int updateSystemUiVisibilityLw() {
Joe Onorato664644d2011-01-23 17:53:23 -08004103 // If there is no window focused, there will be nobody to handle the events
4104 // anyway, so just hang on in whatever state we're in until things settle down.
Dianne Hackborndf89e652011-10-06 22:35:11 -07004105 if (mFocusedWindow == null) {
4106 return 0;
4107 }
4108 final int visibility = mFocusedWindow.getSystemUiVisibility()
Dianne Hackborne26ab702011-10-16 13:21:33 -07004109 & ~mResettingSystemUiFlags
4110 & ~mForceClearedSystemUiFlags;
4111 int diff = visibility ^ mLastSystemUiFlags;
Dianne Hackborn73ab6a42011-12-13 11:16:23 -08004112 final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
Dianne Hackborne0f085d2011-11-30 18:41:15 -08004113 if (diff == 0 && mLastFocusNeedsMenu == needsMenu
4114 && mFocusedApp == mFocusedWindow.getAppToken()) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07004115 return 0;
4116 }
Dianne Hackborne26ab702011-10-16 13:21:33 -07004117 mLastSystemUiFlags = visibility;
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004118 mLastFocusNeedsMenu = needsMenu;
Dianne Hackborne0f085d2011-11-30 18:41:15 -08004119 mFocusedApp = mFocusedWindow.getAppToken();
Dianne Hackborndf89e652011-10-06 22:35:11 -07004120 mHandler.post(new Runnable() {
4121 public void run() {
4122 if (mStatusBarService == null) {
4123 mStatusBarService = IStatusBarService.Stub.asInterface(
4124 ServiceManager.getService("statusbar"));
4125 }
4126 if (mStatusBarService != null) {
4127 try {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07004128 mStatusBarService.setSystemUiVisibility(visibility, 0xffffffff);
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004129 mStatusBarService.topAppWindowChanged(needsMenu);
Dianne Hackborndf89e652011-10-06 22:35:11 -07004130 } catch (RemoteException e) {
4131 // not much to be done
4132 mStatusBarService = null;
Joe Onorato664644d2011-01-23 17:53:23 -08004133 }
4134 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07004135 }
4136 });
4137 return diff;
Joe Onorato664644d2011-01-23 17:53:23 -08004138 }
4139
Daniel Sandler0c4ccff2011-10-19 16:39:14 -04004140 // Use this instead of checking config_showNavigationBar so that it can be consistently
4141 // overridden by qemu.hw.mainkeys in the emulator.
4142 public boolean hasNavigationBar() {
4143 return mHasNavigationBar;
4144 }
4145
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004146 public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
4147 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07004148 pw.print(" mSystemReady="); pw.print(mSystemReady);
4149 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
Jeff Brown2e7760e2012-04-11 15:14:55 -07004150 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004151 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
4152 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
Dianne Hackborne26ab702011-10-16 13:21:33 -07004153 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
4154 || mForceClearedSystemUiFlags != 0) {
4155 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
4156 pw.print(Integer.toHexString(mLastSystemUiFlags));
4157 pw.print(" mResettingSystemUiFlags=0x");
4158 pw.print(Integer.toHexString(mResettingSystemUiFlags));
4159 pw.print(" mForceClearedSystemUiFlags=0x");
4160 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
Dianne Hackborndf89e652011-10-06 22:35:11 -07004161 }
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004162 if (mLastFocusNeedsMenu) {
4163 pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
4164 pw.println(mLastFocusNeedsMenu);
4165 }
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004166 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
4167 pw.print(" mDockMode="); pw.print(mDockMode);
4168 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
4169 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
4170 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
4171 pw.print(" mUserRotation="); pw.print(mUserRotation);
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05004172 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004173 pw.print(prefix); pw.print("mAccelerometerDefault="); pw.print(mAccelerometerDefault);
4174 pw.print(" mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
4175 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
4176 pw.print(mCarDockEnablesAccelerometer);
4177 pw.print(" mDeskDockEnablesAccelerometer=");
4178 pw.println(mDeskDockEnablesAccelerometer);
4179 pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
4180 pw.print(mLidKeyboardAccessibility);
4181 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
Jeff Brownc458ce92012-04-30 14:58:40 -07004182 pw.print(" mLidControlsSleep="); pw.print(mLidControlsSleep);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004183 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07004184 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
4185 pw.print(" mScreenOnFully="); pw.print(mScreenOnFully);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004186 pw.print(" mOrientationSensorEnabled="); pw.print(mOrientationSensorEnabled);
4187 pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
4188 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
4189 pw.print(","); pw.print(mUnrestrictedScreenTop);
4190 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
4191 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
4192 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
4193 pw.print(","); pw.print(mRestrictedScreenTop);
4194 pw.print(") "); pw.print(mRestrictedScreenWidth);
4195 pw.print("x"); pw.println(mRestrictedScreenHeight);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07004196 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
4197 pw.print(","); pw.print(mStableTop);
4198 pw.print(")-("); pw.print(mStableRight);
4199 pw.print(","); pw.print(mStableBottom); pw.println(")");
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004200 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
4201 pw.print(","); pw.print(mCurTop);
4202 pw.print(")-("); pw.print(mCurRight);
4203 pw.print(","); pw.print(mCurBottom); pw.println(")");
4204 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
4205 pw.print(","); pw.print(mContentTop);
4206 pw.print(")-("); pw.print(mContentRight);
4207 pw.print(","); pw.print(mContentBottom); pw.println(")");
4208 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
4209 pw.print(","); pw.print(mDockTop);
4210 pw.print(")-("); pw.print(mDockRight);
4211 pw.print(","); pw.print(mDockBottom); pw.println(")");
4212 pw.print(prefix); pw.print("mDockLayer="); pw.println(mDockLayer);
4213 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
4214 pw.println(mTopFullscreenOpaqueWindowState);
4215 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
4216 pw.print(" mForceStatusBar="); pw.print(mForceStatusBar);
4217 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
4218 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
4219 pw.print(" mHomePressed="); pw.println(mHomePressed);
4220 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
4221 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
4222 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
4223 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
4224 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
4225 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
4226 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
4227 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
4228 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
4229 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
4230 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004231}