blob: cc663c2c5091fcbcd6f113740b4ac89769bfbfc3 [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;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -0700134import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800135import android.view.WindowManagerImpl;
136import android.view.WindowManagerPolicy;
Jeff Brownac143512012-04-05 18:57:33 -0700137import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
138import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
139import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
Jeff Brown6f2fba42011-02-19 01:08:02 -0800140import android.view.KeyCharacterMap.FallbackAction;
Dianne Hackborn295e3c22011-08-25 13:19:08 -0700141import android.view.accessibility.AccessibilityEvent;
Dianne Hackborn01ad2f42009-09-24 19:24:56 -0700142import android.view.animation.Animation;
143import android.view.animation.AnimationUtils;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800144
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800145import java.io.File;
Dianne Hackbornf99f9c52011-01-12 15:49:25 -0800146import java.io.FileDescriptor;
Joe Onoratodc100302011-01-11 17:07:41 -0800147import java.io.FileReader;
148import java.io.IOException;
Dianne Hackbornf99f9c52011-01-12 15:49:25 -0800149import java.io.PrintWriter;
Dianne Hackborn08743722009-12-21 12:16:51 -0800150import java.util.ArrayList;
151
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800152/**
The Android Open Source Project0727d222009-03-11 12:11:58 -0700153 * WindowManagerPolicy implementation for the Android phone UI. This
154 * introduces a new method suffix, Lp, for an internal lock of the
155 * PhoneWindowManager. This is used to protect some internal state, and
156 * can be acquired with either thw Lw and Li lock held, so has the restrictions
157 * of both of those when held.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800158 */
159public class PhoneWindowManager implements WindowManagerPolicy {
160 static final String TAG = "WindowManager";
161 static final boolean DEBUG = false;
Joe Onorato43a17652011-04-06 19:22:23 -0700162 static final boolean localLOGV = false;
The Android Open Source Project11267662009-03-18 17:39:47 -0700163 static final boolean DEBUG_LAYOUT = false;
Jeff Brown49ed71d2010-12-06 17:13:33 -0800164 static final boolean DEBUG_FALLBACK = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800165 static final boolean SHOW_STARTING_ANIMATIONS = true;
166 static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
Joe Onoratod208e702010-10-08 16:22:43 -0400167
Daniel Sandler11ddf532011-11-16 11:10:03 -0800168 // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
169 // No longer recommended for desk docks; still useful in car docks.
170 static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
171 static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
172
Daniel Sandler7e37df52011-11-16 22:08:23 -0800173 // Should screen savers use their own timeout, or the SCREEN_OFF_TIMEOUT?
174 static final boolean SEPARATE_TIMEOUT_FOR_SCREEN_SAVER = false;
175
Joe Onoratod208e702010-10-08 16:22:43 -0400176 static final int LONG_PRESS_POWER_NOTHING = 0;
177 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
178 static final int LONG_PRESS_POWER_SHUT_OFF = 2;
Michael Jurka3b1fc472011-06-13 10:54:40 -0700179
180 // These need to match the documentation/constant in
181 // core/res/res/values/config.xml
Joe Onorato46b0d682010-11-22 17:37:27 -0800182 static final int LONG_PRESS_HOME_NOTHING = 0;
183 static final int LONG_PRESS_HOME_RECENT_DIALOG = 1;
Michael Jurka3b1fc472011-06-13 10:54:40 -0700184 static final int LONG_PRESS_HOME_RECENT_SYSTEM_UI = 2;
Michael Jurka7a348952012-02-27 13:07:58 -0800185 static final int LONG_PRESS_HOME_VOICE_SEARCH = 3;
Joe Onorato46b0d682010-11-22 17:37:27 -0800186
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700187 // wallpaper is at the bottom, though the window manager may move it.
Dianne Hackborn3c3bd442009-08-19 17:09:46 -0700188 static final int WALLPAPER_LAYER = 2;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700189 static final int APPLICATION_LAYER = 2;
190 static final int PHONE_LAYER = 3;
191 static final int SEARCH_BAR_LAYER = 4;
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700192 static final int SYSTEM_DIALOG_LAYER = 5;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800193 // toasts and the plugged-in battery thing
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700194 static final int TOAST_LAYER = 6;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800195 // SIM errors and unlock. Not sure if this really should be in a high layer.
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700196 static final int PRIORITY_PHONE_LAYER = 7;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800197 // like the ANR / app crashed dialogs
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700198 static final int SYSTEM_ALERT_LAYER = 8;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800199 // on-screen keyboards and other such input method user interfaces go here.
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700200 static final int INPUT_METHOD_LAYER = 9;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800201 // on-screen keyboards and other such input method user interfaces go here.
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700202 static final int INPUT_METHOD_DIALOG_LAYER = 10;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800203 // the keyguard; nothing on top of these can take focus, since they are
204 // responsible for power management when displayed.
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700205 static final int KEYGUARD_LAYER = 11;
206 static final int KEYGUARD_DIALOG_LAYER = 12;
Daniel Sandler7d276c32012-01-30 14:33:52 -0500207 // used for Dreams (screensavers with TYPE_DREAM windows)
208 static final int SCREENSAVER_LAYER = 13;
209 static final int STATUS_BAR_SUB_PANEL_LAYER = 14;
210 static final int STATUS_BAR_LAYER = 15;
211 static final int STATUS_BAR_PANEL_LAYER = 16;
Dianne Hackborne8ecde12011-08-03 18:55:19 -0700212 // the on-screen volume indicator and controller shown when the user
213 // changes the device volume
Daniel Sandler7d276c32012-01-30 14:33:52 -0500214 static final int VOLUME_OVERLAY_LAYER = 17;
Jeff Brownbfcb60a2011-09-08 18:51:14 -0700215 // things in here CAN NOT take focus, but are shown on top of everything else.
Daniel Sandler7d276c32012-01-30 14:33:52 -0500216 static final int SYSTEM_OVERLAY_LAYER = 18;
Jeff Brownbfcb60a2011-09-08 18:51:14 -0700217 // the navigation bar, if available, shows atop most things
Daniel Sandler7d276c32012-01-30 14:33:52 -0500218 static final int NAVIGATION_BAR_LAYER = 19;
Dianne Hackborn38cc8962011-10-13 11:33:55 -0700219 // system-level error dialogs
Daniel Sandler7d276c32012-01-30 14:33:52 -0500220 static final int SYSTEM_ERROR_LAYER = 20;
Christopher Tatea53146c2010-09-07 11:57:52 -0700221 // the drag layer: input for drag-and-drop is associated with this window,
222 // which sits above all other focusable windows
Daniel Sandler7d276c32012-01-30 14:33:52 -0500223 static final int DRAG_LAYER = 21;
224 static final int SECURE_SYSTEM_OVERLAY_LAYER = 22;
225 static final int BOOT_PROGRESS_LAYER = 23;
Jeff Brown83c09682010-12-23 17:50:18 -0800226 // the (mouse) pointer layer
Daniel Sandler7d276c32012-01-30 14:33:52 -0500227 static final int POINTER_LAYER = 24;
228 static final int HIDDEN_NAV_CONSUMER_LAYER = 25;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800229
Dianne Hackborn5cb8d792009-05-21 17:34:15 -0700230 static final int APPLICATION_MEDIA_SUBLAYER = -2;
231 static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800232 static final int APPLICATION_PANEL_SUBLAYER = 1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800233 static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800234
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800235 static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
236 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
237 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
Joe Onoratof275f0c2009-11-24 16:11:13 -0500238 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800239
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700240 /**
241 * These are the system UI flags that, when changing, can cause the layout
242 * of the screen to change.
243 */
244 static final int SYSTEM_UI_CHANGING_LAYOUT =
245 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
246
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700247 private static final int BTN_MOUSE = 0x110;
Jeff Brown6651a632011-11-28 12:59:11 -0800248
249 /* Table of Application Launch keys. Maps from key codes to intent categories.
250 *
251 * These are special keys that are used to launch particular kinds of applications,
252 * such as a web browser. HID defines nearly a hundred of them in the Consumer (0x0C)
253 * usage page. We don't support quite that many yet...
254 */
255 static SparseArray<String> sApplicationLaunchKeyCategories;
256 static {
257 sApplicationLaunchKeyCategories = new SparseArray<String>();
258 sApplicationLaunchKeyCategories.append(
259 KeyEvent.KEYCODE_EXPLORER, Intent.CATEGORY_APP_BROWSER);
260 sApplicationLaunchKeyCategories.append(
261 KeyEvent.KEYCODE_ENVELOPE, Intent.CATEGORY_APP_EMAIL);
262 sApplicationLaunchKeyCategories.append(
263 KeyEvent.KEYCODE_CONTACTS, Intent.CATEGORY_APP_CONTACTS);
264 sApplicationLaunchKeyCategories.append(
265 KeyEvent.KEYCODE_CALENDAR, Intent.CATEGORY_APP_CALENDAR);
266 sApplicationLaunchKeyCategories.append(
267 KeyEvent.KEYCODE_MUSIC, Intent.CATEGORY_APP_MUSIC);
268 sApplicationLaunchKeyCategories.append(
269 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
270 }
271
Dianne Hackborndf89e652011-10-06 22:35:11 -0700272 /**
273 * Lock protecting internal state. Must not call out into window
274 * manager with lock held. (This lock will be acquired in places
275 * where the window manager is calling in with its own lock held.)
276 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700277 final Object mLock = new Object();
Dianne Hackborndf89e652011-10-06 22:35:11 -0700278
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800279 Context mContext;
280 IWindowManager mWindowManager;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700281 WindowManagerFuncs mWindowManagerFuncs;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800282 LocalPowerManager mPowerManager;
Joe Onorato93056472010-09-10 10:30:46 -0400283 IStatusBarService mStatusBarService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800284 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
285
Dianne Hackborn181ceb52009-08-27 22:16:40 -0700286 // Vibrator pattern for haptic feedback of a long press.
287 long[] mLongPressVibePattern;
288
289 // Vibrator pattern for haptic feedback of virtual key press.
290 long[] mVirtualKeyVibePattern;
291
Amith Yamasanic33cb712010-02-10 15:21:49 -0800292 // Vibrator pattern for a short vibration.
293 long[] mKeyboardTapVibePattern;
294
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700295 // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
296 long[] mSafeModeDisabledVibePattern;
297
298 // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
299 long[] mSafeModeEnabledVibePattern;
Romain Guy8154cd32010-03-29 14:41:15 -0700300
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800301 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
302 boolean mEnableShiftMenuBugReports = false;
Mike Lockwoodd747dc82011-09-13 16:28:22 -0400303
304 boolean mHeadless;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800305 boolean mSafeMode;
306 WindowState mStatusBar = null;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700307 boolean mHasSystemNavBar;
Dianne Hackborn69cb8752011-05-19 18:13:32 -0700308 int mStatusBarHeight;
Dianne Hackborn7f58b952012-04-18 12:59:29 -0700309 final ArrayList<WindowState> mStatusBarSubPanels = new ArrayList<WindowState>();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400310 WindowState mNavigationBar = null;
Daniel Sandler36412a72011-08-04 09:35:13 -0400311 boolean mHasNavigationBar = false;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700312 boolean mCanHideNavigationBar = false;
Daniel Sandler4a066c52012-04-20 14:49:13 -0400313 boolean mNavigationBarCanMove = false; // can the navigation bar ever move to the side?
314 boolean mNavigationBarOnBottom = true; // is the navigation bar on the bottom *right now*?
315 int[] mNavigationBarHeightForRotation = new int[4];
316 int[] mNavigationBarWidthForRotation = new int[4];
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400317
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800318 WindowState mKeyguard = null;
319 KeyguardViewMediator mKeyguardMediator;
320 GlobalActions mGlobalActions;
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700321 volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
322 boolean mPendingPowerKeyUpCanceled;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800323 Handler mHandler;
Jeff Brown4aed78b2011-01-14 17:36:55 -0800324
Jeff Brown68b909d2011-12-07 16:36:01 -0800325 static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0;
326 static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1;
327 static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 2;
328
329 RecentApplicationsDialog mRecentAppsDialog;
330 int mRecentAppsDialogHeldModifiers;
331
Jeff Brown2e7760e2012-04-11 15:14:55 -0700332 int mLidState = LID_ABSENT;
Jeff Brown4aed78b2011-01-14 17:36:55 -0800333
Dianne Hackbornc777e072010-02-12 13:07:59 -0800334 boolean mSystemReady;
Dianne Hackbornba24e4d2011-09-01 11:17:06 -0700335 boolean mSystemBooted;
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800336 boolean mHdmiPlugged;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700337 int mExternalDisplayWidth;
338 int mExternalDisplayHeight;
Joe Onorato44fcb832011-12-14 20:59:30 -0800339 int mUiMode;
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700340 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700341 int mLidOpenRotation;
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400342 int mCarDockRotation;
343 int mDeskDockRotation;
Erik Gilling9a41ef82011-09-26 19:21:03 -0700344 int mHdmiRotation;
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400345
346 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
347 int mUserRotation = Surface.ROTATION_0;
348
Jeff Brownd3187e32011-09-21 19:26:44 -0700349 int mAllowAllRotations = -1;
Mike Lockwoode9867d22009-09-20 01:59:02 -0400350 boolean mCarDockEnablesAccelerometer;
351 boolean mDeskDockEnablesAccelerometer;
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700352 int mLidKeyboardAccessibility;
353 int mLidNavigationAccessibility;
Joe Onoratod208e702010-10-08 16:22:43 -0400354 int mLongPressOnPowerBehavior = -1;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700355 boolean mScreenOnEarly = false;
356 boolean mScreenOnFully = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800357 boolean mOrientationSensorEnabled = false;
358 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
359 static final int DEFAULT_ACCELEROMETER_ROTATION = 0;
360 int mAccelerometerDefault = DEFAULT_ACCELEROMETER_ROTATION;
361 boolean mHasSoftInput = false;
362
Jeff Brown70825162012-03-28 17:27:48 -0700363 int mPointerLocationMode = 0; // guarded by mLock
Joe Onorato664644d2011-01-23 17:53:23 -0800364
365 // The last window we were told about in focusChanged.
366 WindowState mFocusedWindow;
Dianne Hackborne0f085d2011-11-30 18:41:15 -0800367 IApplicationToken mFocusedApp;
Joe Onorato664644d2011-01-23 17:53:23 -0800368
Jeff Brown70825162012-03-28 17:27:48 -0700369 private static final class PointerLocationInputEventReceiver extends InputEventReceiver {
370 private final PointerLocationView mView;
371
372 public PointerLocationInputEventReceiver(InputChannel inputChannel, Looper looper,
373 PointerLocationView view) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800374 super(inputChannel, looper);
Jeff Brown70825162012-03-28 17:27:48 -0700375 mView = view;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800376 }
377
Jeff Browna41ca772010-08-11 14:46:32 -0700378 @Override
Jeff Brown32cbc38552011-12-01 14:01:49 -0800379 public void onInputEvent(InputEvent event) {
Jeff Brown3915bb82010-11-05 15:02:16 -0700380 boolean handled = false;
381 try {
Jeff Brown4952dfd2011-11-30 19:23:22 -0800382 if (event instanceof MotionEvent
383 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
384 final MotionEvent motionEvent = (MotionEvent)event;
Jeff Brown70825162012-03-28 17:27:48 -0700385 mView.addPointerEvent(motionEvent);
386 handled = true;
Jeff Brown93ed4e32010-09-23 13:51:48 -0700387 }
Jeff Brown3915bb82010-11-05 15:02:16 -0700388 } finally {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800389 finishInputEvent(event, handled);
Jeff Browna41ca772010-08-11 14:46:32 -0700390 }
391 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800392 }
Jeff Brown70825162012-03-28 17:27:48 -0700393
394 // Pointer location view state, only modified on the mHandler Looper.
Jeff Brown32cbc38552011-12-01 14:01:49 -0800395 PointerLocationInputEventReceiver mPointerLocationInputEventReceiver;
Jeff Brown70825162012-03-28 17:27:48 -0700396 PointerLocationView mPointerLocationView;
397 InputChannel mPointerLocationInputChannel;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800398
Joe Onorato29fc2c92010-11-24 10:26:50 -0800399 // The current size of the screen; really; (ir)regardless of whether the status
400 // bar can be hidden or not
401 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
402 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
Dianne Hackborn82de1ae2010-10-28 11:28:39 -0700403 // The current size of the screen; these may be different than (0,0)-(dw,dh)
404 // if the status bar can't be hidden; in that case it effectively carves out
405 // that area of the display from all other windows.
Joe Onorato29fc2c92010-11-24 10:26:50 -0800406 int mRestrictedScreenLeft, mRestrictedScreenTop;
407 int mRestrictedScreenWidth, mRestrictedScreenHeight;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700408 // For applications requesting stable content insets, these are them.
409 int mStableLeft, mStableTop, mStableRight, mStableBottom;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800410 // During layout, the current screen borders with all outer decoration
411 // (status bar, input method dock) accounted for.
412 int mCurLeft, mCurTop, mCurRight, mCurBottom;
413 // During layout, the frame in which content should be displayed
414 // to the user, accounting for all screen decoration except for any
415 // space they deem as available for other content. This is usually
416 // the same as mCur*, but may be larger if the screen decor has supplied
417 // content insets.
418 int mContentLeft, mContentTop, mContentRight, mContentBottom;
Dianne Hackborn8e11ef02010-11-18 19:47:42 -0800419 // During layout, the current screen borders along which input method
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800420 // windows are placed.
421 int mDockLeft, mDockTop, mDockRight, mDockBottom;
422 // During layout, the layer at which the doc window is placed.
423 int mDockLayer;
Dianne Hackborne26ab702011-10-16 13:21:33 -0700424 int mLastSystemUiFlags;
425 // Bits that we are in the process of clearing, so we want to prevent
426 // them from being set by applications until everything has been updated
427 // to have them clear.
428 int mResettingSystemUiFlags = 0;
429 // Bits that we are currently always keeping cleared.
430 int mForceClearedSystemUiFlags = 0;
Dianne Hackborn4eff8d32011-11-10 19:38:40 -0800431 // What we last reported to system UI about whether the compatibility
432 // menu needs to be displayed.
433 boolean mLastFocusNeedsMenu = false;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700434
435 FakeWindow mHideNavFakeWindow = null;
436
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800437 static final Rect mTmpParentFrame = new Rect();
438 static final Rect mTmpDisplayFrame = new Rect();
439 static final Rect mTmpContentFrame = new Rect();
440 static final Rect mTmpVisibleFrame = new Rect();
Dianne Hackborn1f903c32011-09-13 19:18:06 -0700441 static final Rect mTmpNavigationFrame = new Rect();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800442
443 WindowState mTopFullscreenOpaqueWindowState;
Joe Onorato93056472010-09-10 10:30:46 -0400444 boolean mTopIsFullscreen;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800445 boolean mForceStatusBar;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700446 boolean mHideLockScreen;
447 boolean mDismissKeyguard;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800448 boolean mHomePressed;
Michael Jurka7f2668c2012-03-27 07:49:52 -0700449 boolean mHomeLongPressed;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800450 Intent mHomeIntent;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700451 Intent mCarDockIntent;
452 Intent mDeskDockIntent;
Jeff Brown49ed71d2010-12-06 17:13:33 -0800453 int mShortcutKeyPressed = -1;
454 boolean mConsumeShortcutKeyUp;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800455
Mike Lockwood28569302010-01-28 11:54:40 -0500456 // support for activating the lock screen while the screen is on
457 boolean mAllowLockscreenWhenOn;
458 int mLockScreenTimeout;
459 boolean mLockScreenTimerActive;
460
Daniel Sandler0601eb72011-04-13 01:01:32 -0400461 // visual screen saver support
Daniel Sandler7d276c32012-01-30 14:33:52 -0500462 boolean mScreenSaverFeatureAvailable;
Daniel Sandlere5f2cfe2011-11-02 23:30:58 -0400463 int mScreenSaverTimeout = 0;
Daniel Sandler2d545362011-11-17 10:38:37 -0800464 boolean mScreenSaverEnabledByUser = false;
465 boolean mScreenSaverMayRun = true; // false if a wakelock is held
Daniel Sandler7e37df52011-11-16 22:08:23 -0800466 boolean mPluggedIn;
Daniel Sandler0601eb72011-04-13 01:01:32 -0400467
David Brownbaf8d092010-03-08 21:52:59 -0800468 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800469 int mEndcallBehavior;
David Brownbaf8d092010-03-08 21:52:59 -0800470
471 // Behavior of POWER button while in-call and screen on.
472 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
473 int mIncallPowerBehavior;
474
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700475 Display mDisplay;
476
Dianne Hackborn9d132642011-04-21 17:26:39 -0700477 int mLandscapeRotation = 0; // default landscape rotation
478 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation
479 int mPortraitRotation = 0; // default portrait rotation
480 int mUpsideDownRotation = 0; // "other" portrait rotation
Mitsuru Oshima831d0d92009-06-16 18:27:18 -0700481
Joe Onorato46b0d682010-11-22 17:37:27 -0800482 // What we do when the user long presses on home
483 private int mLongPressOnHomeBehavior = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800484
Winson Chung9112ec32011-06-27 13:15:32 -0700485 // Screenshot trigger states
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700486 // Time to volume and power must be pressed within this interval of each other.
487 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
Christopher Tatee90585f2012-03-05 18:56:25 -0800488 private boolean mScreenshotChordEnabled;
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700489 private boolean mVolumeDownKeyTriggered;
490 private long mVolumeDownKeyTime;
491 private boolean mVolumeDownKeyConsumedByScreenshotChord;
492 private boolean mVolumeUpKeyTriggered;
493 private boolean mPowerKeyTriggered;
494 private long mPowerKeyTime;
Winson Chung9112ec32011-06-27 13:15:32 -0700495
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800496 ShortcutManager mShortcutManager;
497 PowerManager.WakeLock mBroadcastWakeLock;
498
Jeff Brown49ed71d2010-12-06 17:13:33 -0800499 final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction();
500
Jeff Brown70825162012-03-28 17:27:48 -0700501 private static final int MSG_ENABLE_POINTER_LOCATION = 1;
502 private static final int MSG_DISABLE_POINTER_LOCATION = 2;
503
504 private class PolicyHandler extends Handler {
505 @Override
506 public void handleMessage(Message msg) {
507 switch (msg.what) {
508 case MSG_ENABLE_POINTER_LOCATION:
509 enablePointerLocation();
510 break;
511 case MSG_DISABLE_POINTER_LOCATION:
512 disablePointerLocation();
513 break;
514 }
515 }
516 }
517
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800518 private UEventObserver mHDMIObserver = new UEventObserver() {
519 @Override
520 public void onUEvent(UEventObserver.UEvent event) {
521 setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
522 }
523 };
524
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800525 class SettingsObserver extends ContentObserver {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800526 SettingsObserver(Handler handler) {
527 super(handler);
528 }
David Brownbaf8d092010-03-08 21:52:59 -0800529
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800530 void observe() {
531 ContentResolver resolver = mContext.getContentResolver();
532 resolver.registerContentObserver(Settings.System.getUriFor(
533 Settings.System.END_BUTTON_BEHAVIOR), false, this);
David Brownbaf8d092010-03-08 21:52:59 -0800534 resolver.registerContentObserver(Settings.Secure.getUriFor(
535 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800536 resolver.registerContentObserver(Settings.System.getUriFor(
537 Settings.System.ACCELEROMETER_ROTATION), false, this);
Mike Lockwood28569302010-01-28 11:54:40 -0500538 resolver.registerContentObserver(Settings.System.getUriFor(
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400539 Settings.System.USER_ROTATION), false, this);
540 resolver.registerContentObserver(Settings.System.getUriFor(
Mike Lockwood28569302010-01-28 11:54:40 -0500541 Settings.System.SCREEN_OFF_TIMEOUT), false, this);
Dianne Hackbornc777e072010-02-12 13:07:59 -0800542 resolver.registerContentObserver(Settings.System.getUriFor(
Jeff Brown4519f072011-01-23 13:16:01 -0800543 Settings.System.WINDOW_ORIENTATION_LISTENER_LOG), false, this);
544 resolver.registerContentObserver(Settings.System.getUriFor(
Dianne Hackbornc777e072010-02-12 13:07:59 -0800545 Settings.System.POINTER_LOCATION), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800546 resolver.registerContentObserver(Settings.Secure.getUriFor(
547 Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700548 resolver.registerContentObserver(Settings.System.getUriFor(
549 "fancy_rotation_anim"), false, this);
Daniel Sandler2d545362011-11-17 10:38:37 -0800550 resolver.registerContentObserver(Settings.Secure.getUriFor(
551 Settings.Secure.SCREENSAVER_ENABLED), false, this);
Daniel Sandler7e37df52011-11-16 22:08:23 -0800552 if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
553 resolver.registerContentObserver(Settings.Secure.getUriFor(
Daniel Sandler2d545362011-11-17 10:38:37 -0800554 "screensaver_timeout"), false, this);
Daniel Sandler7e37df52011-11-16 22:08:23 -0800555 } // otherwise SCREEN_OFF_TIMEOUT will do nicely
Dianne Hackbornc777e072010-02-12 13:07:59 -0800556 updateSettings();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800557 }
558
559 @Override public void onChange(boolean selfChange) {
Dianne Hackbornc777e072010-02-12 13:07:59 -0800560 updateSettings();
Jeff Brown01a98dd2011-09-20 15:08:29 -0700561 updateRotation(false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800562 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800563 }
564
565 class MyOrientationListener extends WindowOrientationListener {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800566 MyOrientationListener(Context context) {
567 super(context);
568 }
569
570 @Override
Jeff Brownc0347aa2011-09-23 17:26:09 -0700571 public void onProposedRotationChanged(int rotation) {
572 if (localLOGV) Log.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
Jeff Brown01a98dd2011-09-20 15:08:29 -0700573 updateRotation(false);
574 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800575 }
576 MyOrientationListener mOrientationListener;
577
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700578 /*
579 * We always let the sensor be switched on by default except when
580 * the user has explicitly disabled sensor based rotation or when the
581 * screen is switched off.
582 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700583 boolean needSensorRunningLp() {
Dianne Hackborne5439f22010-10-02 16:53:50 -0700584 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
585 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
586 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
587 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800588 // If the application has explicitly requested to follow the
589 // orientation, then we need to turn the sensor or.
590 return true;
591 }
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700592 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
Jeff Brown1a693182011-11-08 14:44:16 -0800593 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
594 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
595 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
Mike Lockwoode9867d22009-09-20 01:59:02 -0400596 // enable accelerometer if we are docked in a dock that enables accelerometer
597 // orientation management,
598 return true;
599 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700600 if (mAccelerometerDefault == 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800601 // If the setting for using the sensor by default is enabled, then
602 // we will always leave it on. Note that the user could go to
603 // a window that forces an orientation that does not use the
604 // sensor and in theory we could turn it off... however, when next
605 // turning it on we won't have a good value for the current
606 // orientation for a little bit, which can cause orientation
607 // changes to lag, so we'd like to keep it always on. (It will
608 // still be turned off when the screen is off.)
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700609 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800610 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700611 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800612 }
613
614 /*
615 * Various use cases for invoking this function
616 * screen turning off, should always disable listeners if already enabled
617 * screen turned on and current app has sensor based orientation, enable listeners
618 * if not already enabled
619 * screen turned on and current app does not have sensor orientation, disable listeners if
620 * already enabled
621 * screen turning on and current app has sensor based orientation, enable listeners if needed
622 * screen turning on and current app has nosensor based orientation, do nothing
623 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700624 void updateOrientationListenerLp() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800625 if (!mOrientationListener.canDetectOrientation()) {
626 // If sensor is turned off or nonexistent for some reason
627 return;
628 }
629 //Could have been invoked due to screen turning on or off or
630 //change of the currently visible window's orientation
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700631 if (localLOGV) Log.v(TAG, "Screen status="+mScreenOnEarly+
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800632 ", current orientation="+mCurrentAppOrientation+
633 ", SensorEnabled="+mOrientationSensorEnabled);
634 boolean disable = true;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700635 if (mScreenOnEarly) {
The Android Open Source Project0727d222009-03-11 12:11:58 -0700636 if (needSensorRunningLp()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800637 disable = false;
638 //enable listener if not already enabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700639 if (!mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800640 mOrientationListener.enable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700641 if(localLOGV) Log.v(TAG, "Enabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800642 mOrientationSensorEnabled = true;
643 }
644 }
645 }
646 //check if sensors need to be disabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700647 if (disable && mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800648 mOrientationListener.disable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700649 if(localLOGV) Log.v(TAG, "Disabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800650 mOrientationSensorEnabled = false;
651 }
652 }
653
Jeff Brown4d396052010-10-29 21:50:21 -0700654 private void interceptPowerKeyDown(boolean handled) {
655 mPowerKeyHandled = handled;
656 if (!handled) {
657 mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
658 }
659 }
660
661 private boolean interceptPowerKeyUp(boolean canceled) {
662 if (!mPowerKeyHandled) {
663 mHandler.removeCallbacks(mPowerLongPress);
664 return !canceled;
Jeff Brown4d396052010-10-29 21:50:21 -0700665 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700666 return false;
667 }
668
669 private void cancelPendingPowerKeyAction() {
670 if (!mPowerKeyHandled) {
671 mHandler.removeCallbacks(mPowerLongPress);
672 }
Jeff Brownff204712011-10-25 21:27:54 -0700673 if (mPowerKeyTriggered) {
674 mPendingPowerKeyUpCanceled = true;
675 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700676 }
677
678 private void interceptScreenshotChord() {
Christopher Tatee90585f2012-03-05 18:56:25 -0800679 if (mScreenshotChordEnabled
680 && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700681 final long now = SystemClock.uptimeMillis();
682 if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
683 && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
684 mVolumeDownKeyConsumedByScreenshotChord = true;
685 cancelPendingPowerKeyAction();
686
687 mHandler.postDelayed(mScreenshotChordLongPress,
688 ViewConfiguration.getGlobalActionKeyTimeout());
689 }
690 }
691 }
692
693 private void cancelPendingScreenshotChordAction() {
694 mHandler.removeCallbacks(mScreenshotChordLongPress);
Jeff Brown4d396052010-10-29 21:50:21 -0700695 }
696
697 private final Runnable mPowerLongPress = new Runnable() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800698 public void run() {
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700699 // The context isn't read
700 if (mLongPressOnPowerBehavior < 0) {
701 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
702 com.android.internal.R.integer.config_longPressOnPowerBehavior);
Joe Onoratod208e702010-10-08 16:22:43 -0400703 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700704 switch (mLongPressOnPowerBehavior) {
705 case LONG_PRESS_POWER_NOTHING:
706 break;
707 case LONG_PRESS_POWER_GLOBAL_ACTIONS:
708 mPowerKeyHandled = true;
709 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
710 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
711 showGlobalActionsDialog();
712 break;
713 case LONG_PRESS_POWER_SHUT_OFF:
714 mPowerKeyHandled = true;
715 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
716 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
717 ShutdownThread.shutdown(mContext, true);
718 break;
719 }
720 }
721 };
722
723 private final Runnable mScreenshotChordLongPress = new Runnable() {
724 public void run() {
725 takeScreenshot();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800726 }
727 };
728
729 void showGlobalActionsDialog() {
730 if (mGlobalActions == null) {
731 mGlobalActions = new GlobalActions(mContext);
732 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -0700733 final boolean keyguardShowing = keyguardIsShowingTq();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800734 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
735 if (keyguardShowing) {
736 // since it took two seconds of long press to bring this up,
737 // poke the wake lock so they have some time to see the dialog.
738 mKeyguardMediator.pokeWakelock();
739 }
740 }
741
742 boolean isDeviceProvisioned() {
743 return Settings.Secure.getInt(
744 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
745 }
746
Patrick Dubroyece94522011-02-23 18:35:01 -0800747 private void handleLongPressOnHome() {
Jim Milleree969aa2010-08-26 20:17:43 -0700748 // We can't initialize this in init() since the configuration hasn't been loaded yet.
Joe Onorato46b0d682010-11-22 17:37:27 -0800749 if (mLongPressOnHomeBehavior < 0) {
750 mLongPressOnHomeBehavior
Joe Onorato50262e52010-11-26 14:04:54 -0800751 = mContext.getResources().getInteger(R.integer.config_longPressOnHomeBehavior);
Joe Onorato46b0d682010-11-22 17:37:27 -0800752 if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
Michael Jurka3b1fc472011-06-13 10:54:40 -0700753 mLongPressOnHomeBehavior > LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
Joe Onorato46b0d682010-11-22 17:37:27 -0800754 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
755 }
Michael Jurka7a348952012-02-27 13:07:58 -0800756 if (hasNavigationBar()) {
757 mLongPressOnHomeBehavior = LONG_PRESS_HOME_VOICE_SEARCH;
758 }
Joe Onorato46b0d682010-11-22 17:37:27 -0800759 }
760
761 if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
762 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
763 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
Patrick Dubroyece94522011-02-23 18:35:01 -0800764
765 // Eat the longpress so it won't dismiss the recent apps dialog when
766 // the user lets go of the home key
Michael Jurka7f2668c2012-03-27 07:49:52 -0700767 mHomeLongPressed = true;
Jim Milleree969aa2010-08-26 20:17:43 -0700768 }
Patrick Dubroyece94522011-02-23 18:35:01 -0800769
Joe Onorato46b0d682010-11-22 17:37:27 -0800770 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
Jeff Brown68b909d2011-12-07 16:36:01 -0800771 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
Michael Jurka3b1fc472011-06-13 10:54:40 -0700772 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
Jim Millere6ad1a82010-08-20 19:25:39 -0700773 try {
Michael Jurka3b1fc472011-06-13 10:54:40 -0700774 mStatusBarService.toggleRecentApps();
775 } catch (RemoteException e) {
776 Slog.e(TAG, "RemoteException when showing recent apps", e);
Jim Millere6ad1a82010-08-20 19:25:39 -0700777 }
Michael Jurka7a348952012-02-27 13:07:58 -0800778 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_VOICE_SEARCH) {
779 Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
780 try {
781 intent.setFlags(
782 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
783 mContext.startActivity(intent);
784 } catch (ActivityNotFoundException e) {
785 Log.e(TAG, "Unable to launch. tag=" + TAG + " intent=" + intent, e);
786 } catch (SecurityException e) {
787 Log.e(TAG, "PhoneWindowManager does not have the permission to launch " +
788 "tag=" + TAG + " intent=" + intent, e);
789 }
Jim Millere6ad1a82010-08-20 19:25:39 -0700790 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800791 }
Patrick Dubroyece94522011-02-23 18:35:01 -0800792
793 /**
Jeff Brown68b909d2011-12-07 16:36:01 -0800794 * Create (if necessary) and show or dismiss the recent apps dialog according
795 * according to the requested behavior.
Patrick Dubroyece94522011-02-23 18:35:01 -0800796 */
Jeff Brown68b909d2011-12-07 16:36:01 -0800797 void showOrHideRecentAppsDialog(final int behavior) {
Jeff Brownda3d5a92011-03-29 15:11:34 -0700798 mHandler.post(new Runnable() {
799 @Override
800 public void run() {
801 if (mRecentAppsDialog == null) {
Jeff Brown54875002011-04-06 15:33:01 -0700802 mRecentAppsDialog = new RecentApplicationsDialog(mContext);
Jeff Brownda3d5a92011-03-29 15:11:34 -0700803 }
Jeff Brown54875002011-04-06 15:33:01 -0700804 if (mRecentAppsDialog.isShowing()) {
Jeff Brown68b909d2011-12-07 16:36:01 -0800805 switch (behavior) {
806 case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
807 mRecentAppsDialog.dismiss();
808 break;
809 case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
810 mRecentAppsDialog.dismissAndSwitch();
811 break;
812 case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
813 default:
814 break;
Jeff Brown54875002011-04-06 15:33:01 -0700815 }
816 } else {
Jeff Brown68b909d2011-12-07 16:36:01 -0800817 switch (behavior) {
818 case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
819 mRecentAppsDialog.show();
820 break;
821 case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
822 try {
823 mWindowManager.setInTouchMode(false);
824 } catch (RemoteException e) {
825 }
826 mRecentAppsDialog.show();
827 break;
828 case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
829 default:
830 break;
831 }
Jeff Brown54875002011-04-06 15:33:01 -0700832 }
Jeff Brownda3d5a92011-03-29 15:11:34 -0700833 }
834 });
Patrick Dubroyece94522011-02-23 18:35:01 -0800835 }
Jeff Brownda3d5a92011-03-29 15:11:34 -0700836
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800837 /** {@inheritDoc} */
838 public void init(Context context, IWindowManager windowManager,
Dianne Hackborndf89e652011-10-06 22:35:11 -0700839 WindowManagerFuncs windowManagerFuncs,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800840 LocalPowerManager powerManager) {
841 mContext = context;
842 mWindowManager = windowManager;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700843 mWindowManagerFuncs = windowManagerFuncs;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800844 mPowerManager = powerManager;
Mike Lockwoodd747dc82011-09-13 16:28:22 -0400845 mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
846 if (!mHeadless) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -0700847 // don't create KeyguardViewMediator if headless
848 mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
849 }
Jeff Brown70825162012-03-28 17:27:48 -0700850 mHandler = new PolicyHandler();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800851 mOrientationListener = new MyOrientationListener(mContext);
Jeff Brownc0347aa2011-09-23 17:26:09 -0700852 try {
853 mOrientationListener.setCurrentRotation(windowManager.getRotation());
854 } catch (RemoteException ex) { }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800855 SettingsObserver settingsObserver = new SettingsObserver(mHandler);
856 settingsObserver.observe();
857 mShortcutManager = new ShortcutManager(context, mHandler);
858 mShortcutManager.observe();
Joe Onorato44fcb832011-12-14 20:59:30 -0800859 mUiMode = context.getResources().getInteger(
860 com.android.internal.R.integer.config_defaultUiModeType);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800861 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
862 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
863 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
864 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700865 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
866 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
867 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
868 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
869 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
870 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
871 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
872 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Jim Millere6ad1a82010-08-20 19:25:39 -0700873
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800874 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
875 mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
876 "PhoneWindowManager.mBroadcastWakeLock");
877 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700878 mLidOpenRotation = readRotation(
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400879 com.android.internal.R.integer.config_lidOpenRotation);
880 mCarDockRotation = readRotation(
881 com.android.internal.R.integer.config_carDockRotation);
882 mDeskDockRotation = readRotation(
883 com.android.internal.R.integer.config_deskDockRotation);
Mike Lockwoode9867d22009-09-20 01:59:02 -0400884 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
885 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
886 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
887 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700888 mLidKeyboardAccessibility = mContext.getResources().getInteger(
889 com.android.internal.R.integer.config_lidKeyboardAccessibility);
890 mLidNavigationAccessibility = mContext.getResources().getInteger(
891 com.android.internal.R.integer.config_lidNavigationAccessibility);
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700892 // register for dock events
Dianne Hackborn78968392010-03-04 20:47:56 -0800893 IntentFilter filter = new IntentFilter();
894 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
895 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
896 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
897 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700898 filter.addAction(Intent.ACTION_DOCK_EVENT);
899 Intent intent = context.registerReceiver(mDockReceiver, filter);
900 if (intent != null) {
901 // Retrieve current sticky dock event broadcast.
902 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
903 Intent.EXTRA_DOCK_STATE_UNDOCKED);
904 }
Daniel Sandler7e37df52011-11-16 22:08:23 -0800905
906 // watch the plug to know whether to trigger the screen saver
907 filter = new IntentFilter();
908 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
909 intent = context.registerReceiver(mPowerReceiver, filter);
910 if (intent != null) {
911 mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
912 }
913
Jeff Brownc2346132012-04-13 01:55:38 -0700914 mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700915 mLongPressVibePattern = getLongIntArray(mContext.getResources(),
916 com.android.internal.R.array.config_longPressVibePattern);
917 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
918 com.android.internal.R.array.config_virtualKeyVibePattern);
Amith Yamasanic33cb712010-02-10 15:21:49 -0800919 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
920 com.android.internal.R.array.config_keyboardTapVibePattern);
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700921 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
922 com.android.internal.R.array.config_safeModeDisabledVibePattern);
923 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
924 com.android.internal.R.array.config_safeModeEnabledVibePattern);
Daniel Sandler40427442010-07-16 11:44:52 -0400925
Christopher Tatee90585f2012-03-05 18:56:25 -0800926 mScreenshotChordEnabled = mContext.getResources().getBoolean(
927 com.android.internal.R.bool.config_enableScreenshotChord);
928
Joe Onoratoea495d42011-04-06 11:41:11 -0700929 // Controls rotation and the like.
930 initializeHdmiState();
Dianne Hackborn40011092011-09-22 13:37:48 -0700931
932 // Match current screen state.
933 if (mPowerManager.isScreenOn()) {
934 screenTurningOn(null);
935 } else {
936 screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
937 }
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700938 }
939
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700940 public void setInitialDisplaySize(Display display, int width, int height) {
941 mDisplay = display;
942
943 int shortSize, longSize;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700944 if (width > height) {
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700945 shortSize = height;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700946 longSize = width;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700947 mLandscapeRotation = Surface.ROTATION_0;
948 mSeascapeRotation = Surface.ROTATION_180;
949 if (mContext.getResources().getBoolean(
950 com.android.internal.R.bool.config_reverseDefaultRotation)) {
951 mPortraitRotation = Surface.ROTATION_90;
952 mUpsideDownRotation = Surface.ROTATION_270;
953 } else {
954 mPortraitRotation = Surface.ROTATION_270;
955 mUpsideDownRotation = Surface.ROTATION_90;
956 }
957 } else {
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700958 shortSize = width;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700959 longSize = height;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700960 mPortraitRotation = Surface.ROTATION_0;
961 mUpsideDownRotation = Surface.ROTATION_180;
962 if (mContext.getResources().getBoolean(
963 com.android.internal.R.bool.config_reverseDefaultRotation)) {
964 mLandscapeRotation = Surface.ROTATION_270;
965 mSeascapeRotation = Surface.ROTATION_90;
966 } else {
967 mLandscapeRotation = Surface.ROTATION_90;
968 mSeascapeRotation = Surface.ROTATION_270;
969 }
970 }
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700971
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700972 mExternalDisplayWidth = mDisplay.getRawExternalWidth();
973 mExternalDisplayHeight = mDisplay.getRawExternalHeight();
974
975 mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
976 com.android.internal.R.dimen.status_bar_height);
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700977
Daniel Sandler4a066c52012-04-20 14:49:13 -0400978 mNavigationBarHeightForRotation[Surface.ROTATION_0] =
979 mNavigationBarHeightForRotation[Surface.ROTATION_90] =
980 mNavigationBarHeightForRotation[Surface.ROTATION_180] =
981 mNavigationBarHeightForRotation[Surface.ROTATION_270] =
982 mContext.getResources().getDimensionPixelSize(
983 com.android.internal.R.dimen.navigation_bar_height);
984 mNavigationBarWidthForRotation[Surface.ROTATION_0] =
985 mNavigationBarWidthForRotation[Surface.ROTATION_90] =
986 mNavigationBarWidthForRotation[Surface.ROTATION_180] =
987 mNavigationBarWidthForRotation[Surface.ROTATION_270] =
988 mContext.getResources().getDimensionPixelSize(
989 com.android.internal.R.dimen.navigation_bar_width);
990
991 // SystemUI (status bar) layout policy
Daniel Sandler631cb3d52011-06-03 01:25:43 -0400992 int shortSizeDp = shortSize
993 * DisplayMetrics.DENSITY_DEFAULT
994 / DisplayMetrics.DENSITY_DEVICE;
Daniel Sandler4a066c52012-04-20 14:49:13 -0400995
996 if (shortSizeDp < 600) {
997 // 0-599dp: "phone" UI with a separate status & navigation bar
998 mHasSystemNavBar = false;
999 mNavigationBarCanMove = true;
1000 } else if (shortSizeDp < 720) {
1001 // 600-719dp: "phone" UI with modifications for larger screens
1002 mHasSystemNavBar = false;
1003 mNavigationBarCanMove = false;
1004 } else {
1005 // 720dp: "tablet" UI with a single combined status & navigation bar
1006 mHasSystemNavBar = true;
1007 mNavigationBarCanMove = false;
1008 }
Daniel Sandler36412a72011-08-04 09:35:13 -04001009
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001010 if (!mHasSystemNavBar) {
1011 mHasNavigationBar = mContext.getResources().getBoolean(
1012 com.android.internal.R.bool.config_showNavigationBar);
1013 // Allow a system property to override this. Used by the emulator.
1014 // See also hasNavigationBar().
1015 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
1016 if (! "".equals(navBarOverride)) {
1017 if (navBarOverride.equals("1")) mHasNavigationBar = false;
1018 else if (navBarOverride.equals("0")) mHasNavigationBar = true;
1019 }
1020 } else {
1021 mHasNavigationBar = false;
Daniel Sandler0c4ccff2011-10-19 16:39:14 -04001022 }
1023
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001024 if (mHasSystemNavBar) {
1025 // The system bar is always at the bottom. If you are watching
1026 // a video in landscape, we don't need to hide it if we can still
1027 // show a 16:9 aspect ratio with it.
1028 int longSizeDp = longSize
1029 * DisplayMetrics.DENSITY_DEFAULT
1030 / DisplayMetrics.DENSITY_DEVICE;
Daniel Sandler4a066c52012-04-20 14:49:13 -04001031 int barHeightDp = mNavigationBarHeightForRotation[mLandscapeRotation]
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001032 * DisplayMetrics.DENSITY_DEFAULT
1033 / DisplayMetrics.DENSITY_DEVICE;
1034 int aspect = ((shortSizeDp-barHeightDp) * 16) / longSizeDp;
1035 // We have computed the aspect ratio with the bar height taken
1036 // out to be 16:aspect. If this is less than 9, then hiding
1037 // the navigation bar will provide more useful space for wide
1038 // screen movies.
1039 mCanHideNavigationBar = aspect < 9;
1040 } else if (mHasNavigationBar) {
1041 // The navigation bar is at the right in landscape; it seems always
1042 // useful to hide it for showing a video.
1043 mCanHideNavigationBar = true;
1044 } else {
1045 mCanHideNavigationBar = false;
1046 }
Erik Gilling9a41ef82011-09-26 19:21:03 -07001047
1048 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
1049 mHdmiRotation = mPortraitRotation;
1050 } else {
1051 mHdmiRotation = mLandscapeRotation;
1052 }
Dianne Hackborn9d132642011-04-21 17:26:39 -07001053 }
1054
Dianne Hackbornc777e072010-02-12 13:07:59 -08001055 public void updateSettings() {
1056 ContentResolver resolver = mContext.getContentResolver();
1057 boolean updateRotation = false;
Dianne Hackbornc777e072010-02-12 13:07:59 -08001058 synchronized (mLock) {
1059 mEndcallBehavior = Settings.System.getInt(resolver,
David Brownbaf8d092010-03-08 21:52:59 -08001060 Settings.System.END_BUTTON_BEHAVIOR,
1061 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT);
1062 mIncallPowerBehavior = Settings.Secure.getInt(resolver,
1063 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
1064 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001065 int accelerometerDefault = Settings.System.getInt(resolver,
1066 Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001067
1068 // set up rotation lock state
Daniel Sandler1b815d62010-11-05 10:24:27 -04001069 mUserRotationMode = (accelerometerDefault == 0)
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001070 ? WindowManagerPolicy.USER_ROTATION_LOCKED
1071 : WindowManagerPolicy.USER_ROTATION_FREE;
1072 mUserRotation = Settings.System.getInt(resolver,
1073 Settings.System.USER_ROTATION,
1074 Surface.ROTATION_0);
1075
Dianne Hackbornc777e072010-02-12 13:07:59 -08001076 if (mAccelerometerDefault != accelerometerDefault) {
1077 mAccelerometerDefault = accelerometerDefault;
1078 updateOrientationListenerLp();
1079 }
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001080
Jeff Brown4519f072011-01-23 13:16:01 -08001081 mOrientationListener.setLogEnabled(
1082 Settings.System.getInt(resolver,
1083 Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, 0) != 0);
1084
Dianne Hackbornc777e072010-02-12 13:07:59 -08001085 if (mSystemReady) {
1086 int pointerLocation = Settings.System.getInt(resolver,
1087 Settings.System.POINTER_LOCATION, 0);
1088 if (mPointerLocationMode != pointerLocation) {
1089 mPointerLocationMode = pointerLocation;
Jeff Brown70825162012-03-28 17:27:48 -07001090 mHandler.sendEmptyMessage(pointerLocation != 0 ?
1091 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001092 }
1093 }
1094 // use screen off timeout setting as the timeout for the lockscreen
1095 mLockScreenTimeout = Settings.System.getInt(resolver,
1096 Settings.System.SCREEN_OFF_TIMEOUT, 0);
1097 String imId = Settings.Secure.getString(resolver,
1098 Settings.Secure.DEFAULT_INPUT_METHOD);
1099 boolean hasSoftInput = imId != null && imId.length() > 0;
1100 if (mHasSoftInput != hasSoftInput) {
1101 mHasSoftInput = hasSoftInput;
1102 updateRotation = true;
1103 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04001104
Daniel Sandler7d276c32012-01-30 14:33:52 -05001105 // dreams
1106 mScreenSaverFeatureAvailable = mContext.getResources().getBoolean(
1107 com.android.internal.R.bool.config_enableDreams);
1108
Daniel Sandler2d545362011-11-17 10:38:37 -08001109 mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver,
1110 Settings.Secure.SCREENSAVER_ENABLED, 1);
1111
Daniel Sandler7e37df52011-11-16 22:08:23 -08001112 if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
1113 mScreenSaverTimeout = Settings.Secure.getInt(resolver,
Daniel Sandler2d545362011-11-17 10:38:37 -08001114 "screensaver_timeout", 0);
Daniel Sandler7e37df52011-11-16 22:08:23 -08001115 } else {
1116 mScreenSaverTimeout = Settings.System.getInt(resolver,
1117 Settings.System.SCREEN_OFF_TIMEOUT, 0);
1118 if (mScreenSaverTimeout > 0) {
1119 // We actually want to activate the screensaver just before the
1120 // power manager's screen timeout
1121 mScreenSaverTimeout -= 5000;
1122 }
1123 }
Dianne Hackbornc777e072010-02-12 13:07:59 -08001124 }
1125 if (updateRotation) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07001126 updateRotation(true);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001127 }
Jeff Brown70825162012-03-28 17:27:48 -07001128 }
1129
1130 private void enablePointerLocation() {
1131 if (mPointerLocationView == null) {
1132 mPointerLocationView = new PointerLocationView(mContext);
1133 mPointerLocationView.setPrintCoords(false);
1134
Dianne Hackbornc777e072010-02-12 13:07:59 -08001135 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
1136 WindowManager.LayoutParams.MATCH_PARENT,
1137 WindowManager.LayoutParams.MATCH_PARENT);
Jeff Brown3b2b3542010-10-15 00:54:27 -07001138 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
Jeff Brownbfcb60a2011-09-08 18:51:14 -07001139 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
1140 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
1141 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1142 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Dianne Hackbornc777e072010-02-12 13:07:59 -08001143 lp.format = PixelFormat.TRANSLUCENT;
1144 lp.setTitle("PointerLocation");
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001145 WindowManager wm = (WindowManager)
Dianne Hackbornc777e072010-02-12 13:07:59 -08001146 mContext.getSystemService(Context.WINDOW_SERVICE);
Jeff Browncc4f7db2011-08-30 20:34:48 -07001147 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
Jeff Brown70825162012-03-28 17:27:48 -07001148 wm.addView(mPointerLocationView, lp);
1149
Jeff Brownac143512012-04-05 18:57:33 -07001150 mPointerLocationInputChannel =
1151 mWindowManagerFuncs.monitorInput("PointerLocationView");
1152 mPointerLocationInputEventReceiver =
1153 new PointerLocationInputEventReceiver(mPointerLocationInputChannel,
1154 Looper.myLooper(), mPointerLocationView);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001155 }
Dianne Hackbornc777e072010-02-12 13:07:59 -08001156 }
Jeff Brown70825162012-03-28 17:27:48 -07001157
1158 private void disablePointerLocation() {
1159 if (mPointerLocationInputEventReceiver != null) {
1160 mPointerLocationInputEventReceiver.dispose();
1161 mPointerLocationInputEventReceiver = null;
1162 }
1163
1164 if (mPointerLocationInputChannel != null) {
1165 mPointerLocationInputChannel.dispose();
1166 mPointerLocationInputChannel = null;
1167 }
1168
1169 if (mPointerLocationView != null) {
1170 WindowManager wm = (WindowManager)
1171 mContext.getSystemService(Context.WINDOW_SERVICE);
1172 wm.removeView(mPointerLocationView);
1173 mPointerLocationView = null;
1174 }
1175 }
1176
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001177 private int readRotation(int resID) {
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001178 try {
1179 int rotation = mContext.getResources().getInteger(resID);
1180 switch (rotation) {
1181 case 0:
1182 return Surface.ROTATION_0;
1183 case 90:
1184 return Surface.ROTATION_90;
1185 case 180:
1186 return Surface.ROTATION_180;
1187 case 270:
1188 return Surface.ROTATION_270;
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001189 }
1190 } catch (Resources.NotFoundException e) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001191 // fall through
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001192 }
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001193 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001194 }
1195
1196 /** {@inheritDoc} */
1197 public int checkAddPermission(WindowManager.LayoutParams attrs) {
1198 int type = attrs.type;
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07001199
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001200 if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
1201 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
1202 return WindowManagerImpl.ADD_OKAY;
1203 }
1204 String permission = null;
1205 switch (type) {
1206 case TYPE_TOAST:
1207 // XXX right now the app process has complete control over
1208 // this... should introduce a token to let the system
1209 // monitor/control what they are doing.
1210 break;
Daniel Sandler7d276c32012-01-30 14:33:52 -05001211 case TYPE_DREAM:
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001212 case TYPE_INPUT_METHOD:
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -07001213 case TYPE_WALLPAPER:
1214 // The window manager will check these.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001215 break;
1216 case TYPE_PHONE:
1217 case TYPE_PRIORITY_PHONE:
1218 case TYPE_SYSTEM_ALERT:
1219 case TYPE_SYSTEM_ERROR:
1220 case TYPE_SYSTEM_OVERLAY:
1221 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
1222 break;
1223 default:
1224 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
1225 }
1226 if (permission != null) {
1227 if (mContext.checkCallingOrSelfPermission(permission)
1228 != PackageManager.PERMISSION_GRANTED) {
1229 return WindowManagerImpl.ADD_PERMISSION_DENIED;
1230 }
1231 }
1232 return WindowManagerImpl.ADD_OKAY;
1233 }
1234
1235 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
1236 switch (attrs.type) {
1237 case TYPE_SYSTEM_OVERLAY:
Jeff Brown3b2b3542010-10-15 00:54:27 -07001238 case TYPE_SECURE_SYSTEM_OVERLAY:
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001239 case TYPE_TOAST:
1240 // These types of windows can't receive input events.
1241 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1242 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Jeff Brownbfcb60a2011-09-08 18:51:14 -07001243 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001244 break;
1245 }
1246 }
1247
1248 void readLidState() {
Jeff Brown2e7760e2012-04-11 15:14:55 -07001249 mLidState = mWindowManagerFuncs.getLidState();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001250 }
1251
Jeff Brown4aed78b2011-01-14 17:36:55 -08001252 private int determineHiddenState(int mode, int hiddenValue, int visibleValue) {
Jeff Brown2e7760e2012-04-11 15:14:55 -07001253 if (mLidState != LID_ABSENT) {
Jeff Brownd04a88c2011-01-16 14:05:47 -08001254 switch (mode) {
1255 case 1:
Jeff Brown2e7760e2012-04-11 15:14:55 -07001256 return mLidState == LID_OPEN ? visibleValue : hiddenValue;
Jeff Brownd04a88c2011-01-16 14:05:47 -08001257 case 2:
Jeff Brown2e7760e2012-04-11 15:14:55 -07001258 return mLidState == LID_OPEN ? hiddenValue : visibleValue;
Jeff Brownd04a88c2011-01-16 14:05:47 -08001259 }
Dianne Hackborn2862fff2009-09-15 22:56:29 -07001260 }
1261 return visibleValue;
1262 }
Jeff Brownd04a88c2011-01-16 14:05:47 -08001263
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001264 /** {@inheritDoc} */
1265 public void adjustConfigurationLw(Configuration config) {
1266 readLidState();
Jeff Brown01a98dd2011-09-20 15:08:29 -07001267 updateKeyboardVisibility();
Jeff Brownd04a88c2011-01-16 14:05:47 -08001268
1269 if (config.keyboard == Configuration.KEYBOARD_NOKEYS) {
1270 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
1271 } else {
1272 config.hardKeyboardHidden = determineHiddenState(mLidKeyboardAccessibility,
1273 Configuration.HARDKEYBOARDHIDDEN_YES, Configuration.HARDKEYBOARDHIDDEN_NO);
1274 }
1275
1276 if (config.navigation == Configuration.NAVIGATION_NONAV) {
1277 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
1278 } else {
1279 config.navigationHidden = determineHiddenState(mLidNavigationAccessibility,
1280 Configuration.NAVIGATIONHIDDEN_YES, Configuration.NAVIGATIONHIDDEN_NO);
1281 }
1282
1283 if (mHasSoftInput || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
1284 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
1285 } else {
1286 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
1287 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001288 }
Jeff Brownd04a88c2011-01-16 14:05:47 -08001289
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001290 /** {@inheritDoc} */
1291 public int windowTypeToLayerLw(int type) {
1292 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
1293 return APPLICATION_LAYER;
1294 }
1295 switch (type) {
1296 case TYPE_STATUS_BAR:
1297 return STATUS_BAR_LAYER;
1298 case TYPE_STATUS_BAR_PANEL:
1299 return STATUS_BAR_PANEL_LAYER;
Joe Onorato29fc2c92010-11-24 10:26:50 -08001300 case TYPE_STATUS_BAR_SUB_PANEL:
1301 return STATUS_BAR_SUB_PANEL_LAYER;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -08001302 case TYPE_SYSTEM_DIALOG:
1303 return SYSTEM_DIALOG_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001304 case TYPE_SEARCH_BAR:
1305 return SEARCH_BAR_LAYER;
1306 case TYPE_PHONE:
1307 return PHONE_LAYER;
1308 case TYPE_KEYGUARD:
1309 return KEYGUARD_LAYER;
1310 case TYPE_KEYGUARD_DIALOG:
1311 return KEYGUARD_DIALOG_LAYER;
1312 case TYPE_SYSTEM_ALERT:
1313 return SYSTEM_ALERT_LAYER;
1314 case TYPE_SYSTEM_ERROR:
1315 return SYSTEM_ERROR_LAYER;
1316 case TYPE_INPUT_METHOD:
1317 return INPUT_METHOD_LAYER;
1318 case TYPE_INPUT_METHOD_DIALOG:
1319 return INPUT_METHOD_DIALOG_LAYER;
Dianne Hackborne8ecde12011-08-03 18:55:19 -07001320 case TYPE_VOLUME_OVERLAY:
1321 return VOLUME_OVERLAY_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001322 case TYPE_SYSTEM_OVERLAY:
1323 return SYSTEM_OVERLAY_LAYER;
Jeff Brown3b2b3542010-10-15 00:54:27 -07001324 case TYPE_SECURE_SYSTEM_OVERLAY:
1325 return SECURE_SYSTEM_OVERLAY_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001326 case TYPE_PRIORITY_PHONE:
1327 return PRIORITY_PHONE_LAYER;
1328 case TYPE_TOAST:
1329 return TOAST_LAYER;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -07001330 case TYPE_WALLPAPER:
1331 return WALLPAPER_LAYER;
Christopher Tatea53146c2010-09-07 11:57:52 -07001332 case TYPE_DRAG:
1333 return DRAG_LAYER;
Jeff Brown83c09682010-12-23 17:50:18 -08001334 case TYPE_POINTER:
1335 return POINTER_LAYER;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001336 case TYPE_NAVIGATION_BAR:
1337 return NAVIGATION_BAR_LAYER;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07001338 case TYPE_BOOT_PROGRESS:
1339 return BOOT_PROGRESS_LAYER;
Dianne Hackborndf89e652011-10-06 22:35:11 -07001340 case TYPE_HIDDEN_NAV_CONSUMER:
1341 return HIDDEN_NAV_CONSUMER_LAYER;
Daniel Sandler7d276c32012-01-30 14:33:52 -05001342 case TYPE_DREAM:
1343 return SCREENSAVER_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001344 }
1345 Log.e(TAG, "Unknown window type: " + type);
1346 return APPLICATION_LAYER;
1347 }
1348
1349 /** {@inheritDoc} */
1350 public int subWindowTypeToLayerLw(int type) {
1351 switch (type) {
1352 case TYPE_APPLICATION_PANEL:
1353 case TYPE_APPLICATION_ATTACHED_DIALOG:
1354 return APPLICATION_PANEL_SUBLAYER;
1355 case TYPE_APPLICATION_MEDIA:
1356 return APPLICATION_MEDIA_SUBLAYER;
Dianne Hackborn5cb8d792009-05-21 17:34:15 -07001357 case TYPE_APPLICATION_MEDIA_OVERLAY:
1358 return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001359 case TYPE_APPLICATION_SUB_PANEL:
1360 return APPLICATION_SUB_PANEL_SUBLAYER;
1361 }
1362 Log.e(TAG, "Unknown sub-window type: " + type);
1363 return 0;
1364 }
1365
Dianne Hackbornabe0da02009-09-18 01:55:39 -07001366 public int getMaxWallpaperLayer() {
1367 return STATUS_BAR_LAYER;
1368 }
1369
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001370 public boolean hasSystemNavBar() {
1371 return mHasSystemNavBar;
Dianne Hackborn81e56d52011-05-26 00:55:58 -07001372 }
1373
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001374 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
Dianne Hackborn077ee852012-04-09 16:27:07 -07001375 if (mHasNavigationBar) {
1376 // For a basic navigation bar, when we are in landscape mode we place
1377 // the navigation bar to the side.
Daniel Sandler4a066c52012-04-20 14:49:13 -04001378 if (mNavigationBarCanMove && fullWidth > fullHeight) {
1379 return fullWidth - mNavigationBarWidthForRotation[rotation];
Dianne Hackborn077ee852012-04-09 16:27:07 -07001380 }
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001381 }
1382 return fullWidth;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001383 }
1384
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001385 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
Dianne Hackborn077ee852012-04-09 16:27:07 -07001386 if (mHasSystemNavBar) {
1387 // For the system navigation bar, we always place it at the bottom.
Daniel Sandler4a066c52012-04-20 14:49:13 -04001388 return fullHeight - mNavigationBarHeightForRotation[rotation];
Dianne Hackborn077ee852012-04-09 16:27:07 -07001389 }
1390 if (mHasNavigationBar) {
1391 // For a basic navigation bar, when we are in portrait mode we place
1392 // the navigation bar to the bottom.
Daniel Sandler4a066c52012-04-20 14:49:13 -04001393 if (!mNavigationBarCanMove || fullWidth < fullHeight) {
1394 return fullHeight - mNavigationBarHeightForRotation[rotation];
Dianne Hackborn077ee852012-04-09 16:27:07 -07001395 }
1396 }
1397 return fullHeight;
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001398 }
1399
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001400 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
1401 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation);
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001402 }
1403
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001404 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) {
Dianne Hackborn077ee852012-04-09 16:27:07 -07001405 // If we don't have a system nav bar, then there is a separate status
1406 // bar at the top of the display. We don't count that as part of the
1407 // fixed decor, since it can hide; however, for purposes of configurations,
1408 // we do want to exclude it since applications can't generally use that part
1409 // of the screen.
1410 if (!mHasSystemNavBar) {
1411 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation) - mStatusBarHeight;
1412 }
1413 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001414 }
1415
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001416 public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
1417 return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
1418 }
1419
1420 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
1421 return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001422 && attrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001423 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
1424 }
1425
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001426 /** {@inheritDoc} */
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001427 public View addStartingWindow(IBinder appToken, String packageName, int theme,
1428 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
1429 int icon, int windowFlags) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001430 if (!SHOW_STARTING_ANIMATIONS) {
1431 return null;
1432 }
1433 if (packageName == null) {
1434 return null;
1435 }
1436
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001437 try {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001438 Context context = mContext;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001439 //Log.i(TAG, "addStartingWindow " + packageName + ": nonLocalizedLabel="
1440 // + nonLocalizedLabel + " theme=" + Integer.toHexString(theme));
Dianne Hackborn247fe742011-01-08 17:25:57 -08001441 if (theme != context.getThemeResId() || labelRes != 0) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001442 try {
1443 context = context.createPackageContext(packageName, 0);
Dianne Hackborn247fe742011-01-08 17:25:57 -08001444 context.setTheme(theme);
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001445 } catch (PackageManager.NameNotFoundException e) {
1446 // Ignore
1447 }
1448 }
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001449
1450 Window win = PolicyManager.makeNewWindow(context);
1451 if (win.getWindowStyle().getBoolean(
1452 com.android.internal.R.styleable.Window_windowDisablePreview, false)) {
1453 return null;
1454 }
1455
1456 Resources r = context.getResources();
1457 win.setTitle(r.getText(labelRes, nonLocalizedLabel));
1458
1459 win.setType(
1460 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
1461 // Force the window flags: this is a fake window, so it is not really
1462 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
1463 // flag because we do know that the next window will take input
1464 // focus, so we want to get the IME window up on top of us right away.
1465 win.setFlags(
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001466 windowFlags|
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001467 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
1468 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
1469 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001470 windowFlags|
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001471 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
1472 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
1473 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
1474
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001475 if (!compatInfo.supportsScreen()) {
1476 win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW);
1477 }
1478
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001479 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001480 WindowManager.LayoutParams.MATCH_PARENT);
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001481
1482 final WindowManager.LayoutParams params = win.getAttributes();
1483 params.token = appToken;
1484 params.packageName = packageName;
1485 params.windowAnimations = win.getWindowStyle().getResourceId(
1486 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
Dianne Hackborn5d927c22011-09-02 12:22:18 -07001487 params.privateFlags |=
1488 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001489 params.setTitle("Starting " + packageName);
1490
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001491 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001492 View view = win.getDecorView();
1493
1494 if (win.isFloating()) {
1495 // Whoops, there is no way to display an animation/preview
1496 // of such a thing! After all that work... let's skip it.
1497 // (Note that we must do this here because it is in
1498 // getDecorView() where the theme is evaluated... maybe
1499 // we should peek the floating attribute from the theme
1500 // earlier.)
1501 return null;
1502 }
1503
1504 if (localLOGV) Log.v(
1505 TAG, "Adding starting window for " + packageName
1506 + " / " + appToken + ": "
1507 + (view.getParent() != null ? view : null));
1508
1509 wm.addView(view, params);
1510
1511 // Only return the view if it was successfully added to the
1512 // window manager... which we can tell by it having a parent.
1513 return view.getParent() != null ? view : null;
1514 } catch (WindowManagerImpl.BadTokenException e) {
1515 // ignore
1516 Log.w(TAG, appToken + " already running, starting window not displayed");
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001517 } catch (RuntimeException e) {
1518 // don't crash if something else bad happens, for example a
1519 // failure loading resources because we are loading from an app
1520 // on external storage that has been unmounted.
1521 Log.w(TAG, appToken + " failed creating starting window", e);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001522 }
1523
1524 return null;
1525 }
1526
1527 /** {@inheritDoc} */
1528 public void removeStartingWindow(IBinder appToken, View window) {
1529 // RuntimeException e = new RuntimeException();
1530 // Log.i(TAG, "remove " + appToken + " " + window, e);
1531
1532 if (localLOGV) Log.v(
1533 TAG, "Removing starting window for " + appToken + ": " + window);
1534
1535 if (window != null) {
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001536 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001537 wm.removeView(window);
1538 }
1539 }
1540
1541 /**
1542 * Preflight adding a window to the system.
1543 *
1544 * Currently enforces that three window types are singletons:
1545 * <ul>
1546 * <li>STATUS_BAR_TYPE</li>
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001547 * <li>KEYGUARD_TYPE</li>
1548 * </ul>
1549 *
1550 * @param win The window to be added
1551 * @param attrs Information about the window to be added
1552 *
1553 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON
1554 */
1555 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
1556 switch (attrs.type) {
1557 case TYPE_STATUS_BAR:
Joe Onorato8bc6c512010-06-04 16:21:12 -04001558 mContext.enforceCallingOrSelfPermission(
1559 android.Manifest.permission.STATUS_BAR_SERVICE,
1560 "PhoneWindowManager");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001561 if (mStatusBar != null) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001562 if (mStatusBar.isAlive()) {
1563 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1564 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001565 }
1566 mStatusBar = win;
1567 break;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001568 case TYPE_NAVIGATION_BAR:
1569 mContext.enforceCallingOrSelfPermission(
1570 android.Manifest.permission.STATUS_BAR_SERVICE,
1571 "PhoneWindowManager");
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001572 if (mNavigationBar != null) {
1573 if (mNavigationBar.isAlive()) {
1574 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1575 }
1576 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001577 mNavigationBar = win;
1578 if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
1579 break;
Dianne Hackborn08743722009-12-21 12:16:51 -08001580 case TYPE_STATUS_BAR_PANEL:
Joe Onorato8bc6c512010-06-04 16:21:12 -04001581 mContext.enforceCallingOrSelfPermission(
1582 android.Manifest.permission.STATUS_BAR_SERVICE,
1583 "PhoneWindowManager");
Dianne Hackborn08743722009-12-21 12:16:51 -08001584 break;
Joe Onorato29fc2c92010-11-24 10:26:50 -08001585 case TYPE_STATUS_BAR_SUB_PANEL:
1586 mContext.enforceCallingOrSelfPermission(
1587 android.Manifest.permission.STATUS_BAR_SERVICE,
1588 "PhoneWindowManager");
Dianne Hackborn7f58b952012-04-18 12:59:29 -07001589 mStatusBarSubPanels.add(win);
Joe Onorato29fc2c92010-11-24 10:26:50 -08001590 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001591 case TYPE_KEYGUARD:
1592 if (mKeyguard != null) {
1593 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1594 }
1595 mKeyguard = win;
1596 break;
1597 }
1598 return WindowManagerImpl.ADD_OKAY;
1599 }
1600
1601 /** {@inheritDoc} */
1602 public void removeWindowLw(WindowState win) {
1603 if (mStatusBar == win) {
1604 mStatusBar = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001605 } else if (mKeyguard == win) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001606 mKeyguard = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001607 } else if (mNavigationBar == win) {
1608 mNavigationBar = null;
Dianne Hackborn08743722009-12-21 12:16:51 -08001609 } else {
Dianne Hackborn7f58b952012-04-18 12:59:29 -07001610 mStatusBarSubPanels.remove(win);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001611 }
1612 }
1613
1614 static final boolean PRINT_ANIM = false;
1615
1616 /** {@inheritDoc} */
1617 public int selectAnimationLw(WindowState win, int transit) {
1618 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
1619 + ": transit=" + transit);
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001620 if (win == mStatusBar) {
1621 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1622 return R.anim.dock_top_exit;
1623 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1624 return R.anim.dock_top_enter;
1625 }
1626 } else if (win == mNavigationBar) {
1627 // This can be on either the bottom or the right.
1628 if (mNavigationBarOnBottom) {
1629 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1630 return R.anim.dock_bottom_exit;
1631 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1632 return R.anim.dock_bottom_enter;
1633 }
1634 } else {
1635 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1636 return R.anim.dock_right_exit;
1637 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1638 return R.anim.dock_right_enter;
1639 }
1640 }
1641 } if (transit == TRANSIT_PREVIEW_DONE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001642 if (win.hasAppShownWindows()) {
1643 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
1644 return com.android.internal.R.anim.app_starting_exit;
1645 }
1646 }
1647
1648 return 0;
1649 }
1650
Dianne Hackborn0c2acff2012-04-12 15:17:07 -07001651 public Animation createForceHideEnterAnimation(boolean onWallpaper) {
1652 return AnimationUtils.loadAnimation(mContext, onWallpaper
1653 ? com.android.internal.R.anim.lock_screen_wallpaper_behind_enter
1654 : com.android.internal.R.anim.lock_screen_behind_enter);
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001655 }
1656
Jeff Brown4d396052010-10-29 21:50:21 -07001657 static ITelephony getTelephonyService() {
Mike Lockwoodf5f4ec92011-11-08 14:05:31 -08001658 return ITelephony.Stub.asInterface(
Jeff Brown4d396052010-10-29 21:50:21 -07001659 ServiceManager.checkService(Context.TELEPHONY_SERVICE));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001660 }
1661
Jeff Brown4d396052010-10-29 21:50:21 -07001662 static IAudioService getAudioService() {
1663 IAudioService audioService = IAudioService.Stub.asInterface(
1664 ServiceManager.checkService(Context.AUDIO_SERVICE));
1665 if (audioService == null) {
1666 Log.w(TAG, "Unable to find IAudioService interface.");
1667 }
1668 return audioService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001669 }
1670
1671 boolean keyguardOn() {
1672 return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
1673 }
1674
1675 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
1676 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
1677 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
1678 };
1679
1680 /** {@inheritDoc} */
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001681 @Override
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001682 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001683 final boolean keyguardOn = keyguardOn();
Jeff Brown1f245102010-11-18 20:53:46 -08001684 final int keyCode = event.getKeyCode();
1685 final int repeatCount = event.getRepeatCount();
1686 final int metaState = event.getMetaState();
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001687 final int flags = event.getFlags();
Jeff Brown1f245102010-11-18 20:53:46 -08001688 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
1689 final boolean canceled = event.isCanceled();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001690
1691 if (false) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001692 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001693 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
1694 }
1695
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001696 // If we think we might have a volume down & power key chord on the way
1697 // but we're not sure, then tell the dispatcher to wait a little while and
1698 // try again later before dispatching.
Christopher Tatee90585f2012-03-05 18:56:25 -08001699 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001700 if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
1701 final long now = SystemClock.uptimeMillis();
1702 final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
1703 if (now < timeoutTime) {
1704 return timeoutTime - now;
1705 }
1706 }
1707 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
1708 && mVolumeDownKeyConsumedByScreenshotChord) {
1709 if (!down) {
1710 mVolumeDownKeyConsumedByScreenshotChord = false;
1711 }
1712 return -1;
1713 }
1714 }
1715
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001716 // First we always handle the home key here, so applications
1717 // can never break it, although if keyguard is on, we do let
1718 // it handle it, because that gives us the correct 5 second
1719 // timeout.
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001720 if (keyCode == KeyEvent.KEYCODE_HOME) {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001721
Jeff Brown49ed71d2010-12-06 17:13:33 -08001722 // If we have released the home key, and didn't do anything else
1723 // while it was pressed, then it is time to go home!
Michael Jurka7f2668c2012-03-27 07:49:52 -07001724 if (!down) {
1725 final boolean homeWasLongPressed = mHomeLongPressed;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001726 mHomePressed = false;
Michael Jurka7f2668c2012-03-27 07:49:52 -07001727 mHomeLongPressed = false;
1728 if (!homeWasLongPressed) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001729 try {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001730 mStatusBarService.cancelPreloadRecentApps();
1731 } catch (RemoteException e) {
1732 Slog.e(TAG, "RemoteException when showing recent apps", e);
Jeff Brown49ed71d2010-12-06 17:13:33 -08001733 }
1734
Michael Jurka7f2668c2012-03-27 07:49:52 -07001735 mHomePressed = false;
1736 if (!canceled) {
1737 // If an incoming call is ringing, HOME is totally disabled.
1738 // (The user is already on the InCallScreen at this point,
1739 // and his ONLY options are to answer or reject the call.)
1740 boolean incomingRinging = false;
1741 try {
1742 ITelephony telephonyService = getTelephonyService();
1743 if (telephonyService != null) {
1744 incomingRinging = telephonyService.isRinging();
1745 }
1746 } catch (RemoteException ex) {
1747 Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
1748 }
1749
1750 if (incomingRinging) {
1751 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
1752 } else {
1753 launchHomeFromHotKey();
1754 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001755 } else {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001756 Log.i(TAG, "Ignoring HOME; event canceled.");
Jeff Brown49ed71d2010-12-06 17:13:33 -08001757 }
Michael Jurka7f2668c2012-03-27 07:49:52 -07001758 return -1;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001759 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001760 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001761
1762 // If a system window has focus, then it doesn't make sense
1763 // right now to interact with applications.
1764 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
1765 if (attrs != null) {
1766 final int type = attrs.type;
1767 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
1768 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
1769 // the "app" is keyguard, so give it the key
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001770 return 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001771 }
1772 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
1773 for (int i=0; i<typeCount; i++) {
1774 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
1775 // don't do anything, but also don't pass it to the app
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001776 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001777 }
1778 }
1779 }
Jeff Brown98392ef2011-09-12 18:24:59 -07001780 if (down) {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001781 if (!mHomePressed) {
1782 try {
1783 mStatusBarService.preloadRecentApps();
1784 } catch (RemoteException e) {
1785 Slog.e(TAG, "RemoteException when preloading recent apps", e);
1786 }
1787 }
Jeff Brown98392ef2011-09-12 18:24:59 -07001788 if (repeatCount == 0) {
1789 mHomePressed = true;
1790 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
1791 if (!keyguardOn) {
1792 handleLongPressOnHome();
1793 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001794 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001795 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001796 return -1;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001797 } else if (keyCode == KeyEvent.KEYCODE_MENU) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001798 // Hijack modified menu keys for debugging features
1799 final int chordBug = KeyEvent.META_SHIFT_ON;
1800
1801 if (down && repeatCount == 0) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001802 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001803 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
1804 mContext.sendOrderedBroadcast(intent, null);
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001805 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001806 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001807 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001808 Intent service = new Intent();
1809 service.setClassName(mContext, "com.android.server.LoadAverageService");
1810 ContentResolver res = mContext.getContentResolver();
1811 boolean shown = Settings.System.getInt(
1812 res, Settings.System.SHOW_PROCESSES, 0) != 0;
1813 if (!shown) {
1814 mContext.startService(service);
1815 } else {
1816 mContext.stopService(service);
1817 }
1818 Settings.System.putInt(
1819 res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001820 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001821 }
1822 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001823 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001824 if (down) {
1825 if (repeatCount == 0) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001826 mShortcutKeyPressed = keyCode;
1827 mConsumeShortcutKeyUp = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001828 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001829 } else if (keyCode == mShortcutKeyPressed) {
1830 mShortcutKeyPressed = -1;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001831 if (mConsumeShortcutKeyUp) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001832 mConsumeShortcutKeyUp = false;
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001833 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001834 }
1835 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001836 return 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001837 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
Jeff Brownda3d5a92011-03-29 15:11:34 -07001838 if (down && repeatCount == 0) {
Jeff Brown68b909d2011-12-07 16:36:01 -08001839 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
Jeff Brown49ed71d2010-12-06 17:13:33 -08001840 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001841 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001842 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001843
Jeff Brownc1fb48d2010-12-08 16:52:09 -08001844 // Shortcuts are invoked through Search+key, so intercept those here
Jeff Browncaab4d02010-12-09 22:13:41 -08001845 // Any printing key that is chorded with Search should be consumed
1846 // even if no shortcut was invoked. This prevents text from being
1847 // inadvertently inserted when using a keyboard that has built-in macro
1848 // shortcut keys (that emit Search+x) and some of them are not registered.
1849 if (mShortcutKeyPressed != -1) {
1850 final KeyCharacterMap kcm = event.getKeyCharacterMap();
1851 if (kcm.isPrintingKey(keyCode)) {
1852 mConsumeShortcutKeyUp = true;
1853 if (down && repeatCount == 0 && !keyguardOn) {
1854 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
1855 if (shortcutIntent != null) {
1856 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Jeff Brownf0a3cc52011-01-26 18:42:46 -08001857 try {
1858 mContext.startActivity(shortcutIntent);
1859 } catch (ActivityNotFoundException ex) {
1860 Slog.w(TAG, "Dropping shortcut key combination because "
1861 + "the activity to which it is registered was not found: "
1862 + KeyEvent.keyCodeToString(mShortcutKeyPressed)
1863 + "+" + KeyEvent.keyCodeToString(keyCode), ex);
1864 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001865 } else {
1866 Slog.i(TAG, "Dropping unregistered shortcut key combination: "
1867 + KeyEvent.keyCodeToString(mShortcutKeyPressed)
1868 + "+" + KeyEvent.keyCodeToString(keyCode));
Jeff Brown49ed71d2010-12-06 17:13:33 -08001869 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001870 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001871 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001872 }
1873 }
1874
Jeff Brown68b909d2011-12-07 16:36:01 -08001875 // Invoke shortcuts using Meta.
1876 if (down && repeatCount == 0
1877 && (metaState & KeyEvent.META_META_ON) != 0) {
1878 final KeyCharacterMap kcm = event.getKeyCharacterMap();
1879 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
1880 metaState & ~(KeyEvent.META_META_ON
1881 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
1882 if (shortcutIntent != null) {
1883 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1884 try {
1885 mContext.startActivity(shortcutIntent);
1886 } catch (ActivityNotFoundException ex) {
1887 Slog.w(TAG, "Dropping shortcut key combination because "
1888 + "the activity to which it is registered was not found: "
1889 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
1890 }
1891 return -1;
1892 }
1893 }
1894
Jeff Brown6651a632011-11-28 12:59:11 -08001895 // Handle application launch keys.
1896 if (down && repeatCount == 0) {
1897 String category = sApplicationLaunchKeyCategories.get(keyCode);
1898 if (category != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -08001899 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
Jeff Brown6651a632011-11-28 12:59:11 -08001900 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1901 try {
1902 mContext.startActivity(intent);
1903 } catch (ActivityNotFoundException ex) {
1904 Slog.w(TAG, "Dropping application launch key because "
1905 + "the activity to which it is registered was not found: "
1906 + "keyCode=" + keyCode + ", category=" + category, ex);
1907 }
Jeff Brown68b909d2011-12-07 16:36:01 -08001908 return -1;
Jeff Brown6651a632011-11-28 12:59:11 -08001909 }
1910 }
1911
Jeff Brown68b909d2011-12-07 16:36:01 -08001912 // Display task switcher for ALT-TAB or Meta-TAB.
1913 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
1914 if (mRecentAppsDialogHeldModifiers == 0) {
1915 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
1916 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
1917 || KeyEvent.metaStateHasModifiers(
1918 shiftlessModifiers, KeyEvent.META_META_ON)) {
1919 mRecentAppsDialogHeldModifiers = shiftlessModifiers;
1920 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);
1921 return -1;
1922 }
1923 }
1924 } else if (!down && mRecentAppsDialogHeldModifiers != 0
1925 && (metaState & mRecentAppsDialogHeldModifiers) == 0) {
1926 mRecentAppsDialogHeldModifiers = 0;
1927 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);
1928 }
1929
1930 // Let the application handle the key.
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001931 return 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001932 }
1933
Jeff Brown3915bb82010-11-05 15:02:16 -07001934 /** {@inheritDoc} */
1935 @Override
Jeff Brown49ed71d2010-12-06 17:13:33 -08001936 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
Jeff Brown54875002011-04-06 15:33:01 -07001937 // Note: This method is only called if the initial down was unhandled.
Jeff Brown49ed71d2010-12-06 17:13:33 -08001938 if (DEBUG_FALLBACK) {
Jeff Brown1f245102010-11-18 20:53:46 -08001939 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
1940 + ", flags=" + event.getFlags()
1941 + ", keyCode=" + event.getKeyCode()
1942 + ", scanCode=" + event.getScanCode()
1943 + ", metaState=" + event.getMetaState()
1944 + ", repeatCount=" + event.getRepeatCount()
1945 + ", policyFlags=" + policyFlags);
Jeff Brown3915bb82010-11-05 15:02:16 -07001946 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001947
1948 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1949 final KeyCharacterMap kcm = event.getKeyCharacterMap();
Jeff Brownc1fb48d2010-12-08 16:52:09 -08001950 final int keyCode = event.getKeyCode();
1951 final int metaState = event.getMetaState();
Jeff Brown49ed71d2010-12-06 17:13:33 -08001952
Jeff Brown54875002011-04-06 15:33:01 -07001953 // Check for fallback actions specified by the key character map.
Jeff Brown6f2fba42011-02-19 01:08:02 -08001954 if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001955 if (DEBUG_FALLBACK) {
1956 Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
1957 + " metaState=" + Integer.toHexString(mFallbackAction.metaState));
1958 }
1959
1960 int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
1961 KeyEvent fallbackEvent = KeyEvent.obtain(
1962 event.getDownTime(), event.getEventTime(),
1963 event.getAction(), mFallbackAction.keyCode,
1964 event.getRepeatCount(), mFallbackAction.metaState,
1965 event.getDeviceId(), event.getScanCode(),
1966 flags, event.getSource(), null);
1967 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
1968 if ((actions & ACTION_PASS_TO_USER) != 0) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001969 long delayMillis = interceptKeyBeforeDispatching(
1970 win, fallbackEvent, policyFlags);
1971 if (delayMillis == 0) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001972 if (DEBUG_FALLBACK) {
1973 Slog.d(TAG, "Performing fallback.");
1974 }
1975 return fallbackEvent;
1976 }
1977 }
1978 fallbackEvent.recycle();
1979 }
1980 }
1981
1982 if (DEBUG_FALLBACK) {
1983 Slog.d(TAG, "No fallback.");
1984 }
1985 return null;
Jeff Brown3915bb82010-11-05 15:02:16 -07001986 }
1987
Jeff Brown6f2fba42011-02-19 01:08:02 -08001988 private boolean getFallbackAction(KeyCharacterMap kcm, int keyCode, int metaState,
1989 FallbackAction outFallbackAction) {
1990 // Consult the key character map for specific fallback actions.
1991 // For example, map NUMPAD_1 to MOVE_HOME when NUMLOCK is not pressed.
Jeff Browncc0c1592011-02-19 05:07:28 -08001992 return kcm.getFallbackAction(keyCode, metaState, outFallbackAction);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001993 }
1994
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001995 /**
1996 * A home key -> launch home action was detected. Take the appropriate action
1997 * given the situation with the keyguard.
1998 */
1999 void launchHomeFromHotKey() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002000 if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002001 // don't launch home if keyguard showing
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002002 } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002003 // when in keyguard restricted mode, must first verify unlock
2004 // before launching home
2005 mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
2006 public void onKeyguardExitResult(boolean success) {
2007 if (success) {
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07002008 try {
2009 ActivityManagerNative.getDefault().stopAppSwitches();
2010 } catch (RemoteException e) {
2011 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05002012 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002013 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002014 }
2015 }
2016 });
2017 } else {
2018 // no keyguard stuff to worry about, just launch home!
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07002019 try {
2020 ActivityManagerNative.getDefault().stopAppSwitches();
2021 } catch (RemoteException e) {
2022 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05002023 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002024 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002025 }
2026 }
2027
Dianne Hackborne26ab702011-10-16 13:21:33 -07002028 /**
2029 * A delayed callback use to determine when it is okay to re-allow applications
2030 * to use certain system UI flags. This is used to prevent applications from
2031 * spamming system UI changes that prevent the navigation bar from being shown.
2032 */
2033 final Runnable mAllowSystemUiDelay = new Runnable() {
2034 @Override public void run() {
2035 }
2036 };
2037
2038 /**
2039 * Input handler used while nav bar is hidden. Captures any touch on the screen,
2040 * to determine when the nav bar should be shown and prevent applications from
2041 * receiving those touches.
2042 */
Jeff Brown32cbc38552011-12-01 14:01:49 -08002043 final class HideNavInputEventReceiver extends InputEventReceiver {
2044 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
2045 super(inputChannel, looper);
2046 }
2047
Dianne Hackborndf89e652011-10-06 22:35:11 -07002048 @Override
Jeff Brown32cbc38552011-12-01 14:01:49 -08002049 public void onInputEvent(InputEvent event) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002050 boolean handled = false;
2051 try {
Jeff Brown4952dfd2011-11-30 19:23:22 -08002052 if (event instanceof MotionEvent
2053 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
2054 final MotionEvent motionEvent = (MotionEvent)event;
2055 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002056 // When the user taps down, we re-show the nav bar.
2057 boolean changed = false;
2058 synchronized (mLock) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002059 // Any user activity always causes us to show the
2060 // navigation controls, if they had been hidden.
2061 // We also clear the low profile and only content
2062 // flags so that tapping on the screen will atomically
2063 // restore all currently hidden screen decorations.
2064 int newVal = mResettingSystemUiFlags |
2065 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
2066 View.SYSTEM_UI_FLAG_LOW_PROFILE |
2067 View.SYSTEM_UI_FLAG_FULLSCREEN;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002068 if (mResettingSystemUiFlags != newVal) {
2069 mResettingSystemUiFlags = newVal;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002070 changed = true;
2071 }
Dianne Hackborne26ab702011-10-16 13:21:33 -07002072 // We don't allow the system's nav bar to be hidden
2073 // again for 1 second, to prevent applications from
2074 // spamming us and keeping it from being shown.
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002075 newVal = mForceClearedSystemUiFlags |
2076 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002077 if (mForceClearedSystemUiFlags != newVal) {
2078 mForceClearedSystemUiFlags = newVal;
2079 changed = true;
2080 mHandler.postDelayed(new Runnable() {
2081 @Override public void run() {
2082 synchronized (mLock) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002083 // Clear flags.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002084 mForceClearedSystemUiFlags &=
2085 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
2086 }
2087 mWindowManagerFuncs.reevaluateStatusBarVisibility();
2088 }
2089 }, 1000);
2090 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07002091 }
2092 if (changed) {
2093 mWindowManagerFuncs.reevaluateStatusBarVisibility();
2094 }
2095 }
2096 }
2097 } finally {
Jeff Brown32cbc38552011-12-01 14:01:49 -08002098 finishInputEvent(event, handled);
Dianne Hackborndf89e652011-10-06 22:35:11 -07002099 }
2100 }
Jeff Brown32cbc38552011-12-01 14:01:49 -08002101 }
2102 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
2103 new InputEventReceiver.Factory() {
2104 @Override
2105 public InputEventReceiver createInputEventReceiver(
2106 InputChannel inputChannel, Looper looper) {
2107 return new HideNavInputEventReceiver(inputChannel, looper);
2108 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07002109 };
2110
2111 @Override
2112 public int adjustSystemUiVisibilityLw(int visibility) {
2113 // Reset any bits in mForceClearingStatusBarVisibility that
2114 // are now clear.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002115 mResettingSystemUiFlags &= visibility;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002116 // Clear any bits in the new visibility that are currently being
2117 // force cleared, before reporting it.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002118 return visibility & ~mResettingSystemUiFlags
2119 & ~mForceClearedSystemUiFlags;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002120 }
2121
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002122 public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
2123 final int fl = attrs.flags;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002124
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07002125 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002126 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002127 int availRight, availBottom;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002128 if (mCanHideNavigationBar &&
2129 (attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002130 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
2131 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
2132 } else {
2133 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
2134 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
2135 }
2136 if ((attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2137 contentInset.set(mStableLeft, mStableTop,
2138 availRight - mStableRight, availBottom - mStableBottom);
2139 } else if ((attrs.systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
2140 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
2141 contentInset.set(mCurLeft, mCurTop,
2142 availRight - mCurRight, availBottom - mCurBottom);
2143 } else {
2144 contentInset.set(mCurLeft, mCurTop,
2145 availRight - mCurRight, availBottom - mCurBottom);
2146 }
2147 return;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002148 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002149 contentInset.setEmpty();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002150 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002151
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002152 /** {@inheritDoc} */
Dianne Hackborn1f903c32011-09-13 19:18:06 -07002153 public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation) {
Joe Onorato29fc2c92010-11-24 10:26:50 -08002154 mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
2155 mUnrestrictedScreenWidth = displayWidth;
2156 mUnrestrictedScreenHeight = displayHeight;
2157 mRestrictedScreenLeft = mRestrictedScreenTop = 0;
2158 mRestrictedScreenWidth = displayWidth;
2159 mRestrictedScreenHeight = displayHeight;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002160 mDockLeft = mContentLeft = mStableLeft = mCurLeft = 0;
2161 mDockTop = mContentTop = mStableTop = mCurTop = 0;
2162 mDockRight = mContentRight = mStableRight = mCurRight = displayWidth;
2163 mDockBottom = mContentBottom = mStableBottom = mCurBottom = displayHeight;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002164 mDockLayer = 0x10000000;
2165
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002166 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
2167 final Rect pf = mTmpParentFrame;
2168 final Rect df = mTmpDisplayFrame;
2169 final Rect vf = mTmpVisibleFrame;
2170 pf.left = df.left = vf.left = mDockLeft;
2171 pf.top = df.top = vf.top = mDockTop;
2172 pf.right = df.right = vf.right = mDockRight;
2173 pf.bottom = df.bottom = vf.bottom = mDockBottom;
2174
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002175 // For purposes of putting out fake window up to steal focus, we will
2176 // drive nav being hidden only by whether it is requested.
2177 boolean navVisible = (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002178
2179 // When the navigation bar isn't visible, we put up a fake
2180 // input window to catch all touch events. This way we can
2181 // detect when the user presses anywhere to bring back the nav
2182 // bar and ensure the application doesn't see the event.
2183 if (navVisible) {
2184 if (mHideNavFakeWindow != null) {
2185 mHideNavFakeWindow.dismiss();
2186 mHideNavFakeWindow = null;
2187 }
2188 } else if (mHideNavFakeWindow == null) {
2189 mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
Jeff Brown32cbc38552011-12-01 14:01:49 -08002190 mHandler.getLooper(), mHideNavInputEventReceiverFactory,
Dianne Hackborne26ab702011-10-16 13:21:33 -07002191 "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
2192 0, false, false, true);
2193 }
2194
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002195 // For purposes of positioning and showing the nav bar, if we have
2196 // decided that it can't be hidden (because of the screen aspect ratio),
2197 // then take that into account.
2198 navVisible |= !mCanHideNavigationBar;
2199
2200 if (mNavigationBar != null) {
2201 // Force the navigation bar to its appropriate place and
2202 // size. We need to do this directly, instead of relying on
2203 // it to bubble up from the nav bar, because this needs to
2204 // change atomically with screen rotations.
Daniel Sandler4a066c52012-04-20 14:49:13 -04002205 mNavigationBarOnBottom = (!mNavigationBarCanMove || displayWidth < displayHeight);
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002206 if (mNavigationBarOnBottom) {
2207 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
Daniel Sandler4a066c52012-04-20 14:49:13 -04002208 int top = displayHeight - mNavigationBarHeightForRotation[displayRotation];
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002209 if (mHdmiPlugged) {
2210 if (top > mExternalDisplayHeight) {
2211 top = mExternalDisplayHeight;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002212 }
2213 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002214 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
2215 mStableBottom = mTmpNavigationFrame.top;
2216 if (navVisible) {
2217 mNavigationBar.showLw(true);
2218 mDockBottom = mTmpNavigationFrame.top;
2219 mRestrictedScreenHeight = mDockBottom - mDockTop;
2220 } else {
2221 // We currently want to hide the navigation UI.
2222 mNavigationBar.hideLw(true);
2223 }
2224 } else {
2225 // Landscape screen; nav bar goes to the right.
Daniel Sandler4a066c52012-04-20 14:49:13 -04002226 int left = displayWidth - mNavigationBarWidthForRotation[displayRotation];
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002227 if (mHdmiPlugged) {
2228 if (left > mExternalDisplayWidth) {
2229 left = mExternalDisplayWidth;
2230 }
2231 }
2232 mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight);
2233 mStableRight = mTmpNavigationFrame.left;
2234 if (navVisible) {
2235 mNavigationBar.showLw(true);
2236 mDockRight = mTmpNavigationFrame.left;
2237 mRestrictedScreenWidth = mDockRight - mDockLeft;
2238 } else {
2239 // We currently want to hide the navigation UI.
2240 mNavigationBar.hideLw(true);
2241 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002242 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002243 // Make sure the content and current rectangles are updated to
2244 // account for the restrictions from the navigation bar.
2245 mContentTop = mCurTop = mDockTop;
2246 mContentBottom = mCurBottom = mDockBottom;
2247 mContentLeft = mCurLeft = mDockLeft;
2248 mContentRight = mCurRight = mDockRight;
2249 // And compute the final frame.
2250 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
2251 mTmpNavigationFrame, mTmpNavigationFrame);
2252 if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
2253 }
2254 if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
2255 mDockLeft, mDockTop, mDockRight, mDockBottom));
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002256
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002257 // decide where the status bar goes ahead of time
2258 if (mStatusBar != null) {
2259 // apply any navigation bar insets
Dianne Hackborn98014352012-04-05 18:31:41 -07002260 pf.left = df.left = mUnrestrictedScreenLeft;
2261 pf.top = df.top = mUnrestrictedScreenTop;
2262 pf.right = df.right = mUnrestrictedScreenWidth - mUnrestrictedScreenLeft;
2263 pf.bottom = df.bottom = mUnrestrictedScreenHeight - mUnrestrictedScreenTop;
2264 vf.left = mStableLeft;
2265 vf.top = mStableTop;
2266 vf.right = mStableRight;
2267 vf.bottom = mStableBottom;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002268
Dianne Hackbornde368ff2012-04-10 18:35:54 -07002269 // Let the status bar determine its size.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002270 mStatusBar.computeFrameLw(pf, df, vf, vf);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002271
Dianne Hackbornde368ff2012-04-10 18:35:54 -07002272 // For layout, the status bar is always at the top with our fixed height.
2273 mStableTop = mUnrestrictedScreenTop + mStatusBarHeight;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002274
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002275 // If the status bar is hidden, we don't want to cause
2276 // windows behind it to scroll.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002277 if (mStatusBar.isVisibleLw()) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002278 // Status bar may go away, so the screen area it occupies
2279 // is available to apps but just covering them when the
2280 // status bar is visible.
Dianne Hackbornde368ff2012-04-10 18:35:54 -07002281 mDockTop = mUnrestrictedScreenTop + mStatusBarHeight;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002282
2283 mContentTop = mCurTop = mDockTop;
2284 mContentBottom = mCurBottom = mDockBottom;
2285 mContentLeft = mCurLeft = mDockLeft;
2286 mContentRight = mCurRight = mDockRight;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002287
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002288 if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
2289 String.format(
2290 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
2291 mDockLeft, mDockTop, mDockRight, mDockBottom,
2292 mContentLeft, mContentTop, mContentRight, mContentBottom,
2293 mCurLeft, mCurTop, mCurRight, mCurBottom));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002294 }
2295 }
2296 }
2297
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002298 void setAttachedWindowFrames(WindowState win, int fl, int adjust,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002299 WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
2300 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
2301 // Here's a special case: if this attached window is a panel that is
2302 // above the dock window, and the window it is attached to is below
2303 // the dock window, then the frames we computed for the window it is
2304 // attached to can not be used because the dock is effectively part
2305 // of the underlying window and the attached window is floating on top
2306 // of the whole thing. So, we ignore the attached window and explicitly
2307 // compute the frames that would be appropriate without the dock.
2308 df.left = cf.left = vf.left = mDockLeft;
2309 df.top = cf.top = vf.top = mDockTop;
2310 df.right = cf.right = vf.right = mDockRight;
2311 df.bottom = cf.bottom = vf.bottom = mDockBottom;
2312 } else {
2313 // The effective display frame of the attached window depends on
2314 // whether it is taking care of insetting its content. If not,
2315 // we need to use the parent's content frame so that the entire
2316 // window is positioned within that content. Otherwise we can use
2317 // the display frame and let the attached window take care of
2318 // positioning its content appropriately.
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002319 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002320 cf.set(attached.getDisplayFrameLw());
2321 } else {
2322 // If the window is resizing, then we want to base the content
2323 // frame on our attached content frame to resize... however,
2324 // things can be tricky if the attached window is NOT in resize
2325 // mode, in which case its content frame will be larger.
2326 // Ungh. So to deal with that, make sure the content frame
2327 // we end up using is not covering the IM dock.
2328 cf.set(attached.getContentFrameLw());
2329 if (attached.getSurfaceLayer() < mDockLayer) {
2330 if (cf.left < mContentLeft) cf.left = mContentLeft;
2331 if (cf.top < mContentTop) cf.top = mContentTop;
2332 if (cf.right > mContentRight) cf.right = mContentRight;
2333 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
2334 }
2335 }
2336 df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
2337 vf.set(attached.getVisibleFrameLw());
2338 }
2339 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
2340 // window should be positioned relative to its parent or the entire
2341 // screen.
2342 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
2343 ? attached.getFrameLw() : df);
2344 }
2345
2346 /** {@inheritDoc} */
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07002347 public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
2348 WindowState attached) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002349 // we've already done the status bar
Dianne Hackborn1f903c32011-09-13 19:18:06 -07002350 if (win == mStatusBar || win == mNavigationBar) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002351 return;
2352 }
2353
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002354 final int fl = attrs.flags;
2355 final int sim = attrs.softInputMode;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002356 final int sysUiFl = win.getSystemUiVisibility();
2357
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002358 final Rect pf = mTmpParentFrame;
2359 final Rect df = mTmpDisplayFrame;
2360 final Rect cf = mTmpContentFrame;
2361 final Rect vf = mTmpVisibleFrame;
2362
Daniel Sandler36412a72011-08-04 09:35:13 -04002363 final boolean hasNavBar = (mHasNavigationBar
2364 && mNavigationBar != null && mNavigationBar.isVisibleLw());
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002365
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002366 if (attrs.type == TYPE_INPUT_METHOD) {
2367 pf.left = df.left = cf.left = vf.left = mDockLeft;
2368 pf.top = df.top = cf.top = vf.top = mDockTop;
2369 pf.right = df.right = cf.right = vf.right = mDockRight;
2370 pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
2371 // IM dock windows always go to the bottom of the screen.
2372 attrs.gravity = Gravity.BOTTOM;
2373 mDockLayer = win.getSurfaceLayer();
2374 } else {
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002375 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
2376
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07002377 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002378 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)
2379 && (sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002380 if (DEBUG_LAYOUT)
2381 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2382 + "): IN_SCREEN, INSET_DECOR, !FULLSCREEN");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002383 // This is the case for a normal activity window: we want it
2384 // to cover all of the screen space, and it can take care of
2385 // moving its contents to account for screen decorations that
2386 // intrude into that space.
2387 if (attached != null) {
2388 // If this window is attached to another, our display
2389 // frame is the same as the one we are attached to.
2390 setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
2391 } else {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002392 if (attrs.type == TYPE_STATUS_BAR_PANEL
2393 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
Joe Onorato29fc2c92010-11-24 10:26:50 -08002394 // Status bar panels are the only windows who can go on top of
2395 // the status bar. They are protected by the STATUS_BAR_SERVICE
2396 // permission, so they have the same privileges as the status
2397 // bar itself.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002398 //
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002399 // However, they should still dodge the navigation bar if it exists.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002400
2401 pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002402 pf.top = df.top = mUnrestrictedScreenTop;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002403 pf.right = df.right = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002404 ? mRestrictedScreenLeft+mRestrictedScreenWidth
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002405 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2406 pf.bottom = df.bottom = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002407 ? mRestrictedScreenTop+mRestrictedScreenHeight
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002408 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
2409
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002410 if (DEBUG_LAYOUT) {
2411 Log.v(TAG, String.format(
2412 "Laying out status bar window: (%d,%d - %d,%d)",
2413 pf.left, pf.top, pf.right, pf.bottom));
2414 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002415 } else if (mCanHideNavigationBar
2416 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002417 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
2418 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
2419 // Asking for layout as if the nav bar is hidden, lets the
2420 // application extend into the unrestricted screen area. We
2421 // only do this for application windows to ensure no window that
2422 // can be above the nav bar can do this.
2423 pf.left = df.left = mUnrestrictedScreenLeft;
2424 pf.top = df.top = mUnrestrictedScreenTop;
2425 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2426 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002427 } else {
2428 pf.left = df.left = mRestrictedScreenLeft;
2429 pf.top = df.top = mRestrictedScreenTop;
2430 pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2431 pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
2432 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002433 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002434 cf.left = mDockLeft;
2435 cf.top = mDockTop;
2436 cf.right = mDockRight;
2437 cf.bottom = mDockBottom;
2438 } else {
2439 cf.left = mContentLeft;
2440 cf.top = mContentTop;
2441 cf.right = mContentRight;
2442 cf.bottom = mContentBottom;
2443 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002444 if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2445 // If app is requesting a stable layout, don't let the
2446 // content insets go below the stable values.
2447 if (cf.left < mStableLeft) cf.left = mStableLeft;
2448 if (cf.top < mStableTop) cf.top = mStableTop;
2449 if (cf.right > mStableRight) cf.right = mStableRight;
2450 if (cf.bottom > mStableBottom) cf.bottom = mStableBottom;
2451 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002452 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2453 vf.left = mCurLeft;
2454 vf.top = mCurTop;
2455 vf.right = mCurRight;
2456 vf.bottom = mCurBottom;
2457 } else {
2458 vf.set(cf);
2459 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002460 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002461 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
2462 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
2463 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002464 if (DEBUG_LAYOUT)
2465 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002466 // A window that has requested to fill the entire screen just
2467 // gets everything, period.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002468 if (attrs.type == TYPE_STATUS_BAR_PANEL
2469 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
2470 pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002471 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002472 pf.right = df.right = cf.right = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002473 ? mRestrictedScreenLeft+mRestrictedScreenWidth
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002474 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2475 pf.bottom = df.bottom = cf.bottom = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002476 ? mRestrictedScreenTop+mRestrictedScreenHeight
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002477 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Daniel Sandler36412a72011-08-04 09:35:13 -04002478 if (DEBUG_LAYOUT) {
2479 Log.v(TAG, String.format(
2480 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
2481 pf.left, pf.top, pf.right, pf.bottom));
2482 }
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002483 } else if (attrs.type == TYPE_NAVIGATION_BAR) {
2484 // The navigation bar has Real Ultimate Power.
2485 pf.left = df.left = mUnrestrictedScreenLeft;
2486 pf.top = df.top = mUnrestrictedScreenTop;
2487 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2488 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
2489 if (DEBUG_LAYOUT) {
2490 Log.v(TAG, String.format(
2491 "Laying out navigation bar window: (%d,%d - %d,%d)",
2492 pf.left, pf.top, pf.right, pf.bottom));
2493 }
Dianne Hackborn01011c32012-02-21 13:54:21 -08002494 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
2495 || attrs.type == TYPE_BOOT_PROGRESS)
Jeff Brownbfcb60a2011-09-08 18:51:14 -07002496 && ((fl & FLAG_FULLSCREEN) != 0)) {
2497 // Fullscreen secure system overlays get what they ask for.
2498 pf.left = df.left = mUnrestrictedScreenLeft;
2499 pf.top = df.top = mUnrestrictedScreenTop;
2500 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2501 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Dianne Hackborn01011c32012-02-21 13:54:21 -08002502 } else if (attrs.type == TYPE_BOOT_PROGRESS) {
2503 // Boot progress screen always covers entire display.
2504 pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
2505 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
2506 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2507 pf.bottom = df.bottom = cf.bottom
2508 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002509 } else if (mCanHideNavigationBar
2510 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002511 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
2512 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
2513 // Asking for layout as if the nav bar is hidden, lets the
2514 // application extend into the unrestricted screen area. We
2515 // only do this for application windows to ensure no window that
2516 // can be above the nav bar can do this.
2517 // XXX This assumes that an app asking for this will also
2518 // ask for layout in only content. We can't currently figure out
2519 // what the screen would be if only laying out to hide the nav bar.
2520 pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
2521 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
2522 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2523 pf.bottom = df.bottom = cf.bottom
2524 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002525 } else {
2526 pf.left = df.left = cf.left = mRestrictedScreenLeft;
2527 pf.top = df.top = cf.top = mRestrictedScreenTop;
2528 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2529 pf.bottom = df.bottom = cf.bottom
2530 = mRestrictedScreenTop+mRestrictedScreenHeight;
2531 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002532 if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2533 // If app is requesting a stable layout, don't let the
2534 // content insets go below the stable values.
2535 if (cf.left < mStableLeft) cf.left = mStableLeft;
2536 if (cf.top < mStableTop) cf.top = mStableTop;
2537 if (cf.right > mStableRight) cf.right = mStableRight;
2538 if (cf.bottom > mStableBottom) cf.bottom = mStableBottom;
2539 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002540 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2541 vf.left = mCurLeft;
2542 vf.top = mCurTop;
2543 vf.right = mCurRight;
2544 vf.bottom = mCurBottom;
2545 } else {
2546 vf.set(cf);
2547 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002548 } else if (attached != null) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002549 if (DEBUG_LAYOUT)
2550 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): attached to " + attached);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002551 // A child window should be placed inside of the same visible
2552 // frame that its parent had.
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002553 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002554 } else {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002555 if (DEBUG_LAYOUT)
2556 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002557 // Otherwise, a normal window must be placed inside the content
2558 // of all screen decorations.
Dianne Hackborna239c842011-06-01 12:28:20 -07002559 if (attrs.type == TYPE_STATUS_BAR_PANEL) {
2560 // Status bar panels are the only windows who can go on top of
2561 // the status bar. They are protected by the STATUS_BAR_SERVICE
2562 // permission, so they have the same privileges as the status
2563 // bar itself.
Dianne Hackborn7d049322011-06-14 15:00:32 -07002564 pf.left = df.left = cf.left = mRestrictedScreenLeft;
2565 pf.top = df.top = cf.top = mRestrictedScreenTop;
2566 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2567 pf.bottom = df.bottom = cf.bottom
2568 = mRestrictedScreenTop+mRestrictedScreenHeight;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002569 } else {
Dianne Hackborna239c842011-06-01 12:28:20 -07002570 pf.left = mContentLeft;
2571 pf.top = mContentTop;
2572 pf.right = mContentRight;
2573 pf.bottom = mContentBottom;
2574 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
2575 df.left = cf.left = mDockLeft;
2576 df.top = cf.top = mDockTop;
2577 df.right = cf.right = mDockRight;
2578 df.bottom = cf.bottom = mDockBottom;
2579 } else {
2580 df.left = cf.left = mContentLeft;
2581 df.top = cf.top = mContentTop;
2582 df.right = cf.right = mContentRight;
2583 df.bottom = cf.bottom = mContentBottom;
2584 }
2585 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2586 vf.left = mCurLeft;
2587 vf.top = mCurTop;
2588 vf.right = mCurRight;
2589 vf.bottom = mCurBottom;
2590 } else {
2591 vf.set(cf);
2592 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002593 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002594 }
2595 }
2596
2597 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
2598 df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
2599 df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
2600 }
2601
The Android Open Source Project11267662009-03-18 17:39:47 -07002602 if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
2603 + ": sim=#" + Integer.toHexString(sim)
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002604 + " attach=" + attached + " type=" + attrs.type
2605 + String.format(" flags=0x%08x", fl)
The Android Open Source Project11267662009-03-18 17:39:47 -07002606 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
2607 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
2608
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002609 win.computeFrameLw(pf, df, cf, vf);
2610
2611 // Dock windows carve out the bottom of the screen, so normal windows
2612 // can't appear underneath them.
2613 if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
2614 int top = win.getContentFrameLw().top;
2615 top += win.getGivenContentInsetsLw().top;
2616 if (mContentBottom > top) {
2617 mContentBottom = top;
2618 }
2619 top = win.getVisibleFrameLw().top;
2620 top += win.getGivenVisibleInsetsLw().top;
2621 if (mCurBottom > top) {
2622 mCurBottom = top;
2623 }
The Android Open Source Project11267662009-03-18 17:39:47 -07002624 if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom="
2625 + mDockBottom + " mContentBottom="
2626 + mContentBottom + " mCurBottom=" + mCurBottom);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002627 }
2628 }
2629
2630 /** {@inheritDoc} */
Craig Mautner61ac6bb2012-02-02 17:29:33 -08002631 @Override
2632 public void finishLayoutLw() {
2633 return;
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002634 }
2635
2636 /** {@inheritDoc} */
2637 public void beginAnimationLw(int displayWidth, int displayHeight) {
2638 mTopFullscreenOpaqueWindowState = null;
2639 mForceStatusBar = false;
2640
2641 mHideLockScreen = false;
2642 mAllowLockscreenWhenOn = false;
2643 mDismissKeyguard = false;
2644 }
2645
2646 /** {@inheritDoc} */
2647 public void animatingWindowLw(WindowState win,
2648 WindowManager.LayoutParams attrs) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002649 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
2650 + win.isVisibleOrBehindKeyguardLw());
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002651 if (mTopFullscreenOpaqueWindowState == null &&
Dianne Hackborn01b02a72012-01-12 14:05:03 -08002652 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002653 if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
2654 mForceStatusBar = true;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002655 }
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002656 if (attrs.type >= FIRST_APPLICATION_WINDOW
2657 && attrs.type <= LAST_APPLICATION_WINDOW
Dianne Hackborn6493e642010-10-01 13:06:30 -07002658 && attrs.x == 0 && attrs.y == 0
2659 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
2660 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002661 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win);
2662 mTopFullscreenOpaqueWindowState = win;
2663 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2664 if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
2665 mHideLockScreen = true;
2666 }
2667 if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2668 if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win);
2669 mDismissKeyguard = true;
2670 }
2671 if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
2672 mAllowLockscreenWhenOn = true;
2673 }
2674 }
2675 }
2676 }
2677
2678 /** {@inheritDoc} */
2679 public int finishAnimationLw() {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002680 int changes = 0;
Joe Onorato93056472010-09-10 10:30:46 -04002681 boolean topIsFullscreen = false;
Daniel Sandlere02d8082010-10-08 15:13:22 -04002682
2683 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
2684 ? mTopFullscreenOpaqueWindowState.getAttrs()
2685 : null;
2686
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002687 if (mStatusBar != null) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002688 if (DEBUG_LAYOUT) Log.i(TAG, "force=" + mForceStatusBar
Dianne Hackbornd70bc2f2009-10-06 23:25:51 -07002689 + " top=" + mTopFullscreenOpaqueWindowState);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002690 if (mForceStatusBar) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002691 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: forced");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002692 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002693 } else if (mTopFullscreenOpaqueWindowState != null) {
Joe Onorato93056472010-09-10 10:30:46 -04002694 if (localLOGV) {
2695 Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
2696 + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
2697 Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
2698 + " lp.flags=0x" + Integer.toHexString(lp.flags));
2699 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002700 topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
2701 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
Joe Onorato93056472010-09-10 10:30:46 -04002702 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
2703 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
2704 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
2705 // case though.
2706 if (topIsFullscreen) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002707 if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar");
2708 if (mStatusBar.hideLw(true)) {
2709 changes |= FINISH_LAYOUT_REDO_LAYOUT;
Daniel Sandler9c00d5b2011-09-13 14:04:26 -04002710
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002711 mHandler.post(new Runnable() { public void run() {
2712 if (mStatusBarService != null) {
2713 try {
2714 mStatusBarService.collapse();
2715 } catch (RemoteException ex) {}
2716 }
2717 }});
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002718 } else if (DEBUG_LAYOUT) {
Daniel Sandler40427442010-07-16 11:44:52 -04002719 Log.v(TAG, "Preventing status bar from hiding by policy");
2720 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002721 } else {
Dianne Hackborn01b02a72012-01-12 14:05:03 -08002722 if (DEBUG_LAYOUT) Log.v(TAG, "** SHOWING status bar: top is not fullscreen");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002723 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002724 }
2725 }
2726 }
Daniel Sandlere02d8082010-10-08 15:13:22 -04002727
Joe Onorato644f9c32011-01-25 12:06:23 -08002728 mTopIsFullscreen = topIsFullscreen;
Daniel Sandlere02d8082010-10-08 15:13:22 -04002729
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002730 // Hide the key guard if a visible window explicitly specifies that it wants to be displayed
2731 // when the screen is locked
2732 if (mKeyguard != null) {
Joe Onorato93056472010-09-10 10:30:46 -04002733 if (localLOGV) Log.v(TAG, "finishAnimationLw::mHideKeyguard="+mHideLockScreen);
Dianne Hackborn05726582009-09-22 17:28:24 -07002734 if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
Dianne Hackborn08743722009-12-21 12:16:51 -08002735 if (mKeyguard.hideLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002736 changes |= FINISH_LAYOUT_REDO_LAYOUT
2737 | FINISH_LAYOUT_REDO_CONFIG
2738 | FINISH_LAYOUT_REDO_WALLPAPER;
2739 }
Dianne Hackborn05726582009-09-22 17:28:24 -07002740 if (mKeyguardMediator.isShowing()) {
Dianne Hackbornb446e972009-09-20 15:23:25 -07002741 mHandler.post(new Runnable() {
2742 public void run() {
Dianne Hackborn05726582009-09-22 17:28:24 -07002743 mKeyguardMediator.keyguardDone(false, false);
Dianne Hackbornb446e972009-09-20 15:23:25 -07002744 }
2745 });
2746 }
Dianne Hackborn05726582009-09-22 17:28:24 -07002747 } else if (mHideLockScreen) {
Dianne Hackborn08743722009-12-21 12:16:51 -08002748 if (mKeyguard.hideLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002749 changes |= FINISH_LAYOUT_REDO_LAYOUT
2750 | FINISH_LAYOUT_REDO_CONFIG
2751 | FINISH_LAYOUT_REDO_WALLPAPER;
2752 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05002753 mKeyguardMediator.setHidden(true);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002754 } else {
Dianne Hackborn08743722009-12-21 12:16:51 -08002755 if (mKeyguard.showLw(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 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05002760 mKeyguardMediator.setHidden(false);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002761 }
2762 }
Joe Onorato664644d2011-01-23 17:53:23 -08002763
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002764 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002765 // If the navigation bar has been hidden or shown, we need to do another
2766 // layout pass to update that window.
2767 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2768 }
Joe Onorato664644d2011-01-23 17:53:23 -08002769
Mike Lockwood28569302010-01-28 11:54:40 -05002770 // update since mAllowLockscreenWhenOn might have changed
2771 updateLockScreenTimeout();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002772 return changes;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002773 }
2774
Dianne Hackborn08743722009-12-21 12:16:51 -08002775 public boolean allowAppAnimationsLw() {
2776 if (mKeyguard != null && mKeyguard.isVisibleLw()) {
2777 // If keyguard is currently visible, no reason to animate
2778 // behind it.
2779 return false;
2780 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002781 if (mStatusBar != null && mStatusBar.isVisibleLw()) {
2782 RectF rect = new RectF(mStatusBar.getShownFrameLw());
Dianne Hackborn7f58b952012-04-18 12:59:29 -07002783 for (int i=mStatusBarSubPanels.size()-1; i>=0; i--) {
2784 WindowState w = mStatusBarSubPanels.get(i);
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002785 if (w.isVisibleLw()) {
2786 rect.union(w.getShownFrameLw());
Dianne Hackborn08743722009-12-21 12:16:51 -08002787 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002788 }
2789 final int insetw = mRestrictedScreenWidth/10;
2790 final int inseth = mRestrictedScreenHeight/10;
2791 if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw,
2792 mRestrictedScreenHeight-inseth)) {
2793 // All of the status bar windows put together cover the
2794 // screen, so the app can't be seen. (Note this test doesn't
2795 // work if the rects of these windows are at odd offsets or
2796 // sizes, causing gaps in the rect union we have computed.)
2797 return false;
Dianne Hackborn08743722009-12-21 12:16:51 -08002798 }
2799 }
2800 return true;
2801 }
2802
Dianne Hackborndf89e652011-10-06 22:35:11 -07002803 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
Joe Onorato664644d2011-01-23 17:53:23 -08002804 mFocusedWindow = newFocus;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002805 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002806 // If the navigation bar has been hidden or shown, we need to do another
2807 // layout pass to update that window.
2808 return FINISH_LAYOUT_REDO_LAYOUT;
2809 }
2810 return 0;
Joe Onorato664644d2011-01-23 17:53:23 -08002811 }
2812
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07002813 /** {@inheritDoc} */
Jeff Brown46b9ac02010-04-22 18:58:52 -07002814 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002815 // do nothing if headless
Mike Lockwoodd747dc82011-09-13 16:28:22 -04002816 if (mHeadless) return;
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002817
Jeff Brown46b9ac02010-04-22 18:58:52 -07002818 // lid changed state
Jeff Brown2e7760e2012-04-11 15:14:55 -07002819 mLidState = lidOpen ? LID_OPEN : LID_CLOSED;
Jeff Brown01a98dd2011-09-20 15:08:29 -07002820 updateKeyboardVisibility();
2821
Jeff Brown4aed78b2011-01-14 17:36:55 -08002822 boolean awakeNow = mKeyguardMediator.doLidChangeTq(lidOpen);
Jeff Brown01a98dd2011-09-20 15:08:29 -07002823 updateRotation(true);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002824 if (awakeNow) {
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002825 // If the lid is opening and we don't have to keep the
Jeff Brown46b9ac02010-04-22 18:58:52 -07002826 // keyguard up, then we can turn on the screen
2827 // immediately.
2828 mKeyguardMediator.pokeWakelock();
2829 } else if (keyguardIsShowingTq()) {
Jeff Brown4aed78b2011-01-14 17:36:55 -08002830 if (lidOpen) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002831 // If we are opening the lid and not hiding the
2832 // keyguard, then we need to have it turn on the
2833 // screen once it is shown.
2834 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
Jeff Brown43150bf2011-11-08 20:22:03 -08002835 KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002836 }
2837 } else {
2838 // Light up the keyboard if we are sliding up.
Jeff Brown4aed78b2011-01-14 17:36:55 -08002839 if (lidOpen) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002840 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
2841 LocalPowerManager.BUTTON_EVENT);
2842 } else {
2843 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
2844 LocalPowerManager.OTHER_EVENT);
2845 }
2846 }
2847 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002848
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002849 void setHdmiPlugged(boolean plugged) {
2850 if (mHdmiPlugged != plugged) {
2851 mHdmiPlugged = plugged;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002852 if (plugged && mDisplay != null) {
2853 mExternalDisplayWidth = mDisplay.getRawExternalWidth();
2854 mExternalDisplayHeight = mDisplay.getRawExternalHeight();
2855 }
2856 updateRotation(true, true);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002857 Intent intent = new Intent(ACTION_HDMI_PLUGGED);
Joe Onoratodc100302011-01-11 17:07:41 -08002858 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002859 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
2860 mContext.sendStickyBroadcast(intent);
2861 }
2862 }
2863
Joe Onoratoea495d42011-04-06 11:41:11 -07002864 void initializeHdmiState() {
Joe Onorato7ba631f2011-05-04 15:28:00 -07002865 boolean plugged = false;
Joe Onoratoea495d42011-04-06 11:41:11 -07002866 // watch for HDMI plug messages if the hdmi switch exists
2867 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
2868 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
2869
Joe Onoratoea495d42011-04-06 11:41:11 -07002870 final String filename = "/sys/class/switch/hdmi/state";
2871 FileReader reader = null;
2872 try {
2873 reader = new FileReader(filename);
2874 char[] buf = new char[15];
2875 int n = reader.read(buf);
2876 if (n > 1) {
2877 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
2878 }
2879 } catch (IOException ex) {
2880 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
2881 } catch (NumberFormatException ex) {
2882 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
2883 } finally {
2884 if (reader != null) {
2885 try {
2886 reader.close();
2887 } catch (IOException ex) {
2888 }
Joe Onoratodc100302011-01-11 17:07:41 -08002889 }
2890 }
2891 }
Joe Onorato7ba631f2011-05-04 15:28:00 -07002892 // This dance forces the code in setHdmiPlugged to run.
2893 // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
2894 mHdmiPlugged = !plugged;
2895 setHdmiPlugged(!mHdmiPlugged);
Joe Onoratodc100302011-01-11 17:07:41 -08002896 }
2897
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002898 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002899 * @return Whether music is being played right now.
2900 */
2901 boolean isMusicActive() {
Eric Laurent413cb9d2009-07-17 11:52:43 -07002902 final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
2903 if (am == null) {
2904 Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002905 return false;
2906 }
Eric Laurent413cb9d2009-07-17 11:52:43 -07002907 return am.isMusicActive();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002908 }
2909
2910 /**
2911 * Tell the audio service to adjust the volume appropriate to the event.
2912 * @param keycode
2913 */
Mike Lockwooda53e3812009-09-25 10:51:39 -04002914 void handleVolumeKey(int stream, int keycode) {
Jeff Brown4d396052010-10-29 21:50:21 -07002915 IAudioService audioService = getAudioService();
2916 if (audioService == null) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002917 return;
2918 }
2919 try {
2920 // since audio is playing, we shouldn't have to hold a wake lock
2921 // during the call, but we do it as a precaution for the rare possibility
2922 // that the music stops right before we call this
Jeff Brownb0418da2010-11-01 15:24:01 -07002923 // TODO: Actually handle MUTE.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002924 mBroadcastWakeLock.acquire();
Jeff Brown4d396052010-10-29 21:50:21 -07002925 audioService.adjustStreamVolume(stream,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002926 keycode == KeyEvent.KEYCODE_VOLUME_UP
2927 ? AudioManager.ADJUST_RAISE
2928 : AudioManager.ADJUST_LOWER,
2929 0);
2930 } catch (RemoteException e) {
2931 Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e);
2932 } finally {
2933 mBroadcastWakeLock.release();
2934 }
2935 }
Jeff Brown4d396052010-10-29 21:50:21 -07002936
Dianne Hackbornc0e3f242011-08-19 14:19:10 -07002937 final Object mScreenshotLock = new Object();
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07002938 ServiceConnection mScreenshotConnection = null;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07002939
Jeff Brownd5bb82d2011-10-12 13:57:59 -07002940 final Runnable mScreenshotTimeout = new Runnable() {
2941 @Override public void run() {
2942 synchronized (mScreenshotLock) {
2943 if (mScreenshotConnection != null) {
2944 mContext.unbindService(mScreenshotConnection);
2945 mScreenshotConnection = null;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07002946 }
Winson Chung9112ec32011-06-27 13:15:32 -07002947 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07002948 }
2949 };
2950
2951 // Assume this is called from the Handler thread.
2952 private void takeScreenshot() {
2953 synchronized (mScreenshotLock) {
2954 if (mScreenshotConnection != null) {
2955 return;
2956 }
2957 ComponentName cn = new ComponentName("com.android.systemui",
2958 "com.android.systemui.screenshot.TakeScreenshotService");
2959 Intent intent = new Intent();
2960 intent.setComponent(cn);
2961 ServiceConnection conn = new ServiceConnection() {
2962 @Override
2963 public void onServiceConnected(ComponentName name, IBinder service) {
2964 synchronized (mScreenshotLock) {
2965 if (mScreenshotConnection != this) {
2966 return;
2967 }
2968 Messenger messenger = new Messenger(service);
2969 Message msg = Message.obtain(null, 1);
2970 final ServiceConnection myConn = this;
2971 Handler h = new Handler(mHandler.getLooper()) {
2972 @Override
2973 public void handleMessage(Message msg) {
2974 synchronized (mScreenshotLock) {
2975 if (mScreenshotConnection == myConn) {
2976 mContext.unbindService(mScreenshotConnection);
2977 mScreenshotConnection = null;
2978 mHandler.removeCallbacks(mScreenshotTimeout);
2979 }
2980 }
2981 }
2982 };
2983 msg.replyTo = new Messenger(h);
Winson Chunga63bb842011-10-17 10:26:28 -07002984 msg.arg1 = msg.arg2 = 0;
2985 if (mStatusBar != null && mStatusBar.isVisibleLw())
2986 msg.arg1 = 1;
2987 if (mNavigationBar != null && mNavigationBar.isVisibleLw())
2988 msg.arg2 = 1;
Jeff Brownd5bb82d2011-10-12 13:57:59 -07002989 try {
2990 messenger.send(msg);
2991 } catch (RemoteException e) {
2992 }
2993 }
2994 }
2995 @Override
2996 public void onServiceDisconnected(ComponentName name) {}
2997 };
2998 if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
2999 mScreenshotConnection = conn;
3000 mHandler.postDelayed(mScreenshotTimeout, 10000);
3001 }
3002 }
Winson Chung9112ec32011-06-27 13:15:32 -07003003 }
3004
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003005 /** {@inheritDoc} */
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003006 @Override
Jeff Brown1f245102010-11-18 20:53:46 -08003007 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
3008 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
3009 final boolean canceled = event.isCanceled();
3010 final int keyCode = event.getKeyCode();
Jeff Browne20c9e02010-10-11 14:20:19 -07003011
Jeff Brown3122e442010-10-11 23:32:49 -07003012 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
Jeff Brown3122e442010-10-11 23:32:49 -07003013
Mike Lockwoodc72b15f2009-11-28 20:58:22 -05003014 // If screen is off then we treat the case where the keyguard is open but hidden
3015 // the same as if it were open and in front.
3016 // This will prevent any keys other than the power button from waking the screen
3017 // when the keyguard is hidden by another activity.
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003018 final boolean keyguardActive = (mKeyguardMediator == null ? false :
3019 (isScreenOn ?
3020 mKeyguardMediator.isShowingAndNotHidden() :
3021 mKeyguardMediator.isShowing()));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003022
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07003023 if (!mSystemBooted) {
3024 // If we have not yet booted, don't let key events do anything.
3025 return 0;
3026 }
3027
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003028 if (false) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003029 Log.d(TAG, "interceptKeyTq keycode=" + keyCode
3030 + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003031 }
3032
Jeff Brown98392ef2011-09-12 18:24:59 -07003033 if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
3034 && event.getRepeatCount() == 0) {
Jeff Brown4d396052010-10-29 21:50:21 -07003035 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
3036 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003037
Jeff Brownbc072da2011-11-15 12:56:55 -08003038 if (keyCode == KeyEvent.KEYCODE_POWER) {
3039 policyFlags |= WindowManagerPolicy.FLAG_WAKE;
3040 }
3041 final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
3042 | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
3043
Jeff Brown4d396052010-10-29 21:50:21 -07003044 // Basic policy based on screen state and keyguard.
3045 // FIXME: This policy isn't quite correct. We shouldn't care whether the screen
3046 // is on or off, really. We should care about whether the device is in an
3047 // interactive state or is in suspend pretending to be "off".
3048 // The primary screen might be turned off due to proximity sensor or
3049 // because we are presenting media on an auxiliary screen or remotely controlling
3050 // the device some other way (which is why we have an exemption here for injected
3051 // events).
3052 int result;
Mike Lockwoodd747dc82011-09-13 16:28:22 -04003053 if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) {
Jeff Brown4d396052010-10-29 21:50:21 -07003054 // When the screen is on or if the key is injected pass the key to the application.
3055 result = ACTION_PASS_TO_USER;
3056 } else {
3057 // When the screen is off and the key is not injected, determine whether
3058 // to wake the device but don't pass the key to the application.
3059 result = 0;
Jeff Brown4d396052010-10-29 21:50:21 -07003060 if (down && isWakeKey) {
3061 if (keyguardActive) {
3062 // If the keyguard is showing, let it decide what to do with the wake key.
Jeff Brown43150bf2011-11-08 20:22:03 -08003063 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode,
3064 mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
Jeff Brown4d396052010-10-29 21:50:21 -07003065 } else {
3066 // Otherwise, wake the device ourselves.
3067 result |= ACTION_POKE_USER_ACTIVITY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003068 }
3069 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003070 }
3071
Jeff Brown4d396052010-10-29 21:50:21 -07003072 // Handle special keys.
3073 switch (keyCode) {
3074 case KeyEvent.KEYCODE_VOLUME_DOWN:
Jeff Brownb0418da2010-11-01 15:24:01 -07003075 case KeyEvent.KEYCODE_VOLUME_UP:
3076 case KeyEvent.KEYCODE_VOLUME_MUTE: {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003077 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
3078 if (down) {
3079 if (isScreenOn && !mVolumeDownKeyTriggered
3080 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3081 mVolumeDownKeyTriggered = true;
3082 mVolumeDownKeyTime = event.getDownTime();
3083 mVolumeDownKeyConsumedByScreenshotChord = false;
3084 cancelPendingPowerKeyAction();
3085 interceptScreenshotChord();
3086 }
3087 } else {
3088 mVolumeDownKeyTriggered = false;
3089 cancelPendingScreenshotChordAction();
3090 }
3091 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
3092 if (down) {
3093 if (isScreenOn && !mVolumeUpKeyTriggered
3094 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3095 mVolumeUpKeyTriggered = true;
3096 cancelPendingPowerKeyAction();
3097 cancelPendingScreenshotChordAction();
3098 }
3099 } else {
3100 mVolumeUpKeyTriggered = false;
3101 cancelPendingScreenshotChordAction();
3102 }
3103 }
Jeff Brown4d396052010-10-29 21:50:21 -07003104 if (down) {
3105 ITelephony telephonyService = getTelephonyService();
3106 if (telephonyService != null) {
3107 try {
3108 if (telephonyService.isRinging()) {
3109 // If an incoming call is ringing, either VOLUME key means
3110 // "silence ringer". We handle these keys here, rather than
3111 // in the InCallScreen, to make sure we'll respond to them
3112 // even if the InCallScreen hasn't come to the foreground yet.
3113 // Look for the DOWN event here, to agree with the "fallback"
3114 // behavior in the InCallScreen.
3115 Log.i(TAG, "interceptKeyBeforeQueueing:"
3116 + " VOLUME key-down while ringing: Silence ringer!");
3117
3118 // Silence the ringer. (It's safe to call this
3119 // even if the ringer has already been silenced.)
3120 telephonyService.silenceRinger();
3121
3122 // And *don't* pass this key thru to the current activity
3123 // (which is probably the InCallScreen.)
3124 result &= ~ACTION_PASS_TO_USER;
3125 break;
3126 }
3127 if (telephonyService.isOffhook()
3128 && (result & ACTION_PASS_TO_USER) == 0) {
3129 // If we are in call but we decided not to pass the key to
3130 // the application, handle the volume change here.
3131 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
3132 break;
3133 }
3134 } catch (RemoteException ex) {
3135 Log.w(TAG, "ITelephony threw RemoteException", ex);
3136 }
3137 }
3138
3139 if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) {
3140 // If music is playing but we decided not to pass the key to the
3141 // application, handle the volume change here.
3142 handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
3143 break;
3144 }
3145 }
3146 break;
3147 }
3148
3149 case KeyEvent.KEYCODE_ENDCALL: {
3150 result &= ~ACTION_PASS_TO_USER;
3151 if (down) {
3152 ITelephony telephonyService = getTelephonyService();
3153 boolean hungUp = false;
3154 if (telephonyService != null) {
3155 try {
3156 hungUp = telephonyService.endCall();
3157 } catch (RemoteException ex) {
3158 Log.w(TAG, "ITelephony threw RemoteException", ex);
3159 }
3160 }
3161 interceptPowerKeyDown(!isScreenOn || hungUp);
3162 } else {
3163 if (interceptPowerKeyUp(canceled)) {
3164 if ((mEndcallBehavior
3165 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
3166 if (goHome()) {
3167 break;
Dianne Hackborn0041e972009-07-24 17:14:43 -07003168 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003169 }
Jeff Brown4d396052010-10-29 21:50:21 -07003170 if ((mEndcallBehavior
3171 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
3172 result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
3173 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003174 }
Jeff Brown4d396052010-10-29 21:50:21 -07003175 }
3176 break;
3177 }
3178
3179 case KeyEvent.KEYCODE_POWER: {
3180 result &= ~ACTION_PASS_TO_USER;
3181 if (down) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003182 if (isScreenOn && !mPowerKeyTriggered
3183 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3184 mPowerKeyTriggered = true;
3185 mPowerKeyTime = event.getDownTime();
3186 interceptScreenshotChord();
Winson Chung9112ec32011-06-27 13:15:32 -07003187 }
Winson Chung9112ec32011-06-27 13:15:32 -07003188
Jeff Brown4d396052010-10-29 21:50:21 -07003189 ITelephony telephonyService = getTelephonyService();
3190 boolean hungUp = false;
3191 if (telephonyService != null) {
3192 try {
3193 if (telephonyService.isRinging()) {
3194 // Pressing Power while there's a ringing incoming
3195 // call should silence the ringer.
3196 telephonyService.silenceRinger();
3197 } else if ((mIncallPowerBehavior
3198 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
3199 && telephonyService.isOffhook()) {
3200 // Otherwise, if "Power button ends call" is enabled,
3201 // the Power button will hang up any current active call.
3202 hungUp = telephonyService.endCall();
3203 }
3204 } catch (RemoteException ex) {
3205 Log.w(TAG, "ITelephony threw RemoteException", ex);
3206 }
3207 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003208 interceptPowerKeyDown(!isScreenOn || hungUp
3209 || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003210 } else {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003211 mPowerKeyTriggered = false;
3212 cancelPendingScreenshotChordAction();
3213 if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
Jeff Brown4d396052010-10-29 21:50:21 -07003214 result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003215 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003216 mPendingPowerKeyUpCanceled = false;
Jeff Brown4d396052010-10-29 21:50:21 -07003217 }
3218 break;
3219 }
3220
3221 case KeyEvent.KEYCODE_MEDIA_PLAY:
3222 case KeyEvent.KEYCODE_MEDIA_PAUSE:
3223 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
3224 if (down) {
3225 ITelephony telephonyService = getTelephonyService();
3226 if (telephonyService != null) {
3227 try {
3228 if (!telephonyService.isIdle()) {
3229 // Suppress PLAY/PAUSE toggle when phone is ringing or in-call
3230 // to avoid music playback.
3231 break;
3232 }
3233 } catch (RemoteException ex) {
3234 Log.w(TAG, "ITelephony threw RemoteException", ex);
Jeff Brown3122e442010-10-11 23:32:49 -07003235 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003236 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003237 }
Jeff Brown4d396052010-10-29 21:50:21 -07003238 case KeyEvent.KEYCODE_HEADSETHOOK:
3239 case KeyEvent.KEYCODE_MUTE:
3240 case KeyEvent.KEYCODE_MEDIA_STOP:
3241 case KeyEvent.KEYCODE_MEDIA_NEXT:
3242 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
3243 case KeyEvent.KEYCODE_MEDIA_REWIND:
3244 case KeyEvent.KEYCODE_MEDIA_RECORD:
3245 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
3246 if ((result & ACTION_PASS_TO_USER) == 0) {
3247 // Only do this if we would otherwise not pass it to the user. In that
3248 // case, the PhoneWindow class will do the same thing, except it will
3249 // only do it if the showing app doesn't process the key on its own.
Jeff Brown4d396052010-10-29 21:50:21 -07003250 mBroadcastWakeLock.acquire();
Jeff Brown1f245102010-11-18 20:53:46 -08003251 mHandler.post(new PassHeadsetKey(new KeyEvent(event)));
Jeff Brown4d396052010-10-29 21:50:21 -07003252 }
3253 break;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003254 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003255
Jeff Brown4d396052010-10-29 21:50:21 -07003256 case KeyEvent.KEYCODE_CALL: {
3257 if (down) {
3258 ITelephony telephonyService = getTelephonyService();
3259 if (telephonyService != null) {
3260 try {
3261 if (telephonyService.isRinging()) {
3262 Log.i(TAG, "interceptKeyBeforeQueueing:"
3263 + " CALL key-down while ringing: Answer the call!");
3264 telephonyService.answerRingingCall();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003265
Jeff Brown4d396052010-10-29 21:50:21 -07003266 // And *don't* pass this key thru to the current activity
3267 // (which is presumably the InCallScreen.)
3268 result &= ~ACTION_PASS_TO_USER;
3269 }
3270 } catch (RemoteException ex) {
3271 Log.w(TAG, "ITelephony threw RemoteException", ex);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003272 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003273 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003274 }
Jeff Brown4d396052010-10-29 21:50:21 -07003275 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003276 }
3277 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003278 return result;
3279 }
3280
Jeff Brown56194eb2011-03-02 19:23:13 -08003281 /** {@inheritDoc} */
3282 @Override
3283 public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
3284 int result = 0;
3285
3286 final boolean isWakeMotion = (policyFlags
3287 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
3288 if (isWakeMotion) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003289 if (mKeyguardMediator != null && mKeyguardMediator.isShowing()) {
Jeff Brown56194eb2011-03-02 19:23:13 -08003290 // If the keyguard is showing, let it decide what to do with the wake motion.
3291 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
3292 } else {
3293 // Otherwise, wake the device ourselves.
3294 result |= ACTION_POKE_USER_ACTIVITY;
3295 }
3296 }
3297 return result;
3298 }
3299
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003300 class PassHeadsetKey implements Runnable {
3301 KeyEvent mKeyEvent;
3302
3303 PassHeadsetKey(KeyEvent keyEvent) {
3304 mKeyEvent = keyEvent;
3305 }
3306
3307 public void run() {
3308 if (ActivityManagerNative.isSystemReady()) {
3309 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
3310 intent.putExtra(Intent.EXTRA_KEY_EVENT, mKeyEvent);
3311 mContext.sendOrderedBroadcast(intent, null, mBroadcastDone,
3312 mHandler, Activity.RESULT_OK, null, null);
3313 }
3314 }
3315 }
3316
3317 BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
3318 public void onReceive(Context context, Intent intent) {
3319 mBroadcastWakeLock.release();
3320 }
3321 };
Mike Lockwood1753f7f2009-08-24 14:49:07 -07003322
3323 BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
3324 public void onReceive(Context context, Intent intent) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07003325 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
3326 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
3327 Intent.EXTRA_DOCK_STATE_UNDOCKED);
3328 } else {
3329 try {
3330 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
3331 ServiceManager.getService(Context.UI_MODE_SERVICE));
3332 mUiMode = uiModeService.getCurrentModeType();
3333 } catch (RemoteException e) {
3334 }
Dianne Hackborn80fa1662009-10-07 14:02:10 -07003335 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003336 updateRotation(true);
Mike Lockwoode9867d22009-09-20 01:59:02 -04003337 updateOrientationListenerLp();
Mike Lockwood1753f7f2009-08-24 14:49:07 -07003338 }
3339 };
3340
Daniel Sandler7e37df52011-11-16 22:08:23 -08003341 BroadcastReceiver mPowerReceiver = new BroadcastReceiver() {
3342 public void onReceive(Context context, Intent intent) {
3343 if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
3344 mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
3345 if (localLOGV) Log.v(TAG, "BATTERY_CHANGED: " + intent + " plugged=" + mPluggedIn);
3346 }
3347 }
3348 };
3349
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003350 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003351 public void screenTurnedOff(int why) {
Dianne Hackborn74489012009-03-24 20:50:09 -07003352 EventLog.writeEvent(70000, 0);
The Android Open Source Project0727d222009-03-11 12:11:58 -07003353 synchronized (mLock) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003354 mScreenOnEarly = false;
3355 mScreenOnFully = false;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003356 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003357 if (mKeyguardMediator != null) {
3358 mKeyguardMediator.onScreenTurnedOff(why);
3359 }
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003360 synchronized (mLock) {
The Android Open Source Project0727d222009-03-11 12:11:58 -07003361 updateOrientationListenerLp();
Mike Lockwood28569302010-01-28 11:54:40 -05003362 updateLockScreenTimeout();
The Android Open Source Project0727d222009-03-11 12:11:58 -07003363 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003364 }
3365
3366 /** {@inheritDoc} */
Dianne Hackborn38e29a62011-09-18 14:43:08 -07003367 public void screenTurningOn(final ScreenOnListener screenOnListener) {
Dianne Hackborn74489012009-03-24 20:50:09 -07003368 EventLog.writeEvent(70000, 1);
Dianne Hackborn40011092011-09-22 13:37:48 -07003369 if (false) {
3370 RuntimeException here = new RuntimeException("here");
3371 here.fillInStackTrace();
3372 Slog.i(TAG, "Screen turning on...", here);
3373 }
3374 if (screenOnListener != null) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003375 if (mKeyguardMediator != null) {
3376 mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
3377 @Override public void onShown(IBinder windowToken) {
3378 if (windowToken != null) {
3379 try {
3380 mWindowManager.waitForWindowDrawn(windowToken,
3381 new IRemoteCallback.Stub() {
3382 @Override public void sendResult(Bundle data) {
3383 Slog.i(TAG, "Lock screen displayed!");
3384 screenOnListener.onScreenOn();
3385 synchronized (mLock) {
3386 mScreenOnFully = true;
3387 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003388 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003389 });
3390 } catch (RemoteException e) {
3391 }
3392 } else {
3393 Slog.i(TAG, "No lock screen!");
3394 screenOnListener.onScreenOn();
3395 synchronized (mLock) {
3396 mScreenOnFully = true;
3397 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003398 }
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003399 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003400 });
3401 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003402 } else {
3403 synchronized (mLock) {
3404 mScreenOnFully = true;
Dianne Hackborn38e29a62011-09-18 14:43:08 -07003405 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003406 }
The Android Open Source Project0727d222009-03-11 12:11:58 -07003407 synchronized (mLock) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003408 mScreenOnEarly = true;
The Android Open Source Project0727d222009-03-11 12:11:58 -07003409 updateOrientationListenerLp();
Mike Lockwood28569302010-01-28 11:54:40 -05003410 updateLockScreenTimeout();
The Android Open Source Project0727d222009-03-11 12:11:58 -07003411 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003412 }
3413
3414 /** {@inheritDoc} */
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003415 public boolean isScreenOnEarly() {
3416 return mScreenOnEarly;
3417 }
3418
3419 /** {@inheritDoc} */
3420 public boolean isScreenOnFully() {
3421 return mScreenOnFully;
Dianne Hackborn08743722009-12-21 12:16:51 -08003422 }
3423
3424 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003425 public void enableKeyguard(boolean enabled) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003426 if (mKeyguardMediator != null) {
3427 mKeyguardMediator.setKeyguardEnabled(enabled);
3428 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003429 }
3430
3431 /** {@inheritDoc} */
3432 public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003433 if (mKeyguardMediator != null) {
3434 mKeyguardMediator.verifyUnlock(callback);
3435 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003436 }
3437
Mike Lockwoodf7913302009-11-28 22:27:10 -05003438 private boolean keyguardIsShowingTq() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003439 if (mKeyguardMediator == null) return false;
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08003440 return mKeyguardMediator.isShowingAndNotHidden();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003441 }
3442
Mike Lockwood520d8bc2011-02-18 13:23:13 -05003443
3444 /** {@inheritDoc} */
3445 public boolean isKeyguardLocked() {
3446 return keyguardOn();
3447 }
3448
3449 /** {@inheritDoc} */
3450 public boolean isKeyguardSecure() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003451 if (mKeyguardMediator == null) return false;
Mike Lockwood520d8bc2011-02-18 13:23:13 -05003452 return mKeyguardMediator.isSecure();
3453 }
3454
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003455 /** {@inheritDoc} */
3456 public boolean inKeyguardRestrictedKeyInputMode() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003457 if (mKeyguardMediator == null) return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003458 return mKeyguardMediator.isInputRestricted();
3459 }
3460
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003461 public void dismissKeyguardLw() {
3462 if (!mKeyguardMediator.isSecure()) {
3463 if (mKeyguardMediator.isShowing()) {
3464 mHandler.post(new Runnable() {
3465 public void run() {
3466 mKeyguardMediator.keyguardDone(false, true);
3467 }
3468 });
3469 }
3470 }
3471 }
3472
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003473 void sendCloseSystemWindows() {
3474 sendCloseSystemWindows(mContext, null);
3475 }
3476
3477 void sendCloseSystemWindows(String reason) {
3478 sendCloseSystemWindows(mContext, reason);
3479 }
3480
3481 static void sendCloseSystemWindows(Context context, String reason) {
3482 if (ActivityManagerNative.isSystemReady()) {
Dianne Hackborn94a679d2009-07-28 17:51:07 -07003483 try {
3484 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
3485 } catch (RemoteException e) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003486 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003487 }
3488 }
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07003489
Jeff Brown01a98dd2011-09-20 15:08:29 -07003490 @Override
3491 public int rotationForOrientationLw(int orientation, int lastRotation) {
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003492 if (false) {
3493 Slog.v(TAG, "rotationForOrientationLw(orient="
3494 + orientation + ", last=" + lastRotation
3495 + "); user=" + mUserRotation + " "
3496 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
3497 ? "USER_ROTATION_LOCKED" : "")
3498 );
3499 }
3500
The Android Open Source Project0727d222009-03-11 12:11:58 -07003501 synchronized (mLock) {
Jeff Brownc0347aa2011-09-23 17:26:09 -07003502 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
3503 if (sensorRotation < 0) {
3504 sensorRotation = lastRotation;
3505 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003506
Jeff Browndec6cf42011-11-15 14:08:20 -08003507 final int preferredRotation;
Jeff Brown2e7760e2012-04-11 15:14:55 -07003508 if (mLidState == LID_OPEN && mLidOpenRotation >= 0) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003509 // Ignore sensor when lid switch is open and rotation is forced.
3510 preferredRotation = mLidOpenRotation;
3511 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
Jeff Brownc0347aa2011-09-23 17:26:09 -07003512 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003513 // Ignore sensor when in car dock unless explicitly enabled.
3514 // This case can override the behavior of NOSENSOR, and can also
3515 // enable 180 degree rotation while docked.
Jeff Brownc0347aa2011-09-23 17:26:09 -07003516 preferredRotation = mCarDockEnablesAccelerometer
Jeff Brown01a98dd2011-09-20 15:08:29 -07003517 ? sensorRotation : mCarDockRotation;
Jeff Brown1a693182011-11-08 14:44:16 -08003518 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
3519 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
3520 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
Jeff Brownc0347aa2011-09-23 17:26:09 -07003521 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003522 // Ignore sensor when in desk dock unless explicitly enabled.
3523 // This case can override the behavior of NOSENSOR, and can also
3524 // enable 180 degree rotation while docked.
Jeff Brownc0347aa2011-09-23 17:26:09 -07003525 preferredRotation = mDeskDockEnablesAccelerometer
Jeff Brown01a98dd2011-09-20 15:08:29 -07003526 ? sensorRotation : mDeskDockRotation;
Jeff Browneb3e4b92011-12-06 19:54:24 -08003527 } else if (mHdmiPlugged) {
3528 // Ignore sensor when plugged into HDMI.
3529 // Note that the dock orientation overrides the HDMI orientation.
3530 preferredRotation = mHdmiRotation;
Jeff Brown4dfce202011-10-05 12:00:10 -07003531 } else if ((mAccelerometerDefault != 0 /* implies not rotation locked */
Jeff Brown01a98dd2011-09-20 15:08:29 -07003532 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
3533 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED))
3534 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
3535 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
3536 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
3537 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
3538 // Otherwise, use sensor only if requested by the application or enabled
3539 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR.
Jeff Brownd3187e32011-09-21 19:26:44 -07003540 if (mAllowAllRotations < 0) {
3541 // Can't read this during init() because the context doesn't
3542 // have display metrics at that time so we cannot determine
3543 // tablet vs. phone then.
3544 mAllowAllRotations = mContext.getResources().getBoolean(
3545 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
3546 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003547 if (sensorRotation != Surface.ROTATION_180
Jeff Brownd3187e32011-09-21 19:26:44 -07003548 || mAllowAllRotations == 1
Jeff Brown01a98dd2011-09-20 15:08:29 -07003549 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) {
3550 preferredRotation = sensorRotation;
3551 } else {
3552 preferredRotation = lastRotation;
3553 }
Jeff Brown4dfce202011-10-05 12:00:10 -07003554 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
3555 // Apply rotation lock.
3556 preferredRotation = mUserRotation;
Jeff Browndec6cf42011-11-15 14:08:20 -08003557 } else {
3558 // No overriding preference.
3559 // We will do exactly what the application asked us to do.
3560 preferredRotation = -1;
Jeff Brown01a98dd2011-09-20 15:08:29 -07003561 }
3562
Dianne Hackborne5439f22010-10-02 16:53:50 -07003563 switch (orientation) {
3564 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
Jeff Browndec6cf42011-11-15 14:08:20 -08003565 // Return portrait unless overridden.
3566 if (isAnyPortrait(preferredRotation)) {
3567 return preferredRotation;
3568 }
Dianne Hackborne5439f22010-10-02 16:53:50 -07003569 return mPortraitRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003570
Jeff Brown01a98dd2011-09-20 15:08:29 -07003571 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
Jeff Browndec6cf42011-11-15 14:08:20 -08003572 // Return landscape unless overridden.
3573 if (isLandscapeOrSeascape(preferredRotation)) {
3574 return preferredRotation;
3575 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003576 return mLandscapeRotation;
3577
3578 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
Jeff Browndec6cf42011-11-15 14:08:20 -08003579 // Return reverse portrait unless overridden.
3580 if (isAnyPortrait(preferredRotation)) {
3581 return preferredRotation;
3582 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003583 return mUpsideDownRotation;
3584
3585 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
Jeff Browndec6cf42011-11-15 14:08:20 -08003586 // Return seascape unless overridden.
3587 if (isLandscapeOrSeascape(preferredRotation)) {
3588 return preferredRotation;
3589 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003590 return mSeascapeRotation;
3591
3592 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
3593 // Return either landscape rotation.
3594 if (isLandscapeOrSeascape(preferredRotation)) {
3595 return preferredRotation;
3596 }
3597 if (isLandscapeOrSeascape(lastRotation)) {
Jeff Brown4519f072011-01-23 13:16:01 -08003598 return lastRotation;
3599 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003600 return mLandscapeRotation;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003601
Jeff Brown01a98dd2011-09-20 15:08:29 -07003602 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
3603 // Return either portrait rotation.
3604 if (isAnyPortrait(preferredRotation)) {
3605 return preferredRotation;
3606 }
3607 if (isAnyPortrait(lastRotation)) {
3608 return lastRotation;
3609 }
3610 return mPortraitRotation;
3611
3612 default:
Jeff Brown4dfce202011-10-05 12:00:10 -07003613 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
3614 // just return the preferred orientation we already calculated.
Jeff Brown01a98dd2011-09-20 15:08:29 -07003615 if (preferredRotation >= 0) {
3616 return preferredRotation;
3617 }
Dianne Hackborndacea8c2011-04-21 17:26:39 -07003618 return Surface.ROTATION_0;
Daniel Sandlere7e5ac22011-02-22 16:10:21 -05003619 }
3620 }
Steve Howarda7bfe6a2010-09-23 16:47:49 -07003621 }
3622
Jeff Brown01a98dd2011-09-20 15:08:29 -07003623 @Override
3624 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
3625 switch (orientation) {
3626 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
3627 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
3628 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
3629 return isAnyPortrait(rotation);
3630
3631 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
3632 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
3633 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
3634 return isLandscapeOrSeascape(rotation);
3635
3636 default:
3637 return true;
3638 }
Steve Howarda7bfe6a2010-09-23 16:47:49 -07003639 }
3640
Jeff Brownc0347aa2011-09-23 17:26:09 -07003641 @Override
3642 public void setRotationLw(int rotation) {
3643 mOrientationListener.setCurrentRotation(rotation);
3644 }
3645
Jeff Brown01a98dd2011-09-20 15:08:29 -07003646 private boolean isLandscapeOrSeascape(int rotation) {
3647 return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003648 }
3649
Jeff Brown01a98dd2011-09-20 15:08:29 -07003650 private boolean isAnyPortrait(int rotation) {
3651 return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003652 }
3653
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003654
3655 // User rotation: to be used when all else fails in assigning an orientation to the device
3656 public void setUserRotationMode(int mode, int rot) {
3657 ContentResolver res = mContext.getContentResolver();
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003658
3659 // mUserRotationMode and mUserRotation will be assigned by the content observer
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003660 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003661 Settings.System.putInt(res,
3662 Settings.System.USER_ROTATION,
3663 rot);
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003664 Settings.System.putInt(res,
3665 Settings.System.ACCELEROMETER_ROTATION,
3666 0);
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003667 } else {
3668 Settings.System.putInt(res,
3669 Settings.System.ACCELEROMETER_ROTATION,
3670 1);
3671 }
3672 }
3673
Jeff Brownac143512012-04-05 18:57:33 -07003674 public void setSafeMode(boolean safeMode) {
3675 mSafeMode = safeMode;
3676 performHapticFeedbackLw(null, safeMode
3677 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
3678 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003679 }
3680
Dianne Hackborn181ceb52009-08-27 22:16:40 -07003681 static long[] getLongIntArray(Resources r, int resid) {
3682 int[] ar = r.getIntArray(resid);
3683 if (ar == null) {
3684 return null;
3685 }
3686 long[] out = new long[ar.length];
3687 for (int i=0; i<ar.length; i++) {
3688 out[i] = ar[i];
3689 }
3690 return out;
3691 }
3692
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003693 /** {@inheritDoc} */
3694 public void systemReady() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003695 if (mKeyguardMediator != null) {
3696 // tell the keyguard
3697 mKeyguardMediator.onSystemReady();
3698 }
Dianne Hackbornb1a79802009-09-29 15:18:31 -07003699 synchronized (mLock) {
3700 updateOrientationListenerLp();
Dianne Hackbornc777e072010-02-12 13:07:59 -08003701 mSystemReady = true;
3702 mHandler.post(new Runnable() {
3703 public void run() {
3704 updateSettings();
3705 }
3706 });
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003707 }
3708 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07003709
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07003710 /** {@inheritDoc} */
3711 public void systemBooted() {
3712 synchronized (mLock) {
3713 mSystemBooted = true;
3714 }
3715 }
3716
Dianne Hackborn661cd522011-08-22 00:26:20 -07003717 ProgressDialog mBootMsgDialog = null;
3718
3719 /** {@inheritDoc} */
3720 public void showBootMessage(final CharSequence msg, final boolean always) {
Mike Lockwoodaa5bf142011-09-21 13:03:40 -04003721 if (mHeadless) return;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003722 mHandler.post(new Runnable() {
3723 @Override public void run() {
3724 if (mBootMsgDialog == null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07003725 mBootMsgDialog = new ProgressDialog(mContext) {
3726 // This dialog will consume all events coming in to
3727 // it, to avoid it trying to do things too early in boot.
3728 @Override public boolean dispatchKeyEvent(KeyEvent event) {
3729 return true;
3730 }
3731 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
3732 return true;
3733 }
3734 @Override public boolean dispatchTouchEvent(MotionEvent ev) {
3735 return true;
3736 }
3737 @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
3738 return true;
3739 }
3740 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
3741 return true;
3742 }
3743 @Override public boolean dispatchPopulateAccessibilityEvent(
3744 AccessibilityEvent event) {
3745 return true;
3746 }
3747 };
Dianne Hackborn661cd522011-08-22 00:26:20 -07003748 mBootMsgDialog.setTitle(R.string.android_upgrading_title);
3749 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
3750 mBootMsgDialog.setIndeterminate(true);
3751 mBootMsgDialog.getWindow().setType(
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003752 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
Dianne Hackborn661cd522011-08-22 00:26:20 -07003753 mBootMsgDialog.getWindow().addFlags(
3754 WindowManager.LayoutParams.FLAG_DIM_BEHIND
3755 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
3756 mBootMsgDialog.getWindow().setDimAmount(1);
Dianne Hackbornd9efb952011-12-07 14:56:51 -08003757 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
3758 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
3759 mBootMsgDialog.getWindow().setAttributes(lp);
Dianne Hackborn661cd522011-08-22 00:26:20 -07003760 mBootMsgDialog.setCancelable(false);
3761 mBootMsgDialog.show();
3762 }
3763 mBootMsgDialog.setMessage(msg);
3764 }
3765 });
3766 }
3767
3768 /** {@inheritDoc} */
3769 public void hideBootMessages() {
3770 mHandler.post(new Runnable() {
3771 @Override public void run() {
3772 if (mBootMsgDialog != null) {
3773 mBootMsgDialog.dismiss();
3774 mBootMsgDialog = null;
3775 }
3776 }
3777 });
3778 }
3779
Mike Lockwood28569302010-01-28 11:54:40 -05003780 /** {@inheritDoc} */
3781 public void userActivity() {
Dianne Hackborndf89e652011-10-06 22:35:11 -07003782 // ***************************************
3783 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
3784 // ***************************************
3785 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
3786 // WITH ITS LOCKS HELD.
3787 //
3788 // This code must be VERY careful about the locks
3789 // it acquires.
3790 // In fact, the current code acquires way too many,
3791 // and probably has lurking deadlocks.
3792
Mike Lockwood28569302010-01-28 11:54:40 -05003793 synchronized (mScreenLockTimeout) {
3794 if (mLockScreenTimerActive) {
3795 // reset the timer
3796 mHandler.removeCallbacks(mScreenLockTimeout);
3797 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
3798 }
3799 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003800 }
3801
Daniel Sandler7d276c32012-01-30 14:33:52 -05003802 private IDreamManager getDreamManager() {
3803 if (!mScreenSaverFeatureAvailable) {
3804 return null;
3805 }
3806
3807 IDreamManager sandman = IDreamManager.Stub.asInterface(
3808 ServiceManager.checkService("dreams"));
3809 if (sandman == null) {
3810 Log.w(TAG, "Unable to find IDreamManager");
3811 }
3812 return sandman;
3813 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003814
Daniel Sandler7d276c32012-01-30 14:33:52 -05003815 @Override
3816 public boolean isScreenSaverEnabled() {
3817 return (mScreenSaverFeatureAvailable && mScreenSaverEnabledByUser
3818 && mScreenSaverMayRun && mScreenOnEarly && mPluggedIn);
3819 }
Daniel Sandler7e37df52011-11-16 22:08:23 -08003820
Daniel Sandler7d276c32012-01-30 14:33:52 -05003821 @Override
3822 public boolean startScreenSaver() {
3823 synchronized (mLock) {
3824 if (isScreenSaverEnabled()) {
3825 IDreamManager dm = getDreamManager();
3826 if (dm == null) return false;
3827
3828 try {
3829 if (localLOGV) Log.v(TAG, "startScreenSaver: entering dreamland...");
3830
3831 dm.dream();
3832 return true;
3833 } catch (RemoteException ex) {
3834 // too bad, so sad, oh mom, oh dad
Daniel Sandlerc224f762011-11-15 22:55:03 -08003835 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003836 }
3837 }
Daniel Sandler7d276c32012-01-30 14:33:52 -05003838 return false;
3839 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003840
Daniel Sandler7d276c32012-01-30 14:33:52 -05003841 @Override
3842 public void stopScreenSaver() {
3843 synchronized (mLock) {
3844 IDreamManager dm = getDreamManager();
3845 if (dm == null) return;
3846
3847 try {
3848 if (localLOGV) Log.v(TAG, "startScreenSaver: awakening...");
3849
3850 dm.awaken();
3851 } catch (RemoteException ex) {
Daniel Sandler0601eb72011-04-13 01:01:32 -04003852 }
3853 }
Mike Lockwood28569302010-01-28 11:54:40 -05003854 }
3855
3856 Runnable mScreenLockTimeout = new Runnable() {
3857 public void run() {
3858 synchronized (this) {
3859 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003860 if (mKeyguardMediator != null) {
3861 mKeyguardMediator.doKeyguardTimeout();
3862 }
Mike Lockwood28569302010-01-28 11:54:40 -05003863 mLockScreenTimerActive = false;
3864 }
3865 }
3866 };
3867
Jim Miller93c518e2012-01-17 15:55:31 -08003868 public void lockNow() {
3869 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
3870 mHandler.removeCallbacks(mScreenLockTimeout);
3871 mHandler.post(mScreenLockTimeout);
3872 }
3873
Mike Lockwood28569302010-01-28 11:54:40 -05003874 private void updateLockScreenTimeout() {
3875 synchronized (mScreenLockTimeout) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003876 boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly &&
3877 mKeyguardMediator != null && mKeyguardMediator.isSecure());
Mike Lockwood28569302010-01-28 11:54:40 -05003878 if (mLockScreenTimerActive != enable) {
3879 if (enable) {
3880 if (localLOGV) Log.v(TAG, "setting lockscreen timer");
3881 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
3882 } else {
3883 if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
3884 mHandler.removeCallbacks(mScreenLockTimeout);
3885 }
3886 mLockScreenTimerActive = enable;
3887 }
3888 }
3889 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003890
3891 /** {@inheritDoc} */
3892 public void enableScreenAfterBoot() {
3893 readLidState();
Jeff Brown01a98dd2011-09-20 15:08:29 -07003894 updateKeyboardVisibility();
3895
3896 updateRotation(true);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003897 }
Dianne Hackbornf54c8f92009-09-19 14:03:57 -07003898
Jeff Brown01a98dd2011-09-20 15:08:29 -07003899 private void updateKeyboardVisibility() {
Jeff Brown2e7760e2012-04-11 15:14:55 -07003900 mPowerManager.setKeyboardVisibility(mLidState == LID_OPEN);
Jeff Brown01a98dd2011-09-20 15:08:29 -07003901 }
3902
3903 void updateRotation(boolean alwaysSendConfiguration) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003904 try {
3905 //set orientation on WindowManager
Dianne Hackbornf87d1962012-04-04 12:48:24 -07003906 mWindowManager.updateRotation(alwaysSendConfiguration, false);
3907 } catch (RemoteException e) {
3908 // Ignore
3909 }
3910 }
3911
3912 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
3913 try {
3914 //set orientation on WindowManager
3915 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003916 } catch (RemoteException e) {
3917 // Ignore
3918 }
3919 }
3920
3921 /**
Daniel Sandler11ddf532011-11-16 11:10:03 -08003922 * Return an Intent to launch the currently active dock app as home. Returns
3923 * null if the standard home should be launched, which is the case if any of the following is
3924 * true:
3925 * <ul>
3926 * <li>The device is not in either car mode or desk mode
3927 * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
3928 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
3929 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
3930 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
3931 * </ul>
Dianne Hackborn39c2d712009-09-22 11:41:31 -07003932 * @return
3933 */
3934 Intent createHomeDockIntent() {
Daniel Sandler11ddf532011-11-16 11:10:03 -08003935 Intent intent = null;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07003936
3937 // What home does is based on the mode, not the dock state. That
3938 // is, when in car mode you should be taken to car home regardless
3939 // of whether we are actually in a car dock.
Dianne Hackborn78968392010-03-04 20:47:56 -08003940 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
Daniel Sandler11ddf532011-11-16 11:10:03 -08003941 if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
3942 intent = mCarDockIntent;
3943 }
Dianne Hackborn78968392010-03-04 20:47:56 -08003944 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
Daniel Sandler11ddf532011-11-16 11:10:03 -08003945 if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
3946 intent = mDeskDockIntent;
3947 }
3948 }
3949
3950 if (intent == null) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07003951 return null;
3952 }
3953
3954 ActivityInfo ai = intent.resolveActivityInfo(
3955 mContext.getPackageManager(), PackageManager.GET_META_DATA);
3956 if (ai == null) {
3957 return null;
3958 }
3959
3960 if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
3961 intent = new Intent(intent);
3962 intent.setClassName(ai.packageName, ai.name);
3963 return intent;
3964 }
3965
3966 return null;
3967 }
3968
3969 void startDockOrHome() {
3970 Intent dock = createHomeDockIntent();
3971 if (dock != null) {
3972 try {
3973 mContext.startActivity(dock);
3974 return;
3975 } catch (ActivityNotFoundException e) {
3976 }
3977 }
3978 mContext.startActivity(mHomeIntent);
3979 }
3980
3981 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003982 * goes to the home screen
3983 * @return whether it did anything
3984 */
3985 boolean goHome() {
3986 if (false) {
3987 // This code always brings home to the front.
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07003988 try {
3989 ActivityManagerNative.getDefault().stopAppSwitches();
3990 } catch (RemoteException e) {
3991 }
Dianne Hackborn94a679d2009-07-28 17:51:07 -07003992 sendCloseSystemWindows();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07003993 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003994 } else {
3995 // This code brings home to the front or, if it is already
3996 // at the front, puts the device to sleep.
3997 try {
Wink Savilled2e6a332010-02-12 12:12:06 -08003998 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
3999 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
4000 Log.d(TAG, "UTS-TEST-MODE");
4001 } else {
4002 ActivityManagerNative.getDefault().stopAppSwitches();
4003 sendCloseSystemWindows();
4004 Intent dock = createHomeDockIntent();
4005 if (dock != null) {
4006 int result = ActivityManagerNative.getDefault()
4007 .startActivity(null, dock,
4008 dock.resolveTypeIfNeeded(mContext.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07004009 null, null, 0,
4010 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
4011 null, null, null);
4012 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
Wink Savilled2e6a332010-02-12 12:12:06 -08004013 return false;
4014 }
Dianne Hackborn39c2d712009-09-22 11:41:31 -07004015 }
4016 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004017 int result = ActivityManagerNative.getDefault()
4018 .startActivity(null, mHomeIntent,
4019 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07004020 null, null, 0,
4021 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
4022 null, null, null);
4023 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004024 return false;
4025 }
4026 } catch (RemoteException ex) {
4027 // bummer, the activity manager, which is in this process, is dead
4028 }
4029 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004030 return true;
4031 }
4032
The Android Open Source Project0727d222009-03-11 12:11:58 -07004033 public void setCurrentOrientationLw(int newOrientation) {
4034 synchronized (mLock) {
4035 if (newOrientation != mCurrentAppOrientation) {
4036 mCurrentAppOrientation = newOrientation;
4037 updateOrientationListenerLp();
4038 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004039 }
4040 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004041
The Android Open Source Project0727d222009-03-11 12:11:58 -07004042 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
Jim Miller89b17222009-10-27 14:54:09 -07004043 final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
4044 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08004045 if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004046 return false;
4047 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004048 long[] pattern = null;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004049 switch (effectId) {
4050 case HapticFeedbackConstants.LONG_PRESS:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004051 pattern = mLongPressVibePattern;
4052 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004053 case HapticFeedbackConstants.VIRTUAL_KEY:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004054 pattern = mVirtualKeyVibePattern;
4055 break;
4056 case HapticFeedbackConstants.KEYBOARD_TAP:
4057 pattern = mKeyboardTapVibePattern;
4058 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004059 case HapticFeedbackConstants.SAFE_MODE_DISABLED:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004060 pattern = mSafeModeDisabledVibePattern;
4061 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004062 case HapticFeedbackConstants.SAFE_MODE_ENABLED:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004063 pattern = mSafeModeEnabledVibePattern;
4064 break;
Amith Yamasanic33cb712010-02-10 15:21:49 -08004065 default:
4066 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004067 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004068 if (pattern.length == 1) {
4069 // One-shot vibration
4070 mVibrator.vibrate(pattern[0]);
4071 } else {
4072 // Pattern vibration
4073 mVibrator.vibrate(pattern, -1);
4074 }
4075 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004076 }
4077
Daniel Sandler0601eb72011-04-13 01:01:32 -04004078 public void screenOnStartedLw() {
4079 // The window manager has just grabbed a wake lock. This is our cue to disable the screen
4080 // saver.
4081 synchronized (mLock) {
Daniel Sandler2d545362011-11-17 10:38:37 -08004082 mScreenSaverMayRun = false;
Daniel Sandler0601eb72011-04-13 01:01:32 -04004083 }
4084 }
4085
The Android Open Source Project0727d222009-03-11 12:11:58 -07004086 public void screenOnStoppedLw() {
Daniel Sandler0601eb72011-04-13 01:01:32 -04004087 if (mPowerManager.isScreenOn()) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07004088 if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
Daniel Sandler0601eb72011-04-13 01:01:32 -04004089 long curTime = SystemClock.uptimeMillis();
4090 mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
4091 }
4092
4093 synchronized (mLock) {
4094 // even if the keyguard is up, now that all the wakelocks have been released, we
4095 // should re-enable the screen saver
Daniel Sandler2d545362011-11-17 10:38:37 -08004096 mScreenSaverMayRun = true;
Daniel Sandler0601eb72011-04-13 01:01:32 -04004097 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004098 }
4099 }
Mike Lockwoodfcb39242009-10-21 23:01:07 -04004100
4101 public boolean allowKeyRepeat() {
4102 // disable key repeat when screen is off
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07004103 return mScreenOnEarly;
Mike Lockwoodfcb39242009-10-21 23:01:07 -04004104 }
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004105
Dianne Hackborndf89e652011-10-06 22:35:11 -07004106 private int updateSystemUiVisibilityLw() {
Joe Onorato664644d2011-01-23 17:53:23 -08004107 // If there is no window focused, there will be nobody to handle the events
4108 // anyway, so just hang on in whatever state we're in until things settle down.
Dianne Hackborndf89e652011-10-06 22:35:11 -07004109 if (mFocusedWindow == null) {
4110 return 0;
4111 }
4112 final int visibility = mFocusedWindow.getSystemUiVisibility()
Dianne Hackborne26ab702011-10-16 13:21:33 -07004113 & ~mResettingSystemUiFlags
4114 & ~mForceClearedSystemUiFlags;
4115 int diff = visibility ^ mLastSystemUiFlags;
Dianne Hackborn73ab6a42011-12-13 11:16:23 -08004116 final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
Dianne Hackborne0f085d2011-11-30 18:41:15 -08004117 if (diff == 0 && mLastFocusNeedsMenu == needsMenu
4118 && mFocusedApp == mFocusedWindow.getAppToken()) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07004119 return 0;
4120 }
Dianne Hackborne26ab702011-10-16 13:21:33 -07004121 mLastSystemUiFlags = visibility;
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004122 mLastFocusNeedsMenu = needsMenu;
Dianne Hackborne0f085d2011-11-30 18:41:15 -08004123 mFocusedApp = mFocusedWindow.getAppToken();
Dianne Hackborndf89e652011-10-06 22:35:11 -07004124 mHandler.post(new Runnable() {
4125 public void run() {
4126 if (mStatusBarService == null) {
4127 mStatusBarService = IStatusBarService.Stub.asInterface(
4128 ServiceManager.getService("statusbar"));
4129 }
4130 if (mStatusBarService != null) {
4131 try {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07004132 mStatusBarService.setSystemUiVisibility(visibility, 0xffffffff);
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004133 mStatusBarService.topAppWindowChanged(needsMenu);
Dianne Hackborndf89e652011-10-06 22:35:11 -07004134 } catch (RemoteException e) {
4135 // not much to be done
4136 mStatusBarService = null;
Joe Onorato664644d2011-01-23 17:53:23 -08004137 }
4138 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07004139 }
4140 });
4141 return diff;
Joe Onorato664644d2011-01-23 17:53:23 -08004142 }
4143
Daniel Sandler0c4ccff2011-10-19 16:39:14 -04004144 // Use this instead of checking config_showNavigationBar so that it can be consistently
4145 // overridden by qemu.hw.mainkeys in the emulator.
4146 public boolean hasNavigationBar() {
4147 return mHasNavigationBar;
4148 }
4149
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004150 public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
4151 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07004152 pw.print(" mSystemReady="); pw.print(mSystemReady);
4153 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
Jeff Brown2e7760e2012-04-11 15:14:55 -07004154 pw.print(prefix); pw.print("mLidState="); pw.print(mLidState);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004155 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
4156 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
Dianne Hackborne26ab702011-10-16 13:21:33 -07004157 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
4158 || mForceClearedSystemUiFlags != 0) {
4159 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
4160 pw.print(Integer.toHexString(mLastSystemUiFlags));
4161 pw.print(" mResettingSystemUiFlags=0x");
4162 pw.print(Integer.toHexString(mResettingSystemUiFlags));
4163 pw.print(" mForceClearedSystemUiFlags=0x");
4164 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
Dianne Hackborndf89e652011-10-06 22:35:11 -07004165 }
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004166 if (mLastFocusNeedsMenu) {
4167 pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
4168 pw.println(mLastFocusNeedsMenu);
4169 }
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004170 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
4171 pw.print(" mDockMode="); pw.print(mDockMode);
4172 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
4173 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
4174 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
4175 pw.print(" mUserRotation="); pw.print(mUserRotation);
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05004176 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004177 pw.print(prefix); pw.print("mAccelerometerDefault="); pw.print(mAccelerometerDefault);
4178 pw.print(" mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
4179 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
4180 pw.print(mCarDockEnablesAccelerometer);
4181 pw.print(" mDeskDockEnablesAccelerometer=");
4182 pw.println(mDeskDockEnablesAccelerometer);
4183 pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
4184 pw.print(mLidKeyboardAccessibility);
4185 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
4186 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07004187 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
4188 pw.print(" mScreenOnFully="); pw.print(mScreenOnFully);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004189 pw.print(" mOrientationSensorEnabled="); pw.print(mOrientationSensorEnabled);
4190 pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
4191 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
4192 pw.print(","); pw.print(mUnrestrictedScreenTop);
4193 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
4194 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
4195 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
4196 pw.print(","); pw.print(mRestrictedScreenTop);
4197 pw.print(") "); pw.print(mRestrictedScreenWidth);
4198 pw.print("x"); pw.println(mRestrictedScreenHeight);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07004199 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
4200 pw.print(","); pw.print(mStableTop);
4201 pw.print(")-("); pw.print(mStableRight);
4202 pw.print(","); pw.print(mStableBottom); pw.println(")");
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004203 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
4204 pw.print(","); pw.print(mCurTop);
4205 pw.print(")-("); pw.print(mCurRight);
4206 pw.print(","); pw.print(mCurBottom); pw.println(")");
4207 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
4208 pw.print(","); pw.print(mContentTop);
4209 pw.print(")-("); pw.print(mContentRight);
4210 pw.print(","); pw.print(mContentBottom); pw.println(")");
4211 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
4212 pw.print(","); pw.print(mDockTop);
4213 pw.print(")-("); pw.print(mDockRight);
4214 pw.print(","); pw.print(mDockBottom); pw.println(")");
4215 pw.print(prefix); pw.print("mDockLayer="); pw.println(mDockLayer);
4216 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
4217 pw.println(mTopFullscreenOpaqueWindowState);
4218 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
4219 pw.print(" mForceStatusBar="); pw.print(mForceStatusBar);
4220 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
4221 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
4222 pw.print(" mHomePressed="); pw.println(mHomePressed);
4223 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
4224 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
4225 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
4226 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
4227 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
4228 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
4229 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
4230 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
4231 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
4232 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
4233 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004234}