blob: f1e571f3040e23f0fb476863a085a5db4a787c8d [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 Hackborn08743722009-12-21 12:16:51 -0800309 final ArrayList<WindowState> mStatusBarPanels = 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;
313 boolean mNavigationBarOnBottom = true;
Daniel Sandler36412a72011-08-04 09:35:13 -0400314 int mNavigationBarWidth = 0, mNavigationBarHeight = 0;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400315
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800316 WindowState mKeyguard = null;
317 KeyguardViewMediator mKeyguardMediator;
318 GlobalActions mGlobalActions;
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700319 volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
320 boolean mPendingPowerKeyUpCanceled;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800321 Handler mHandler;
Jeff Brown4aed78b2011-01-14 17:36:55 -0800322
Jeff Brown68b909d2011-12-07 16:36:01 -0800323 static final int RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS = 0;
324 static final int RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW = 1;
325 static final int RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH = 2;
326
327 RecentApplicationsDialog mRecentAppsDialog;
328 int mRecentAppsDialogHeldModifiers;
329
Jeff Brown4aed78b2011-01-14 17:36:55 -0800330 int mLidOpen = LID_ABSENT;
331
Dianne Hackbornc777e072010-02-12 13:07:59 -0800332 boolean mSystemReady;
Dianne Hackbornba24e4d2011-09-01 11:17:06 -0700333 boolean mSystemBooted;
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800334 boolean mHdmiPlugged;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700335 int mExternalDisplayWidth;
336 int mExternalDisplayHeight;
Joe Onorato44fcb832011-12-14 20:59:30 -0800337 int mUiMode;
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700338 int mDockMode = Intent.EXTRA_DOCK_STATE_UNDOCKED;
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700339 int mLidOpenRotation;
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400340 int mCarDockRotation;
341 int mDeskDockRotation;
Erik Gilling9a41ef82011-09-26 19:21:03 -0700342 int mHdmiRotation;
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400343
344 int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
345 int mUserRotation = Surface.ROTATION_0;
346
Jeff Brownd3187e32011-09-21 19:26:44 -0700347 int mAllowAllRotations = -1;
Mike Lockwoode9867d22009-09-20 01:59:02 -0400348 boolean mCarDockEnablesAccelerometer;
349 boolean mDeskDockEnablesAccelerometer;
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700350 int mLidKeyboardAccessibility;
351 int mLidNavigationAccessibility;
Joe Onoratod208e702010-10-08 16:22:43 -0400352 int mLongPressOnPowerBehavior = -1;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700353 boolean mScreenOnEarly = false;
354 boolean mScreenOnFully = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800355 boolean mOrientationSensorEnabled = false;
356 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
357 static final int DEFAULT_ACCELEROMETER_ROTATION = 0;
358 int mAccelerometerDefault = DEFAULT_ACCELEROMETER_ROTATION;
359 boolean mHasSoftInput = false;
360
Jeff Brown70825162012-03-28 17:27:48 -0700361 int mPointerLocationMode = 0; // guarded by mLock
Joe Onorato664644d2011-01-23 17:53:23 -0800362
363 // The last window we were told about in focusChanged.
364 WindowState mFocusedWindow;
Dianne Hackborne0f085d2011-11-30 18:41:15 -0800365 IApplicationToken mFocusedApp;
Joe Onorato664644d2011-01-23 17:53:23 -0800366
Jeff Brown70825162012-03-28 17:27:48 -0700367 private static final class PointerLocationInputEventReceiver extends InputEventReceiver {
368 private final PointerLocationView mView;
369
370 public PointerLocationInputEventReceiver(InputChannel inputChannel, Looper looper,
371 PointerLocationView view) {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800372 super(inputChannel, looper);
Jeff Brown70825162012-03-28 17:27:48 -0700373 mView = view;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800374 }
375
Jeff Browna41ca772010-08-11 14:46:32 -0700376 @Override
Jeff Brown32cbc38552011-12-01 14:01:49 -0800377 public void onInputEvent(InputEvent event) {
Jeff Brown3915bb82010-11-05 15:02:16 -0700378 boolean handled = false;
379 try {
Jeff Brown4952dfd2011-11-30 19:23:22 -0800380 if (event instanceof MotionEvent
381 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
382 final MotionEvent motionEvent = (MotionEvent)event;
Jeff Brown70825162012-03-28 17:27:48 -0700383 mView.addPointerEvent(motionEvent);
384 handled = true;
Jeff Brown93ed4e32010-09-23 13:51:48 -0700385 }
Jeff Brown3915bb82010-11-05 15:02:16 -0700386 } finally {
Jeff Brown32cbc38552011-12-01 14:01:49 -0800387 finishInputEvent(event, handled);
Jeff Browna41ca772010-08-11 14:46:32 -0700388 }
389 }
Jeff Brown32cbc38552011-12-01 14:01:49 -0800390 }
Jeff Brown70825162012-03-28 17:27:48 -0700391
392 // Pointer location view state, only modified on the mHandler Looper.
Jeff Brown32cbc38552011-12-01 14:01:49 -0800393 PointerLocationInputEventReceiver mPointerLocationInputEventReceiver;
Jeff Brown70825162012-03-28 17:27:48 -0700394 PointerLocationView mPointerLocationView;
395 InputChannel mPointerLocationInputChannel;
Jeff Brown32cbc38552011-12-01 14:01:49 -0800396
Joe Onorato29fc2c92010-11-24 10:26:50 -0800397 // The current size of the screen; really; (ir)regardless of whether the status
398 // bar can be hidden or not
399 int mUnrestrictedScreenLeft, mUnrestrictedScreenTop;
400 int mUnrestrictedScreenWidth, mUnrestrictedScreenHeight;
Dianne Hackborn82de1ae2010-10-28 11:28:39 -0700401 // The current size of the screen; these may be different than (0,0)-(dw,dh)
402 // if the status bar can't be hidden; in that case it effectively carves out
403 // that area of the display from all other windows.
Joe Onorato29fc2c92010-11-24 10:26:50 -0800404 int mRestrictedScreenLeft, mRestrictedScreenTop;
405 int mRestrictedScreenWidth, mRestrictedScreenHeight;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700406 // For applications requesting stable content insets, these are them.
407 int mStableLeft, mStableTop, mStableRight, mStableBottom;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800408 // During layout, the current screen borders with all outer decoration
409 // (status bar, input method dock) accounted for.
410 int mCurLeft, mCurTop, mCurRight, mCurBottom;
411 // During layout, the frame in which content should be displayed
412 // to the user, accounting for all screen decoration except for any
413 // space they deem as available for other content. This is usually
414 // the same as mCur*, but may be larger if the screen decor has supplied
415 // content insets.
416 int mContentLeft, mContentTop, mContentRight, mContentBottom;
Dianne Hackborn8e11ef02010-11-18 19:47:42 -0800417 // During layout, the current screen borders along which input method
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800418 // windows are placed.
419 int mDockLeft, mDockTop, mDockRight, mDockBottom;
420 // During layout, the layer at which the doc window is placed.
421 int mDockLayer;
Dianne Hackborne26ab702011-10-16 13:21:33 -0700422 int mLastSystemUiFlags;
423 // Bits that we are in the process of clearing, so we want to prevent
424 // them from being set by applications until everything has been updated
425 // to have them clear.
426 int mResettingSystemUiFlags = 0;
427 // Bits that we are currently always keeping cleared.
428 int mForceClearedSystemUiFlags = 0;
Dianne Hackborn4eff8d32011-11-10 19:38:40 -0800429 // What we last reported to system UI about whether the compatibility
430 // menu needs to be displayed.
431 boolean mLastFocusNeedsMenu = false;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700432
433 FakeWindow mHideNavFakeWindow = null;
434
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800435 static final Rect mTmpParentFrame = new Rect();
436 static final Rect mTmpDisplayFrame = new Rect();
437 static final Rect mTmpContentFrame = new Rect();
438 static final Rect mTmpVisibleFrame = new Rect();
Dianne Hackborn1f903c32011-09-13 19:18:06 -0700439 static final Rect mTmpNavigationFrame = new Rect();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800440
441 WindowState mTopFullscreenOpaqueWindowState;
Joe Onorato93056472010-09-10 10:30:46 -0400442 boolean mTopIsFullscreen;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800443 boolean mForceStatusBar;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700444 boolean mHideLockScreen;
445 boolean mDismissKeyguard;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800446 boolean mHomePressed;
Michael Jurka7f2668c2012-03-27 07:49:52 -0700447 boolean mHomeLongPressed;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800448 Intent mHomeIntent;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700449 Intent mCarDockIntent;
450 Intent mDeskDockIntent;
Jeff Brown49ed71d2010-12-06 17:13:33 -0800451 int mShortcutKeyPressed = -1;
452 boolean mConsumeShortcutKeyUp;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800453
Mike Lockwood28569302010-01-28 11:54:40 -0500454 // support for activating the lock screen while the screen is on
455 boolean mAllowLockscreenWhenOn;
456 int mLockScreenTimeout;
457 boolean mLockScreenTimerActive;
458
Daniel Sandler0601eb72011-04-13 01:01:32 -0400459 // visual screen saver support
Daniel Sandler7d276c32012-01-30 14:33:52 -0500460 boolean mScreenSaverFeatureAvailable;
Daniel Sandlere5f2cfe2011-11-02 23:30:58 -0400461 int mScreenSaverTimeout = 0;
Daniel Sandler2d545362011-11-17 10:38:37 -0800462 boolean mScreenSaverEnabledByUser = false;
463 boolean mScreenSaverMayRun = true; // false if a wakelock is held
Daniel Sandler7e37df52011-11-16 22:08:23 -0800464 boolean mPluggedIn;
Daniel Sandler0601eb72011-04-13 01:01:32 -0400465
David Brownbaf8d092010-03-08 21:52:59 -0800466 // Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800467 int mEndcallBehavior;
David Brownbaf8d092010-03-08 21:52:59 -0800468
469 // Behavior of POWER button while in-call and screen on.
470 // (See Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR.)
471 int mIncallPowerBehavior;
472
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700473 Display mDisplay;
474
Dianne Hackborn9d132642011-04-21 17:26:39 -0700475 int mLandscapeRotation = 0; // default landscape rotation
476 int mSeascapeRotation = 0; // "other" landscape rotation, 180 degrees from mLandscapeRotation
477 int mPortraitRotation = 0; // default portrait rotation
478 int mUpsideDownRotation = 0; // "other" portrait rotation
Mitsuru Oshima831d0d92009-06-16 18:27:18 -0700479
Joe Onorato46b0d682010-11-22 17:37:27 -0800480 // What we do when the user long presses on home
481 private int mLongPressOnHomeBehavior = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800482
Winson Chung9112ec32011-06-27 13:15:32 -0700483 // Screenshot trigger states
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700484 // Time to volume and power must be pressed within this interval of each other.
485 private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
Christopher Tatee90585f2012-03-05 18:56:25 -0800486 private boolean mScreenshotChordEnabled;
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700487 private boolean mVolumeDownKeyTriggered;
488 private long mVolumeDownKeyTime;
489 private boolean mVolumeDownKeyConsumedByScreenshotChord;
490 private boolean mVolumeUpKeyTriggered;
491 private boolean mPowerKeyTriggered;
492 private long mPowerKeyTime;
Winson Chung9112ec32011-06-27 13:15:32 -0700493
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800494 ShortcutManager mShortcutManager;
495 PowerManager.WakeLock mBroadcastWakeLock;
496
Jeff Brown49ed71d2010-12-06 17:13:33 -0800497 final KeyCharacterMap.FallbackAction mFallbackAction = new KeyCharacterMap.FallbackAction();
498
Jeff Brown70825162012-03-28 17:27:48 -0700499 private static final int MSG_ENABLE_POINTER_LOCATION = 1;
500 private static final int MSG_DISABLE_POINTER_LOCATION = 2;
501
502 private class PolicyHandler extends Handler {
503 @Override
504 public void handleMessage(Message msg) {
505 switch (msg.what) {
506 case MSG_ENABLE_POINTER_LOCATION:
507 enablePointerLocation();
508 break;
509 case MSG_DISABLE_POINTER_LOCATION:
510 disablePointerLocation();
511 break;
512 }
513 }
514 }
515
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -0800516 private UEventObserver mHDMIObserver = new UEventObserver() {
517 @Override
518 public void onUEvent(UEventObserver.UEvent event) {
519 setHdmiPlugged("1".equals(event.get("SWITCH_STATE")));
520 }
521 };
522
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800523 class SettingsObserver extends ContentObserver {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800524 SettingsObserver(Handler handler) {
525 super(handler);
526 }
David Brownbaf8d092010-03-08 21:52:59 -0800527
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800528 void observe() {
529 ContentResolver resolver = mContext.getContentResolver();
530 resolver.registerContentObserver(Settings.System.getUriFor(
531 Settings.System.END_BUTTON_BEHAVIOR), false, this);
David Brownbaf8d092010-03-08 21:52:59 -0800532 resolver.registerContentObserver(Settings.Secure.getUriFor(
533 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800534 resolver.registerContentObserver(Settings.System.getUriFor(
535 Settings.System.ACCELEROMETER_ROTATION), false, this);
Mike Lockwood28569302010-01-28 11:54:40 -0500536 resolver.registerContentObserver(Settings.System.getUriFor(
Daniel Sandlerb73617d2010-08-17 00:41:00 -0400537 Settings.System.USER_ROTATION), false, this);
538 resolver.registerContentObserver(Settings.System.getUriFor(
Mike Lockwood28569302010-01-28 11:54:40 -0500539 Settings.System.SCREEN_OFF_TIMEOUT), false, this);
Dianne Hackbornc777e072010-02-12 13:07:59 -0800540 resolver.registerContentObserver(Settings.System.getUriFor(
Jeff Brown4519f072011-01-23 13:16:01 -0800541 Settings.System.WINDOW_ORIENTATION_LISTENER_LOG), false, this);
542 resolver.registerContentObserver(Settings.System.getUriFor(
Dianne Hackbornc777e072010-02-12 13:07:59 -0800543 Settings.System.POINTER_LOCATION), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800544 resolver.registerContentObserver(Settings.Secure.getUriFor(
545 Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700546 resolver.registerContentObserver(Settings.System.getUriFor(
547 "fancy_rotation_anim"), false, this);
Daniel Sandler2d545362011-11-17 10:38:37 -0800548 resolver.registerContentObserver(Settings.Secure.getUriFor(
549 Settings.Secure.SCREENSAVER_ENABLED), false, this);
Daniel Sandler7e37df52011-11-16 22:08:23 -0800550 if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
551 resolver.registerContentObserver(Settings.Secure.getUriFor(
Daniel Sandler2d545362011-11-17 10:38:37 -0800552 "screensaver_timeout"), false, this);
Daniel Sandler7e37df52011-11-16 22:08:23 -0800553 } // otherwise SCREEN_OFF_TIMEOUT will do nicely
Dianne Hackbornc777e072010-02-12 13:07:59 -0800554 updateSettings();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800555 }
556
557 @Override public void onChange(boolean selfChange) {
Dianne Hackbornc777e072010-02-12 13:07:59 -0800558 updateSettings();
Jeff Brown01a98dd2011-09-20 15:08:29 -0700559 updateRotation(false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800560 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800561 }
562
563 class MyOrientationListener extends WindowOrientationListener {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800564 MyOrientationListener(Context context) {
565 super(context);
566 }
567
568 @Override
Jeff Brownc0347aa2011-09-23 17:26:09 -0700569 public void onProposedRotationChanged(int rotation) {
570 if (localLOGV) Log.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
Jeff Brown01a98dd2011-09-20 15:08:29 -0700571 updateRotation(false);
572 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800573 }
574 MyOrientationListener mOrientationListener;
575
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700576 /*
577 * We always let the sensor be switched on by default except when
578 * the user has explicitly disabled sensor based rotation or when the
579 * screen is switched off.
580 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700581 boolean needSensorRunningLp() {
Dianne Hackborne5439f22010-10-02 16:53:50 -0700582 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
583 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
584 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
585 || mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800586 // If the application has explicitly requested to follow the
587 // orientation, then we need to turn the sensor or.
588 return true;
589 }
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700590 if ((mCarDockEnablesAccelerometer && mDockMode == Intent.EXTRA_DOCK_STATE_CAR) ||
Jeff Brown1a693182011-11-08 14:44:16 -0800591 (mDeskDockEnablesAccelerometer && (mDockMode == Intent.EXTRA_DOCK_STATE_DESK
592 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
593 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK))) {
Mike Lockwoode9867d22009-09-20 01:59:02 -0400594 // enable accelerometer if we are docked in a dock that enables accelerometer
595 // orientation management,
596 return true;
597 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700598 if (mAccelerometerDefault == 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800599 // If the setting for using the sensor by default is enabled, then
600 // we will always leave it on. Note that the user could go to
601 // a window that forces an orientation that does not use the
602 // sensor and in theory we could turn it off... however, when next
603 // turning it on we won't have a good value for the current
604 // orientation for a little bit, which can cause orientation
605 // changes to lag, so we'd like to keep it always on. (It will
606 // still be turned off when the screen is off.)
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700607 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800608 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700609 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800610 }
611
612 /*
613 * Various use cases for invoking this function
614 * screen turning off, should always disable listeners if already enabled
615 * screen turned on and current app has sensor based orientation, enable listeners
616 * if not already enabled
617 * screen turned on and current app does not have sensor orientation, disable listeners if
618 * already enabled
619 * screen turning on and current app has sensor based orientation, enable listeners if needed
620 * screen turning on and current app has nosensor based orientation, do nothing
621 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700622 void updateOrientationListenerLp() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800623 if (!mOrientationListener.canDetectOrientation()) {
624 // If sensor is turned off or nonexistent for some reason
625 return;
626 }
627 //Could have been invoked due to screen turning on or off or
628 //change of the currently visible window's orientation
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700629 if (localLOGV) Log.v(TAG, "Screen status="+mScreenOnEarly+
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800630 ", current orientation="+mCurrentAppOrientation+
631 ", SensorEnabled="+mOrientationSensorEnabled);
632 boolean disable = true;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -0700633 if (mScreenOnEarly) {
The Android Open Source Project0727d222009-03-11 12:11:58 -0700634 if (needSensorRunningLp()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800635 disable = false;
636 //enable listener if not already enabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700637 if (!mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800638 mOrientationListener.enable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700639 if(localLOGV) Log.v(TAG, "Enabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800640 mOrientationSensorEnabled = true;
641 }
642 }
643 }
644 //check if sensors need to be disabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700645 if (disable && mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800646 mOrientationListener.disable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700647 if(localLOGV) Log.v(TAG, "Disabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800648 mOrientationSensorEnabled = false;
649 }
650 }
651
Jeff Brown4d396052010-10-29 21:50:21 -0700652 private void interceptPowerKeyDown(boolean handled) {
653 mPowerKeyHandled = handled;
654 if (!handled) {
655 mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
656 }
657 }
658
659 private boolean interceptPowerKeyUp(boolean canceled) {
660 if (!mPowerKeyHandled) {
661 mHandler.removeCallbacks(mPowerLongPress);
662 return !canceled;
Jeff Brown4d396052010-10-29 21:50:21 -0700663 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700664 return false;
665 }
666
667 private void cancelPendingPowerKeyAction() {
668 if (!mPowerKeyHandled) {
669 mHandler.removeCallbacks(mPowerLongPress);
670 }
Jeff Brownff204712011-10-25 21:27:54 -0700671 if (mPowerKeyTriggered) {
672 mPendingPowerKeyUpCanceled = true;
673 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700674 }
675
676 private void interceptScreenshotChord() {
Christopher Tatee90585f2012-03-05 18:56:25 -0800677 if (mScreenshotChordEnabled
678 && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700679 final long now = SystemClock.uptimeMillis();
680 if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
681 && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
682 mVolumeDownKeyConsumedByScreenshotChord = true;
683 cancelPendingPowerKeyAction();
684
685 mHandler.postDelayed(mScreenshotChordLongPress,
686 ViewConfiguration.getGlobalActionKeyTimeout());
687 }
688 }
689 }
690
691 private void cancelPendingScreenshotChordAction() {
692 mHandler.removeCallbacks(mScreenshotChordLongPress);
Jeff Brown4d396052010-10-29 21:50:21 -0700693 }
694
695 private final Runnable mPowerLongPress = new Runnable() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800696 public void run() {
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700697 // The context isn't read
698 if (mLongPressOnPowerBehavior < 0) {
699 mLongPressOnPowerBehavior = mContext.getResources().getInteger(
700 com.android.internal.R.integer.config_longPressOnPowerBehavior);
Joe Onoratod208e702010-10-08 16:22:43 -0400701 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -0700702 switch (mLongPressOnPowerBehavior) {
703 case LONG_PRESS_POWER_NOTHING:
704 break;
705 case LONG_PRESS_POWER_GLOBAL_ACTIONS:
706 mPowerKeyHandled = true;
707 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
708 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
709 showGlobalActionsDialog();
710 break;
711 case LONG_PRESS_POWER_SHUT_OFF:
712 mPowerKeyHandled = true;
713 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
714 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
715 ShutdownThread.shutdown(mContext, true);
716 break;
717 }
718 }
719 };
720
721 private final Runnable mScreenshotChordLongPress = new Runnable() {
722 public void run() {
723 takeScreenshot();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800724 }
725 };
726
727 void showGlobalActionsDialog() {
728 if (mGlobalActions == null) {
729 mGlobalActions = new GlobalActions(mContext);
730 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -0700731 final boolean keyguardShowing = keyguardIsShowingTq();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800732 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
733 if (keyguardShowing) {
734 // since it took two seconds of long press to bring this up,
735 // poke the wake lock so they have some time to see the dialog.
736 mKeyguardMediator.pokeWakelock();
737 }
738 }
739
740 boolean isDeviceProvisioned() {
741 return Settings.Secure.getInt(
742 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
743 }
744
Patrick Dubroyece94522011-02-23 18:35:01 -0800745 private void handleLongPressOnHome() {
Jim Milleree969aa2010-08-26 20:17:43 -0700746 // We can't initialize this in init() since the configuration hasn't been loaded yet.
Joe Onorato46b0d682010-11-22 17:37:27 -0800747 if (mLongPressOnHomeBehavior < 0) {
748 mLongPressOnHomeBehavior
Joe Onorato50262e52010-11-26 14:04:54 -0800749 = mContext.getResources().getInteger(R.integer.config_longPressOnHomeBehavior);
Joe Onorato46b0d682010-11-22 17:37:27 -0800750 if (mLongPressOnHomeBehavior < LONG_PRESS_HOME_NOTHING ||
Michael Jurka3b1fc472011-06-13 10:54:40 -0700751 mLongPressOnHomeBehavior > LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
Joe Onorato46b0d682010-11-22 17:37:27 -0800752 mLongPressOnHomeBehavior = LONG_PRESS_HOME_NOTHING;
753 }
Michael Jurka7a348952012-02-27 13:07:58 -0800754 if (hasNavigationBar()) {
755 mLongPressOnHomeBehavior = LONG_PRESS_HOME_VOICE_SEARCH;
756 }
Joe Onorato46b0d682010-11-22 17:37:27 -0800757 }
758
759 if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
760 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
761 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
Patrick Dubroyece94522011-02-23 18:35:01 -0800762
763 // Eat the longpress so it won't dismiss the recent apps dialog when
764 // the user lets go of the home key
Michael Jurka7f2668c2012-03-27 07:49:52 -0700765 mHomeLongPressed = true;
Jim Milleree969aa2010-08-26 20:17:43 -0700766 }
Patrick Dubroyece94522011-02-23 18:35:01 -0800767
Joe Onorato46b0d682010-11-22 17:37:27 -0800768 if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_DIALOG) {
Jeff Brown68b909d2011-12-07 16:36:01 -0800769 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
Michael Jurka3b1fc472011-06-13 10:54:40 -0700770 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_RECENT_SYSTEM_UI) {
Jim Millere6ad1a82010-08-20 19:25:39 -0700771 try {
Michael Jurka3b1fc472011-06-13 10:54:40 -0700772 mStatusBarService.toggleRecentApps();
773 } catch (RemoteException e) {
774 Slog.e(TAG, "RemoteException when showing recent apps", e);
Jim Millere6ad1a82010-08-20 19:25:39 -0700775 }
Michael Jurka7a348952012-02-27 13:07:58 -0800776 } else if (mLongPressOnHomeBehavior == LONG_PRESS_HOME_VOICE_SEARCH) {
777 Intent intent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
778 try {
779 intent.setFlags(
780 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
781 mContext.startActivity(intent);
782 } catch (ActivityNotFoundException e) {
783 Log.e(TAG, "Unable to launch. tag=" + TAG + " intent=" + intent, e);
784 } catch (SecurityException e) {
785 Log.e(TAG, "PhoneWindowManager does not have the permission to launch " +
786 "tag=" + TAG + " intent=" + intent, e);
787 }
Jim Millere6ad1a82010-08-20 19:25:39 -0700788 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800789 }
Patrick Dubroyece94522011-02-23 18:35:01 -0800790
791 /**
Jeff Brown68b909d2011-12-07 16:36:01 -0800792 * Create (if necessary) and show or dismiss the recent apps dialog according
793 * according to the requested behavior.
Patrick Dubroyece94522011-02-23 18:35:01 -0800794 */
Jeff Brown68b909d2011-12-07 16:36:01 -0800795 void showOrHideRecentAppsDialog(final int behavior) {
Jeff Brownda3d5a92011-03-29 15:11:34 -0700796 mHandler.post(new Runnable() {
797 @Override
798 public void run() {
799 if (mRecentAppsDialog == null) {
Jeff Brown54875002011-04-06 15:33:01 -0700800 mRecentAppsDialog = new RecentApplicationsDialog(mContext);
Jeff Brownda3d5a92011-03-29 15:11:34 -0700801 }
Jeff Brown54875002011-04-06 15:33:01 -0700802 if (mRecentAppsDialog.isShowing()) {
Jeff Brown68b909d2011-12-07 16:36:01 -0800803 switch (behavior) {
804 case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
805 mRecentAppsDialog.dismiss();
806 break;
807 case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
808 mRecentAppsDialog.dismissAndSwitch();
809 break;
810 case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
811 default:
812 break;
Jeff Brown54875002011-04-06 15:33:01 -0700813 }
814 } else {
Jeff Brown68b909d2011-12-07 16:36:01 -0800815 switch (behavior) {
816 case RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS:
817 mRecentAppsDialog.show();
818 break;
819 case RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW:
820 try {
821 mWindowManager.setInTouchMode(false);
822 } catch (RemoteException e) {
823 }
824 mRecentAppsDialog.show();
825 break;
826 case RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH:
827 default:
828 break;
829 }
Jeff Brown54875002011-04-06 15:33:01 -0700830 }
Jeff Brownda3d5a92011-03-29 15:11:34 -0700831 }
832 });
Patrick Dubroyece94522011-02-23 18:35:01 -0800833 }
Jeff Brownda3d5a92011-03-29 15:11:34 -0700834
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800835 /** {@inheritDoc} */
836 public void init(Context context, IWindowManager windowManager,
Dianne Hackborndf89e652011-10-06 22:35:11 -0700837 WindowManagerFuncs windowManagerFuncs,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800838 LocalPowerManager powerManager) {
839 mContext = context;
840 mWindowManager = windowManager;
Dianne Hackborndf89e652011-10-06 22:35:11 -0700841 mWindowManagerFuncs = windowManagerFuncs;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800842 mPowerManager = powerManager;
Mike Lockwoodd747dc82011-09-13 16:28:22 -0400843 mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
844 if (!mHeadless) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -0700845 // don't create KeyguardViewMediator if headless
846 mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
847 }
Jeff Brown70825162012-03-28 17:27:48 -0700848 mHandler = new PolicyHandler();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800849 mOrientationListener = new MyOrientationListener(mContext);
Jeff Brownc0347aa2011-09-23 17:26:09 -0700850 try {
851 mOrientationListener.setCurrentRotation(windowManager.getRotation());
852 } catch (RemoteException ex) { }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800853 SettingsObserver settingsObserver = new SettingsObserver(mHandler);
854 settingsObserver.observe();
855 mShortcutManager = new ShortcutManager(context, mHandler);
856 mShortcutManager.observe();
Joe Onorato44fcb832011-12-14 20:59:30 -0800857 mUiMode = context.getResources().getInteger(
858 com.android.internal.R.integer.config_defaultUiModeType);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800859 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
860 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
861 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
862 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700863 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
864 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
865 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
866 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
867 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
868 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
869 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
870 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Jim Millere6ad1a82010-08-20 19:25:39 -0700871
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800872 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
873 mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
874 "PhoneWindowManager.mBroadcastWakeLock");
875 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700876 mLidOpenRotation = readRotation(
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400877 com.android.internal.R.integer.config_lidOpenRotation);
878 mCarDockRotation = readRotation(
879 com.android.internal.R.integer.config_carDockRotation);
880 mDeskDockRotation = readRotation(
881 com.android.internal.R.integer.config_deskDockRotation);
Mike Lockwoode9867d22009-09-20 01:59:02 -0400882 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
883 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
884 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
885 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700886 mLidKeyboardAccessibility = mContext.getResources().getInteger(
887 com.android.internal.R.integer.config_lidKeyboardAccessibility);
888 mLidNavigationAccessibility = mContext.getResources().getInteger(
889 com.android.internal.R.integer.config_lidNavigationAccessibility);
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700890 // register for dock events
Dianne Hackborn78968392010-03-04 20:47:56 -0800891 IntentFilter filter = new IntentFilter();
892 filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
893 filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE);
894 filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
895 filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
Dianne Hackborn867ab6472010-04-29 13:28:56 -0700896 filter.addAction(Intent.ACTION_DOCK_EVENT);
897 Intent intent = context.registerReceiver(mDockReceiver, filter);
898 if (intent != null) {
899 // Retrieve current sticky dock event broadcast.
900 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
901 Intent.EXTRA_DOCK_STATE_UNDOCKED);
902 }
Daniel Sandler7e37df52011-11-16 22:08:23 -0800903
904 // watch the plug to know whether to trigger the screen saver
905 filter = new IntentFilter();
906 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
907 intent = context.registerReceiver(mPowerReceiver, filter);
908 if (intent != null) {
909 mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
910 }
911
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700912 mVibrator = new Vibrator();
913 mLongPressVibePattern = getLongIntArray(mContext.getResources(),
914 com.android.internal.R.array.config_longPressVibePattern);
915 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
916 com.android.internal.R.array.config_virtualKeyVibePattern);
Amith Yamasanic33cb712010-02-10 15:21:49 -0800917 mKeyboardTapVibePattern = getLongIntArray(mContext.getResources(),
918 com.android.internal.R.array.config_keyboardTapVibePattern);
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700919 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
920 com.android.internal.R.array.config_safeModeDisabledVibePattern);
921 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
922 com.android.internal.R.array.config_safeModeEnabledVibePattern);
Daniel Sandler40427442010-07-16 11:44:52 -0400923
Christopher Tatee90585f2012-03-05 18:56:25 -0800924 mScreenshotChordEnabled = mContext.getResources().getBoolean(
925 com.android.internal.R.bool.config_enableScreenshotChord);
926
Joe Onoratoea495d42011-04-06 11:41:11 -0700927 // Controls rotation and the like.
928 initializeHdmiState();
Dianne Hackborn40011092011-09-22 13:37:48 -0700929
930 // Match current screen state.
931 if (mPowerManager.isScreenOn()) {
932 screenTurningOn(null);
933 } else {
934 screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
935 }
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700936 }
937
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700938 public void setInitialDisplaySize(Display display, int width, int height) {
939 mDisplay = display;
940
941 int shortSize, longSize;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700942 if (width > height) {
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700943 shortSize = height;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700944 longSize = width;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700945 mLandscapeRotation = Surface.ROTATION_0;
946 mSeascapeRotation = Surface.ROTATION_180;
947 if (mContext.getResources().getBoolean(
948 com.android.internal.R.bool.config_reverseDefaultRotation)) {
949 mPortraitRotation = Surface.ROTATION_90;
950 mUpsideDownRotation = Surface.ROTATION_270;
951 } else {
952 mPortraitRotation = Surface.ROTATION_270;
953 mUpsideDownRotation = Surface.ROTATION_90;
954 }
955 } else {
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700956 shortSize = width;
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700957 longSize = height;
Dianne Hackborn9d132642011-04-21 17:26:39 -0700958 mPortraitRotation = Surface.ROTATION_0;
959 mUpsideDownRotation = Surface.ROTATION_180;
960 if (mContext.getResources().getBoolean(
961 com.android.internal.R.bool.config_reverseDefaultRotation)) {
962 mLandscapeRotation = Surface.ROTATION_270;
963 mSeascapeRotation = Surface.ROTATION_90;
964 } else {
965 mLandscapeRotation = Surface.ROTATION_90;
966 mSeascapeRotation = Surface.ROTATION_270;
967 }
968 }
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700969
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700970 mExternalDisplayWidth = mDisplay.getRawExternalWidth();
971 mExternalDisplayHeight = mDisplay.getRawExternalHeight();
972
973 mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
974 com.android.internal.R.dimen.status_bar_height);
975 mNavigationBarHeight = mContext.getResources().getDimensionPixelSize(
976 com.android.internal.R.dimen.navigation_bar_height);
977 mNavigationBarWidth = mContext.getResources().getDimensionPixelSize(
978 com.android.internal.R.dimen.navigation_bar_width);
979
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700980 // Determine whether the status bar can hide based on the size
Daniel Sandlerc8cb3292012-04-05 23:56:05 -0400981 // of the screen. We assume sizes >= 600dp are tablets where we
Dianne Hackborn81e56d52011-05-26 00:55:58 -0700982 // will use the system bar.
Daniel Sandlerc8cb3292012-04-05 23:56:05 -0400983 // XXX: This will change to 720dp soon.
Daniel Sandler631cb3d52011-06-03 01:25:43 -0400984 int shortSizeDp = shortSize
985 * DisplayMetrics.DENSITY_DEFAULT
986 / DisplayMetrics.DENSITY_DEVICE;
Daniel Sandlerc8cb3292012-04-05 23:56:05 -0400987 mHasSystemNavBar = shortSizeDp >= 600;
Daniel Sandler36412a72011-08-04 09:35:13 -0400988
Dianne Hackbornf87d1962012-04-04 12:48:24 -0700989 if (!mHasSystemNavBar) {
990 mHasNavigationBar = mContext.getResources().getBoolean(
991 com.android.internal.R.bool.config_showNavigationBar);
992 // Allow a system property to override this. Used by the emulator.
993 // See also hasNavigationBar().
994 String navBarOverride = SystemProperties.get("qemu.hw.mainkeys");
995 if (! "".equals(navBarOverride)) {
996 if (navBarOverride.equals("1")) mHasNavigationBar = false;
997 else if (navBarOverride.equals("0")) mHasNavigationBar = true;
998 }
999 } else {
1000 mHasNavigationBar = false;
Daniel Sandler0c4ccff2011-10-19 16:39:14 -04001001 }
1002
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001003 if (mHasSystemNavBar) {
1004 // The system bar is always at the bottom. If you are watching
1005 // a video in landscape, we don't need to hide it if we can still
1006 // show a 16:9 aspect ratio with it.
1007 int longSizeDp = longSize
1008 * DisplayMetrics.DENSITY_DEFAULT
1009 / DisplayMetrics.DENSITY_DEVICE;
1010 int barHeightDp = mNavigationBarHeight
1011 * DisplayMetrics.DENSITY_DEFAULT
1012 / DisplayMetrics.DENSITY_DEVICE;
1013 int aspect = ((shortSizeDp-barHeightDp) * 16) / longSizeDp;
1014 // We have computed the aspect ratio with the bar height taken
1015 // out to be 16:aspect. If this is less than 9, then hiding
1016 // the navigation bar will provide more useful space for wide
1017 // screen movies.
1018 mCanHideNavigationBar = aspect < 9;
1019 } else if (mHasNavigationBar) {
1020 // The navigation bar is at the right in landscape; it seems always
1021 // useful to hide it for showing a video.
1022 mCanHideNavigationBar = true;
1023 } else {
1024 mCanHideNavigationBar = false;
1025 }
Erik Gilling9a41ef82011-09-26 19:21:03 -07001026
1027 if ("portrait".equals(SystemProperties.get("persist.demo.hdmirotation"))) {
1028 mHdmiRotation = mPortraitRotation;
1029 } else {
1030 mHdmiRotation = mLandscapeRotation;
1031 }
Dianne Hackborn9d132642011-04-21 17:26:39 -07001032 }
1033
Dianne Hackbornc777e072010-02-12 13:07:59 -08001034 public void updateSettings() {
1035 ContentResolver resolver = mContext.getContentResolver();
1036 boolean updateRotation = false;
Dianne Hackbornc777e072010-02-12 13:07:59 -08001037 synchronized (mLock) {
1038 mEndcallBehavior = Settings.System.getInt(resolver,
David Brownbaf8d092010-03-08 21:52:59 -08001039 Settings.System.END_BUTTON_BEHAVIOR,
1040 Settings.System.END_BUTTON_BEHAVIOR_DEFAULT);
1041 mIncallPowerBehavior = Settings.Secure.getInt(resolver,
1042 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
1043 Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001044 int accelerometerDefault = Settings.System.getInt(resolver,
1045 Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001046
1047 // set up rotation lock state
Daniel Sandler1b815d62010-11-05 10:24:27 -04001048 mUserRotationMode = (accelerometerDefault == 0)
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001049 ? WindowManagerPolicy.USER_ROTATION_LOCKED
1050 : WindowManagerPolicy.USER_ROTATION_FREE;
1051 mUserRotation = Settings.System.getInt(resolver,
1052 Settings.System.USER_ROTATION,
1053 Surface.ROTATION_0);
1054
Dianne Hackbornc777e072010-02-12 13:07:59 -08001055 if (mAccelerometerDefault != accelerometerDefault) {
1056 mAccelerometerDefault = accelerometerDefault;
1057 updateOrientationListenerLp();
1058 }
Daniel Sandlerb73617d2010-08-17 00:41:00 -04001059
Jeff Brown4519f072011-01-23 13:16:01 -08001060 mOrientationListener.setLogEnabled(
1061 Settings.System.getInt(resolver,
1062 Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, 0) != 0);
1063
Dianne Hackbornc777e072010-02-12 13:07:59 -08001064 if (mSystemReady) {
1065 int pointerLocation = Settings.System.getInt(resolver,
1066 Settings.System.POINTER_LOCATION, 0);
1067 if (mPointerLocationMode != pointerLocation) {
1068 mPointerLocationMode = pointerLocation;
Jeff Brown70825162012-03-28 17:27:48 -07001069 mHandler.sendEmptyMessage(pointerLocation != 0 ?
1070 MSG_ENABLE_POINTER_LOCATION : MSG_DISABLE_POINTER_LOCATION);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001071 }
1072 }
1073 // use screen off timeout setting as the timeout for the lockscreen
1074 mLockScreenTimeout = Settings.System.getInt(resolver,
1075 Settings.System.SCREEN_OFF_TIMEOUT, 0);
1076 String imId = Settings.Secure.getString(resolver,
1077 Settings.Secure.DEFAULT_INPUT_METHOD);
1078 boolean hasSoftInput = imId != null && imId.length() > 0;
1079 if (mHasSoftInput != hasSoftInput) {
1080 mHasSoftInput = hasSoftInput;
1081 updateRotation = true;
1082 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04001083
Daniel Sandler7d276c32012-01-30 14:33:52 -05001084 // dreams
1085 mScreenSaverFeatureAvailable = mContext.getResources().getBoolean(
1086 com.android.internal.R.bool.config_enableDreams);
1087
Daniel Sandler2d545362011-11-17 10:38:37 -08001088 mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver,
1089 Settings.Secure.SCREENSAVER_ENABLED, 1);
1090
Daniel Sandler7e37df52011-11-16 22:08:23 -08001091 if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
1092 mScreenSaverTimeout = Settings.Secure.getInt(resolver,
Daniel Sandler2d545362011-11-17 10:38:37 -08001093 "screensaver_timeout", 0);
Daniel Sandler7e37df52011-11-16 22:08:23 -08001094 } else {
1095 mScreenSaverTimeout = Settings.System.getInt(resolver,
1096 Settings.System.SCREEN_OFF_TIMEOUT, 0);
1097 if (mScreenSaverTimeout > 0) {
1098 // We actually want to activate the screensaver just before the
1099 // power manager's screen timeout
1100 mScreenSaverTimeout -= 5000;
1101 }
1102 }
Dianne Hackbornc777e072010-02-12 13:07:59 -08001103 }
1104 if (updateRotation) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07001105 updateRotation(true);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001106 }
Jeff Brown70825162012-03-28 17:27:48 -07001107 }
1108
1109 private void enablePointerLocation() {
1110 if (mPointerLocationView == null) {
1111 mPointerLocationView = new PointerLocationView(mContext);
1112 mPointerLocationView.setPrintCoords(false);
1113
Dianne Hackbornc777e072010-02-12 13:07:59 -08001114 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
1115 WindowManager.LayoutParams.MATCH_PARENT,
1116 WindowManager.LayoutParams.MATCH_PARENT);
Jeff Brown3b2b3542010-10-15 00:54:27 -07001117 lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
Jeff Brownbfcb60a2011-09-08 18:51:14 -07001118 lp.flags = WindowManager.LayoutParams.FLAG_FULLSCREEN
1119 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
1120 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1121 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
Dianne Hackbornc777e072010-02-12 13:07:59 -08001122 lp.format = PixelFormat.TRANSLUCENT;
1123 lp.setTitle("PointerLocation");
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001124 WindowManager wm = (WindowManager)
Dianne Hackbornc777e072010-02-12 13:07:59 -08001125 mContext.getSystemService(Context.WINDOW_SERVICE);
Jeff Browncc4f7db2011-08-30 20:34:48 -07001126 lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
Jeff Brown70825162012-03-28 17:27:48 -07001127 wm.addView(mPointerLocationView, lp);
1128
Jeff Brownac143512012-04-05 18:57:33 -07001129 mPointerLocationInputChannel =
1130 mWindowManagerFuncs.monitorInput("PointerLocationView");
1131 mPointerLocationInputEventReceiver =
1132 new PointerLocationInputEventReceiver(mPointerLocationInputChannel,
1133 Looper.myLooper(), mPointerLocationView);
Dianne Hackbornc777e072010-02-12 13:07:59 -08001134 }
Dianne Hackbornc777e072010-02-12 13:07:59 -08001135 }
Jeff Brown70825162012-03-28 17:27:48 -07001136
1137 private void disablePointerLocation() {
1138 if (mPointerLocationInputEventReceiver != null) {
1139 mPointerLocationInputEventReceiver.dispose();
1140 mPointerLocationInputEventReceiver = null;
1141 }
1142
1143 if (mPointerLocationInputChannel != null) {
1144 mPointerLocationInputChannel.dispose();
1145 mPointerLocationInputChannel = null;
1146 }
1147
1148 if (mPointerLocationView != null) {
1149 WindowManager wm = (WindowManager)
1150 mContext.getSystemService(Context.WINDOW_SERVICE);
1151 wm.removeView(mPointerLocationView);
1152 mPointerLocationView = null;
1153 }
1154 }
1155
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001156 private int readRotation(int resID) {
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001157 try {
1158 int rotation = mContext.getResources().getInteger(resID);
1159 switch (rotation) {
1160 case 0:
1161 return Surface.ROTATION_0;
1162 case 90:
1163 return Surface.ROTATION_90;
1164 case 180:
1165 return Surface.ROTATION_180;
1166 case 270:
1167 return Surface.ROTATION_270;
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001168 }
1169 } catch (Resources.NotFoundException e) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001170 // fall through
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001171 }
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001172 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001173 }
1174
1175 /** {@inheritDoc} */
1176 public int checkAddPermission(WindowManager.LayoutParams attrs) {
1177 int type = attrs.type;
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07001178
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001179 if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
1180 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
1181 return WindowManagerImpl.ADD_OKAY;
1182 }
1183 String permission = null;
1184 switch (type) {
1185 case TYPE_TOAST:
1186 // XXX right now the app process has complete control over
1187 // this... should introduce a token to let the system
1188 // monitor/control what they are doing.
1189 break;
Daniel Sandler7d276c32012-01-30 14:33:52 -05001190 case TYPE_DREAM:
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001191 case TYPE_INPUT_METHOD:
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -07001192 case TYPE_WALLPAPER:
1193 // The window manager will check these.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001194 break;
1195 case TYPE_PHONE:
1196 case TYPE_PRIORITY_PHONE:
1197 case TYPE_SYSTEM_ALERT:
1198 case TYPE_SYSTEM_ERROR:
1199 case TYPE_SYSTEM_OVERLAY:
1200 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
1201 break;
1202 default:
1203 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
1204 }
1205 if (permission != null) {
1206 if (mContext.checkCallingOrSelfPermission(permission)
1207 != PackageManager.PERMISSION_GRANTED) {
1208 return WindowManagerImpl.ADD_PERMISSION_DENIED;
1209 }
1210 }
1211 return WindowManagerImpl.ADD_OKAY;
1212 }
1213
1214 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
1215 switch (attrs.type) {
1216 case TYPE_SYSTEM_OVERLAY:
Jeff Brown3b2b3542010-10-15 00:54:27 -07001217 case TYPE_SECURE_SYSTEM_OVERLAY:
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001218 case TYPE_TOAST:
1219 // These types of windows can't receive input events.
1220 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
1221 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
Jeff Brownbfcb60a2011-09-08 18:51:14 -07001222 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001223 break;
1224 }
1225 }
1226
1227 void readLidState() {
Jeff Brownac143512012-04-05 18:57:33 -07001228 mLidOpen = mWindowManagerFuncs.getLidState();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001229 }
1230
Jeff Brown4aed78b2011-01-14 17:36:55 -08001231 private int determineHiddenState(int mode, int hiddenValue, int visibleValue) {
Jeff Brownd04a88c2011-01-16 14:05:47 -08001232 if (mLidOpen != LID_ABSENT) {
1233 switch (mode) {
1234 case 1:
1235 return mLidOpen == LID_OPEN ? visibleValue : hiddenValue;
1236 case 2:
1237 return mLidOpen == LID_OPEN ? hiddenValue : visibleValue;
1238 }
Dianne Hackborn2862fff2009-09-15 22:56:29 -07001239 }
1240 return visibleValue;
1241 }
Jeff Brownd04a88c2011-01-16 14:05:47 -08001242
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001243 /** {@inheritDoc} */
1244 public void adjustConfigurationLw(Configuration config) {
1245 readLidState();
Jeff Brown01a98dd2011-09-20 15:08:29 -07001246 updateKeyboardVisibility();
Jeff Brownd04a88c2011-01-16 14:05:47 -08001247
1248 if (config.keyboard == Configuration.KEYBOARD_NOKEYS) {
1249 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_YES;
1250 } else {
1251 config.hardKeyboardHidden = determineHiddenState(mLidKeyboardAccessibility,
1252 Configuration.HARDKEYBOARDHIDDEN_YES, Configuration.HARDKEYBOARDHIDDEN_NO);
1253 }
1254
1255 if (config.navigation == Configuration.NAVIGATION_NONAV) {
1256 config.navigationHidden = Configuration.NAVIGATIONHIDDEN_YES;
1257 } else {
1258 config.navigationHidden = determineHiddenState(mLidNavigationAccessibility,
1259 Configuration.NAVIGATIONHIDDEN_YES, Configuration.NAVIGATIONHIDDEN_NO);
1260 }
1261
1262 if (mHasSoftInput || config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO) {
1263 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
1264 } else {
1265 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
1266 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001267 }
Jeff Brownd04a88c2011-01-16 14:05:47 -08001268
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001269 /** {@inheritDoc} */
1270 public int windowTypeToLayerLw(int type) {
1271 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
1272 return APPLICATION_LAYER;
1273 }
1274 switch (type) {
1275 case TYPE_STATUS_BAR:
1276 return STATUS_BAR_LAYER;
1277 case TYPE_STATUS_BAR_PANEL:
1278 return STATUS_BAR_PANEL_LAYER;
Joe Onorato29fc2c92010-11-24 10:26:50 -08001279 case TYPE_STATUS_BAR_SUB_PANEL:
1280 return STATUS_BAR_SUB_PANEL_LAYER;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -08001281 case TYPE_SYSTEM_DIALOG:
1282 return SYSTEM_DIALOG_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001283 case TYPE_SEARCH_BAR:
1284 return SEARCH_BAR_LAYER;
1285 case TYPE_PHONE:
1286 return PHONE_LAYER;
1287 case TYPE_KEYGUARD:
1288 return KEYGUARD_LAYER;
1289 case TYPE_KEYGUARD_DIALOG:
1290 return KEYGUARD_DIALOG_LAYER;
1291 case TYPE_SYSTEM_ALERT:
1292 return SYSTEM_ALERT_LAYER;
1293 case TYPE_SYSTEM_ERROR:
1294 return SYSTEM_ERROR_LAYER;
1295 case TYPE_INPUT_METHOD:
1296 return INPUT_METHOD_LAYER;
1297 case TYPE_INPUT_METHOD_DIALOG:
1298 return INPUT_METHOD_DIALOG_LAYER;
Dianne Hackborne8ecde12011-08-03 18:55:19 -07001299 case TYPE_VOLUME_OVERLAY:
1300 return VOLUME_OVERLAY_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001301 case TYPE_SYSTEM_OVERLAY:
1302 return SYSTEM_OVERLAY_LAYER;
Jeff Brown3b2b3542010-10-15 00:54:27 -07001303 case TYPE_SECURE_SYSTEM_OVERLAY:
1304 return SECURE_SYSTEM_OVERLAY_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001305 case TYPE_PRIORITY_PHONE:
1306 return PRIORITY_PHONE_LAYER;
1307 case TYPE_TOAST:
1308 return TOAST_LAYER;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -07001309 case TYPE_WALLPAPER:
1310 return WALLPAPER_LAYER;
Christopher Tatea53146c2010-09-07 11:57:52 -07001311 case TYPE_DRAG:
1312 return DRAG_LAYER;
Jeff Brown83c09682010-12-23 17:50:18 -08001313 case TYPE_POINTER:
1314 return POINTER_LAYER;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001315 case TYPE_NAVIGATION_BAR:
1316 return NAVIGATION_BAR_LAYER;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07001317 case TYPE_BOOT_PROGRESS:
1318 return BOOT_PROGRESS_LAYER;
Dianne Hackborndf89e652011-10-06 22:35:11 -07001319 case TYPE_HIDDEN_NAV_CONSUMER:
1320 return HIDDEN_NAV_CONSUMER_LAYER;
Daniel Sandler7d276c32012-01-30 14:33:52 -05001321 case TYPE_DREAM:
1322 return SCREENSAVER_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001323 }
1324 Log.e(TAG, "Unknown window type: " + type);
1325 return APPLICATION_LAYER;
1326 }
1327
1328 /** {@inheritDoc} */
1329 public int subWindowTypeToLayerLw(int type) {
1330 switch (type) {
1331 case TYPE_APPLICATION_PANEL:
1332 case TYPE_APPLICATION_ATTACHED_DIALOG:
1333 return APPLICATION_PANEL_SUBLAYER;
1334 case TYPE_APPLICATION_MEDIA:
1335 return APPLICATION_MEDIA_SUBLAYER;
Dianne Hackborn5cb8d792009-05-21 17:34:15 -07001336 case TYPE_APPLICATION_MEDIA_OVERLAY:
1337 return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001338 case TYPE_APPLICATION_SUB_PANEL:
1339 return APPLICATION_SUB_PANEL_SUBLAYER;
1340 }
1341 Log.e(TAG, "Unknown sub-window type: " + type);
1342 return 0;
1343 }
1344
Dianne Hackbornabe0da02009-09-18 01:55:39 -07001345 public int getMaxWallpaperLayer() {
1346 return STATUS_BAR_LAYER;
1347 }
1348
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001349 public boolean hasSystemNavBar() {
1350 return mHasSystemNavBar;
Dianne Hackborn81e56d52011-05-26 00:55:58 -07001351 }
1352
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001353 public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
Daniel Sandler36412a72011-08-04 09:35:13 -04001354 // Assumes that the navigation bar appears on the side of the display in landscape.
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001355 if (mHasNavigationBar && fullWidth > fullHeight) {
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001356 return fullWidth - mNavigationBarWidth;
1357 }
1358 return fullWidth;
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001359 }
1360
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001361 public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
1362 // Assumes the navigation bar appears on the bottom of the display in portrait.
Daniel Sandler36412a72011-08-04 09:35:13 -04001363 return fullHeight
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001364 - (mHasSystemNavBar ? mNavigationBarHeight : 0)
1365 - ((mHasNavigationBar && fullWidth > fullHeight) ? 0 : mNavigationBarHeight);
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001366 }
1367
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001368 public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
1369 return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation);
Dianne Hackborn69cb8752011-05-19 18:13:32 -07001370 }
1371
Dianne Hackborn1f903c32011-09-13 19:18:06 -07001372 public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) {
Dianne Hackborn56b53b52011-11-10 11:19:57 -08001373 // This is the same as getNonDecorDisplayHeight, unless the status bar
1374 // can hide. If the status bar can hide, we don't count that as part
1375 // of the decor; however for purposes of configurations, we do want to
1376 // exclude it since applications can't generally use that part of the
1377 // screen.
1378 return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation)
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001379 - (mHasSystemNavBar ? 0 : mStatusBarHeight);
Dianne Hackborne2515ee2011-04-27 18:52:56 -04001380 }
1381
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001382 public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
1383 return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
1384 }
1385
1386 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
1387 return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001388 && attrs.type != WindowManager.LayoutParams.TYPE_NAVIGATION_BAR
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001389 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
1390 }
1391
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001392 /** {@inheritDoc} */
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001393 public View addStartingWindow(IBinder appToken, String packageName, int theme,
1394 CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
1395 int icon, int windowFlags) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001396 if (!SHOW_STARTING_ANIMATIONS) {
1397 return null;
1398 }
1399 if (packageName == null) {
1400 return null;
1401 }
1402
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001403 try {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001404 Context context = mContext;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001405 //Log.i(TAG, "addStartingWindow " + packageName + ": nonLocalizedLabel="
1406 // + nonLocalizedLabel + " theme=" + Integer.toHexString(theme));
Dianne Hackborn247fe742011-01-08 17:25:57 -08001407 if (theme != context.getThemeResId() || labelRes != 0) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001408 try {
1409 context = context.createPackageContext(packageName, 0);
Dianne Hackborn247fe742011-01-08 17:25:57 -08001410 context.setTheme(theme);
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001411 } catch (PackageManager.NameNotFoundException e) {
1412 // Ignore
1413 }
1414 }
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001415
1416 Window win = PolicyManager.makeNewWindow(context);
1417 if (win.getWindowStyle().getBoolean(
1418 com.android.internal.R.styleable.Window_windowDisablePreview, false)) {
1419 return null;
1420 }
1421
1422 Resources r = context.getResources();
1423 win.setTitle(r.getText(labelRes, nonLocalizedLabel));
1424
1425 win.setType(
1426 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
1427 // Force the window flags: this is a fake window, so it is not really
1428 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
1429 // flag because we do know that the next window will take input
1430 // focus, so we want to get the IME window up on top of us right away.
1431 win.setFlags(
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001432 windowFlags|
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001433 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
1434 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
1435 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001436 windowFlags|
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001437 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
1438 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
1439 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
1440
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001441 if (!compatInfo.supportsScreen()) {
1442 win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW);
1443 }
1444
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001445 win.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
Dianne Hackborn2f0b1752011-05-31 17:59:49 -07001446 WindowManager.LayoutParams.MATCH_PARENT);
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001447
1448 final WindowManager.LayoutParams params = win.getAttributes();
1449 params.token = appToken;
1450 params.packageName = packageName;
1451 params.windowAnimations = win.getWindowStyle().getResourceId(
1452 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
Dianne Hackborn5d927c22011-09-02 12:22:18 -07001453 params.privateFlags |=
1454 WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001455 params.setTitle("Starting " + packageName);
1456
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001457 WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001458 View view = win.getDecorView();
1459
1460 if (win.isFloating()) {
1461 // Whoops, there is no way to display an animation/preview
1462 // of such a thing! After all that work... let's skip it.
1463 // (Note that we must do this here because it is in
1464 // getDecorView() where the theme is evaluated... maybe
1465 // we should peek the floating attribute from the theme
1466 // earlier.)
1467 return null;
1468 }
1469
1470 if (localLOGV) Log.v(
1471 TAG, "Adding starting window for " + packageName
1472 + " / " + appToken + ": "
1473 + (view.getParent() != null ? view : null));
1474
1475 wm.addView(view, params);
1476
1477 // Only return the view if it was successfully added to the
1478 // window manager... which we can tell by it having a parent.
1479 return view.getParent() != null ? view : null;
1480 } catch (WindowManagerImpl.BadTokenException e) {
1481 // ignore
1482 Log.w(TAG, appToken + " already running, starting window not displayed");
Dianne Hackborn867ab6472010-04-29 13:28:56 -07001483 } catch (RuntimeException e) {
1484 // don't crash if something else bad happens, for example a
1485 // failure loading resources because we are loading from an app
1486 // on external storage that has been unmounted.
1487 Log.w(TAG, appToken + " failed creating starting window", e);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001488 }
1489
1490 return null;
1491 }
1492
1493 /** {@inheritDoc} */
1494 public void removeStartingWindow(IBinder appToken, View window) {
1495 // RuntimeException e = new RuntimeException();
1496 // Log.i(TAG, "remove " + appToken + " " + window, e);
1497
1498 if (localLOGV) Log.v(
1499 TAG, "Removing starting window for " + appToken + ": " + window);
1500
1501 if (window != null) {
Dianne Hackborn5fd21692011-06-07 14:09:47 -07001502 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001503 wm.removeView(window);
1504 }
1505 }
1506
1507 /**
1508 * Preflight adding a window to the system.
1509 *
1510 * Currently enforces that three window types are singletons:
1511 * <ul>
1512 * <li>STATUS_BAR_TYPE</li>
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001513 * <li>KEYGUARD_TYPE</li>
1514 * </ul>
1515 *
1516 * @param win The window to be added
1517 * @param attrs Information about the window to be added
1518 *
1519 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON
1520 */
1521 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
1522 switch (attrs.type) {
1523 case TYPE_STATUS_BAR:
Joe Onorato8bc6c512010-06-04 16:21:12 -04001524 mContext.enforceCallingOrSelfPermission(
1525 android.Manifest.permission.STATUS_BAR_SERVICE,
1526 "PhoneWindowManager");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001527 if (mStatusBar != null) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001528 if (mStatusBar.isAlive()) {
1529 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1530 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001531 }
1532 mStatusBar = win;
1533 break;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001534 case TYPE_NAVIGATION_BAR:
1535 mContext.enforceCallingOrSelfPermission(
1536 android.Manifest.permission.STATUS_BAR_SERVICE,
1537 "PhoneWindowManager");
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001538 if (mNavigationBar != null) {
1539 if (mNavigationBar.isAlive()) {
1540 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1541 }
1542 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001543 mNavigationBar = win;
1544 if (DEBUG_LAYOUT) Log.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
1545 break;
Dianne Hackborn08743722009-12-21 12:16:51 -08001546 case TYPE_STATUS_BAR_PANEL:
Joe Onorato8bc6c512010-06-04 16:21:12 -04001547 mContext.enforceCallingOrSelfPermission(
1548 android.Manifest.permission.STATUS_BAR_SERVICE,
1549 "PhoneWindowManager");
Dianne Hackborn08743722009-12-21 12:16:51 -08001550 mStatusBarPanels.add(win);
1551 break;
Joe Onorato29fc2c92010-11-24 10:26:50 -08001552 case TYPE_STATUS_BAR_SUB_PANEL:
1553 mContext.enforceCallingOrSelfPermission(
1554 android.Manifest.permission.STATUS_BAR_SERVICE,
1555 "PhoneWindowManager");
1556 mStatusBarPanels.add(win);
1557 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001558 case TYPE_KEYGUARD:
1559 if (mKeyguard != null) {
1560 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
1561 }
1562 mKeyguard = win;
1563 break;
1564 }
1565 return WindowManagerImpl.ADD_OKAY;
1566 }
1567
1568 /** {@inheritDoc} */
1569 public void removeWindowLw(WindowState win) {
1570 if (mStatusBar == win) {
1571 mStatusBar = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001572 } else if (mKeyguard == win) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001573 mKeyguard = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001574 } else if (mNavigationBar == win) {
1575 mNavigationBar = null;
Dianne Hackborn08743722009-12-21 12:16:51 -08001576 } else {
1577 mStatusBarPanels.remove(win);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001578 }
1579 }
1580
1581 static final boolean PRINT_ANIM = false;
1582
1583 /** {@inheritDoc} */
1584 public int selectAnimationLw(WindowState win, int transit) {
1585 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
1586 + ": transit=" + transit);
Dianne Hackbornf87d1962012-04-04 12:48:24 -07001587 if (win == mStatusBar) {
1588 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1589 return R.anim.dock_top_exit;
1590 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1591 return R.anim.dock_top_enter;
1592 }
1593 } else if (win == mNavigationBar) {
1594 // This can be on either the bottom or the right.
1595 if (mNavigationBarOnBottom) {
1596 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1597 return R.anim.dock_bottom_exit;
1598 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1599 return R.anim.dock_bottom_enter;
1600 }
1601 } else {
1602 if (transit == TRANSIT_EXIT || transit == TRANSIT_HIDE) {
1603 return R.anim.dock_right_exit;
1604 } else if (transit == TRANSIT_ENTER || transit == TRANSIT_SHOW) {
1605 return R.anim.dock_right_enter;
1606 }
1607 }
1608 } if (transit == TRANSIT_PREVIEW_DONE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001609 if (win.hasAppShownWindows()) {
1610 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
1611 return com.android.internal.R.anim.app_starting_exit;
1612 }
1613 }
1614
1615 return 0;
1616 }
1617
Dianne Hackborn01ad2f42009-09-24 19:24:56 -07001618 public Animation createForceHideEnterAnimation() {
1619 return AnimationUtils.loadAnimation(mContext,
1620 com.android.internal.R.anim.lock_screen_behind_enter);
1621 }
1622
Jeff Brown4d396052010-10-29 21:50:21 -07001623 static ITelephony getTelephonyService() {
Mike Lockwoodf5f4ec92011-11-08 14:05:31 -08001624 return ITelephony.Stub.asInterface(
Jeff Brown4d396052010-10-29 21:50:21 -07001625 ServiceManager.checkService(Context.TELEPHONY_SERVICE));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001626 }
1627
Jeff Brown4d396052010-10-29 21:50:21 -07001628 static IAudioService getAudioService() {
1629 IAudioService audioService = IAudioService.Stub.asInterface(
1630 ServiceManager.checkService(Context.AUDIO_SERVICE));
1631 if (audioService == null) {
1632 Log.w(TAG, "Unable to find IAudioService interface.");
1633 }
1634 return audioService;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001635 }
1636
1637 boolean keyguardOn() {
1638 return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
1639 }
1640
1641 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
1642 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
1643 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
1644 };
1645
1646 /** {@inheritDoc} */
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001647 @Override
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001648 public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001649 final boolean keyguardOn = keyguardOn();
Jeff Brown1f245102010-11-18 20:53:46 -08001650 final int keyCode = event.getKeyCode();
1651 final int repeatCount = event.getRepeatCount();
1652 final int metaState = event.getMetaState();
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001653 final int flags = event.getFlags();
Jeff Brown1f245102010-11-18 20:53:46 -08001654 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
1655 final boolean canceled = event.isCanceled();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001656
1657 if (false) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001658 Log.d(TAG, "interceptKeyTi keyCode=" + keyCode + " down=" + down + " repeatCount="
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001659 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
1660 }
1661
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001662 // If we think we might have a volume down & power key chord on the way
1663 // but we're not sure, then tell the dispatcher to wait a little while and
1664 // try again later before dispatching.
Christopher Tatee90585f2012-03-05 18:56:25 -08001665 if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001666 if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
1667 final long now = SystemClock.uptimeMillis();
1668 final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
1669 if (now < timeoutTime) {
1670 return timeoutTime - now;
1671 }
1672 }
1673 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
1674 && mVolumeDownKeyConsumedByScreenshotChord) {
1675 if (!down) {
1676 mVolumeDownKeyConsumedByScreenshotChord = false;
1677 }
1678 return -1;
1679 }
1680 }
1681
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001682 // First we always handle the home key here, so applications
1683 // can never break it, although if keyguard is on, we do let
1684 // it handle it, because that gives us the correct 5 second
1685 // timeout.
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001686 if (keyCode == KeyEvent.KEYCODE_HOME) {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001687
Jeff Brown49ed71d2010-12-06 17:13:33 -08001688 // If we have released the home key, and didn't do anything else
1689 // while it was pressed, then it is time to go home!
Michael Jurka7f2668c2012-03-27 07:49:52 -07001690 if (!down) {
1691 final boolean homeWasLongPressed = mHomeLongPressed;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001692 mHomePressed = false;
Michael Jurka7f2668c2012-03-27 07:49:52 -07001693 mHomeLongPressed = false;
1694 if (!homeWasLongPressed) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001695 try {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001696 mStatusBarService.cancelPreloadRecentApps();
1697 } catch (RemoteException e) {
1698 Slog.e(TAG, "RemoteException when showing recent apps", e);
Jeff Brown49ed71d2010-12-06 17:13:33 -08001699 }
1700
Michael Jurka7f2668c2012-03-27 07:49:52 -07001701 mHomePressed = false;
1702 if (!canceled) {
1703 // If an incoming call is ringing, HOME is totally disabled.
1704 // (The user is already on the InCallScreen at this point,
1705 // and his ONLY options are to answer or reject the call.)
1706 boolean incomingRinging = false;
1707 try {
1708 ITelephony telephonyService = getTelephonyService();
1709 if (telephonyService != null) {
1710 incomingRinging = telephonyService.isRinging();
1711 }
1712 } catch (RemoteException ex) {
1713 Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
1714 }
1715
1716 if (incomingRinging) {
1717 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
1718 } else {
1719 launchHomeFromHotKey();
1720 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001721 } else {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001722 Log.i(TAG, "Ignoring HOME; event canceled.");
Jeff Brown49ed71d2010-12-06 17:13:33 -08001723 }
Michael Jurka7f2668c2012-03-27 07:49:52 -07001724 return -1;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001725 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001726 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001727
1728 // If a system window has focus, then it doesn't make sense
1729 // right now to interact with applications.
1730 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
1731 if (attrs != null) {
1732 final int type = attrs.type;
1733 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
1734 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
1735 // the "app" is keyguard, so give it the key
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001736 return 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001737 }
1738 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
1739 for (int i=0; i<typeCount; i++) {
1740 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
1741 // don't do anything, but also don't pass it to the app
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001742 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001743 }
1744 }
1745 }
Jeff Brown98392ef2011-09-12 18:24:59 -07001746 if (down) {
Michael Jurka7f2668c2012-03-27 07:49:52 -07001747 if (!mHomePressed) {
1748 try {
1749 mStatusBarService.preloadRecentApps();
1750 } catch (RemoteException e) {
1751 Slog.e(TAG, "RemoteException when preloading recent apps", e);
1752 }
1753 }
Jeff Brown98392ef2011-09-12 18:24:59 -07001754 if (repeatCount == 0) {
1755 mHomePressed = true;
1756 } else if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
1757 if (!keyguardOn) {
1758 handleLongPressOnHome();
1759 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001760 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001761 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001762 return -1;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001763 } else if (keyCode == KeyEvent.KEYCODE_MENU) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001764 // Hijack modified menu keys for debugging features
1765 final int chordBug = KeyEvent.META_SHIFT_ON;
1766
1767 if (down && repeatCount == 0) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001768 if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001769 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
1770 mContext.sendOrderedBroadcast(intent, null);
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001771 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001772 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001773 (metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001774 Intent service = new Intent();
1775 service.setClassName(mContext, "com.android.server.LoadAverageService");
1776 ContentResolver res = mContext.getContentResolver();
1777 boolean shown = Settings.System.getInt(
1778 res, Settings.System.SHOW_PROCESSES, 0) != 0;
1779 if (!shown) {
1780 mContext.startService(service);
1781 } else {
1782 mContext.stopService(service);
1783 }
1784 Settings.System.putInt(
1785 res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001786 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001787 }
1788 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001789 } else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001790 if (down) {
1791 if (repeatCount == 0) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001792 mShortcutKeyPressed = keyCode;
1793 mConsumeShortcutKeyUp = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001794 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001795 } else if (keyCode == mShortcutKeyPressed) {
1796 mShortcutKeyPressed = -1;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001797 if (mConsumeShortcutKeyUp) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001798 mConsumeShortcutKeyUp = false;
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001799 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001800 }
1801 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001802 return 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001803 } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
Jeff Brownda3d5a92011-03-29 15:11:34 -07001804 if (down && repeatCount == 0) {
Jeff Brown68b909d2011-12-07 16:36:01 -08001805 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_SHOW_OR_DISMISS);
Jeff Brown49ed71d2010-12-06 17:13:33 -08001806 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001807 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001808 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001809
Jeff Brownc1fb48d2010-12-08 16:52:09 -08001810 // Shortcuts are invoked through Search+key, so intercept those here
Jeff Browncaab4d02010-12-09 22:13:41 -08001811 // Any printing key that is chorded with Search should be consumed
1812 // even if no shortcut was invoked. This prevents text from being
1813 // inadvertently inserted when using a keyboard that has built-in macro
1814 // shortcut keys (that emit Search+x) and some of them are not registered.
1815 if (mShortcutKeyPressed != -1) {
1816 final KeyCharacterMap kcm = event.getKeyCharacterMap();
1817 if (kcm.isPrintingKey(keyCode)) {
1818 mConsumeShortcutKeyUp = true;
1819 if (down && repeatCount == 0 && !keyguardOn) {
1820 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode, metaState);
1821 if (shortcutIntent != null) {
1822 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Jeff Brownf0a3cc52011-01-26 18:42:46 -08001823 try {
1824 mContext.startActivity(shortcutIntent);
1825 } catch (ActivityNotFoundException ex) {
1826 Slog.w(TAG, "Dropping shortcut key combination because "
1827 + "the activity to which it is registered was not found: "
1828 + KeyEvent.keyCodeToString(mShortcutKeyPressed)
1829 + "+" + KeyEvent.keyCodeToString(keyCode), ex);
1830 }
Jeff Browncaab4d02010-12-09 22:13:41 -08001831 } else {
1832 Slog.i(TAG, "Dropping unregistered shortcut key combination: "
1833 + KeyEvent.keyCodeToString(mShortcutKeyPressed)
1834 + "+" + KeyEvent.keyCodeToString(keyCode));
Jeff Brown49ed71d2010-12-06 17:13:33 -08001835 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001836 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001837 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001838 }
1839 }
1840
Jeff Brown68b909d2011-12-07 16:36:01 -08001841 // Invoke shortcuts using Meta.
1842 if (down && repeatCount == 0
1843 && (metaState & KeyEvent.META_META_ON) != 0) {
1844 final KeyCharacterMap kcm = event.getKeyCharacterMap();
1845 Intent shortcutIntent = mShortcutManager.getIntent(kcm, keyCode,
1846 metaState & ~(KeyEvent.META_META_ON
1847 | KeyEvent.META_META_LEFT_ON | KeyEvent.META_META_RIGHT_ON));
1848 if (shortcutIntent != null) {
1849 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1850 try {
1851 mContext.startActivity(shortcutIntent);
1852 } catch (ActivityNotFoundException ex) {
1853 Slog.w(TAG, "Dropping shortcut key combination because "
1854 + "the activity to which it is registered was not found: "
1855 + "META+" + KeyEvent.keyCodeToString(keyCode), ex);
1856 }
1857 return -1;
1858 }
1859 }
1860
Jeff Brown6651a632011-11-28 12:59:11 -08001861 // Handle application launch keys.
1862 if (down && repeatCount == 0) {
1863 String category = sApplicationLaunchKeyCategories.get(keyCode);
1864 if (category != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -08001865 Intent intent = Intent.makeMainSelectorActivity(Intent.ACTION_MAIN, category);
Jeff Brown6651a632011-11-28 12:59:11 -08001866 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1867 try {
1868 mContext.startActivity(intent);
1869 } catch (ActivityNotFoundException ex) {
1870 Slog.w(TAG, "Dropping application launch key because "
1871 + "the activity to which it is registered was not found: "
1872 + "keyCode=" + keyCode + ", category=" + category, ex);
1873 }
Jeff Brown68b909d2011-12-07 16:36:01 -08001874 return -1;
Jeff Brown6651a632011-11-28 12:59:11 -08001875 }
1876 }
1877
Jeff Brown68b909d2011-12-07 16:36:01 -08001878 // Display task switcher for ALT-TAB or Meta-TAB.
1879 if (down && repeatCount == 0 && keyCode == KeyEvent.KEYCODE_TAB) {
1880 if (mRecentAppsDialogHeldModifiers == 0) {
1881 final int shiftlessModifiers = event.getModifiers() & ~KeyEvent.META_SHIFT_MASK;
1882 if (KeyEvent.metaStateHasModifiers(shiftlessModifiers, KeyEvent.META_ALT_ON)
1883 || KeyEvent.metaStateHasModifiers(
1884 shiftlessModifiers, KeyEvent.META_META_ON)) {
1885 mRecentAppsDialogHeldModifiers = shiftlessModifiers;
1886 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_EXIT_TOUCH_MODE_AND_SHOW);
1887 return -1;
1888 }
1889 }
1890 } else if (!down && mRecentAppsDialogHeldModifiers != 0
1891 && (metaState & mRecentAppsDialogHeldModifiers) == 0) {
1892 mRecentAppsDialogHeldModifiers = 0;
1893 showOrHideRecentAppsDialog(RECENT_APPS_BEHAVIOR_DISMISS_AND_SWITCH);
1894 }
1895
1896 // Let the application handle the key.
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001897 return 0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001898 }
1899
Jeff Brown3915bb82010-11-05 15:02:16 -07001900 /** {@inheritDoc} */
1901 @Override
Jeff Brown49ed71d2010-12-06 17:13:33 -08001902 public KeyEvent dispatchUnhandledKey(WindowState win, KeyEvent event, int policyFlags) {
Jeff Brown54875002011-04-06 15:33:01 -07001903 // Note: This method is only called if the initial down was unhandled.
Jeff Brown49ed71d2010-12-06 17:13:33 -08001904 if (DEBUG_FALLBACK) {
Jeff Brown1f245102010-11-18 20:53:46 -08001905 Slog.d(TAG, "Unhandled key: win=" + win + ", action=" + event.getAction()
1906 + ", flags=" + event.getFlags()
1907 + ", keyCode=" + event.getKeyCode()
1908 + ", scanCode=" + event.getScanCode()
1909 + ", metaState=" + event.getMetaState()
1910 + ", repeatCount=" + event.getRepeatCount()
1911 + ", policyFlags=" + policyFlags);
Jeff Brown3915bb82010-11-05 15:02:16 -07001912 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001913
1914 if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
1915 final KeyCharacterMap kcm = event.getKeyCharacterMap();
Jeff Brownc1fb48d2010-12-08 16:52:09 -08001916 final int keyCode = event.getKeyCode();
1917 final int metaState = event.getMetaState();
Jeff Brown49ed71d2010-12-06 17:13:33 -08001918
Jeff Brown54875002011-04-06 15:33:01 -07001919 // Check for fallback actions specified by the key character map.
Jeff Brown6f2fba42011-02-19 01:08:02 -08001920 if (getFallbackAction(kcm, keyCode, metaState, mFallbackAction)) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001921 if (DEBUG_FALLBACK) {
1922 Slog.d(TAG, "Fallback: keyCode=" + mFallbackAction.keyCode
1923 + " metaState=" + Integer.toHexString(mFallbackAction.metaState));
1924 }
1925
1926 int flags = event.getFlags() | KeyEvent.FLAG_FALLBACK;
1927 KeyEvent fallbackEvent = KeyEvent.obtain(
1928 event.getDownTime(), event.getEventTime(),
1929 event.getAction(), mFallbackAction.keyCode,
1930 event.getRepeatCount(), mFallbackAction.metaState,
1931 event.getDeviceId(), event.getScanCode(),
1932 flags, event.getSource(), null);
1933 int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
1934 if ((actions & ACTION_PASS_TO_USER) != 0) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07001935 long delayMillis = interceptKeyBeforeDispatching(
1936 win, fallbackEvent, policyFlags);
1937 if (delayMillis == 0) {
Jeff Brown49ed71d2010-12-06 17:13:33 -08001938 if (DEBUG_FALLBACK) {
1939 Slog.d(TAG, "Performing fallback.");
1940 }
1941 return fallbackEvent;
1942 }
1943 }
1944 fallbackEvent.recycle();
1945 }
1946 }
1947
1948 if (DEBUG_FALLBACK) {
1949 Slog.d(TAG, "No fallback.");
1950 }
1951 return null;
Jeff Brown3915bb82010-11-05 15:02:16 -07001952 }
1953
Jeff Brown6f2fba42011-02-19 01:08:02 -08001954 private boolean getFallbackAction(KeyCharacterMap kcm, int keyCode, int metaState,
1955 FallbackAction outFallbackAction) {
1956 // Consult the key character map for specific fallback actions.
1957 // For example, map NUMPAD_1 to MOVE_HOME when NUMLOCK is not pressed.
Jeff Browncc0c1592011-02-19 05:07:28 -08001958 return kcm.getFallbackAction(keyCode, metaState, outFallbackAction);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001959 }
1960
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001961 /**
1962 * A home key -> launch home action was detected. Take the appropriate action
1963 * given the situation with the keyguard.
1964 */
1965 void launchHomeFromHotKey() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07001966 if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001967 // don't launch home if keyguard showing
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001968 } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001969 // when in keyguard restricted mode, must first verify unlock
1970 // before launching home
1971 mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
1972 public void onKeyguardExitResult(boolean success) {
1973 if (success) {
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07001974 try {
1975 ActivityManagerNative.getDefault().stopAppSwitches();
1976 } catch (RemoteException e) {
1977 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05001978 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001979 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001980 }
1981 }
1982 });
1983 } else {
1984 // no keyguard stuff to worry about, just launch home!
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07001985 try {
1986 ActivityManagerNative.getDefault().stopAppSwitches();
1987 } catch (RemoteException e) {
1988 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05001989 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001990 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001991 }
1992 }
1993
Dianne Hackborne26ab702011-10-16 13:21:33 -07001994 /**
1995 * A delayed callback use to determine when it is okay to re-allow applications
1996 * to use certain system UI flags. This is used to prevent applications from
1997 * spamming system UI changes that prevent the navigation bar from being shown.
1998 */
1999 final Runnable mAllowSystemUiDelay = new Runnable() {
2000 @Override public void run() {
2001 }
2002 };
2003
2004 /**
2005 * Input handler used while nav bar is hidden. Captures any touch on the screen,
2006 * to determine when the nav bar should be shown and prevent applications from
2007 * receiving those touches.
2008 */
Jeff Brown32cbc38552011-12-01 14:01:49 -08002009 final class HideNavInputEventReceiver extends InputEventReceiver {
2010 public HideNavInputEventReceiver(InputChannel inputChannel, Looper looper) {
2011 super(inputChannel, looper);
2012 }
2013
Dianne Hackborndf89e652011-10-06 22:35:11 -07002014 @Override
Jeff Brown32cbc38552011-12-01 14:01:49 -08002015 public void onInputEvent(InputEvent event) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002016 boolean handled = false;
2017 try {
Jeff Brown4952dfd2011-11-30 19:23:22 -08002018 if (event instanceof MotionEvent
2019 && (event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) {
2020 final MotionEvent motionEvent = (MotionEvent)event;
2021 if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002022 // When the user taps down, we re-show the nav bar.
2023 boolean changed = false;
2024 synchronized (mLock) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002025 // Any user activity always causes us to show the
2026 // navigation controls, if they had been hidden.
2027 // We also clear the low profile and only content
2028 // flags so that tapping on the screen will atomically
2029 // restore all currently hidden screen decorations.
2030 int newVal = mResettingSystemUiFlags |
2031 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
2032 View.SYSTEM_UI_FLAG_LOW_PROFILE |
2033 View.SYSTEM_UI_FLAG_FULLSCREEN;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002034 if (mResettingSystemUiFlags != newVal) {
2035 mResettingSystemUiFlags = newVal;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002036 changed = true;
2037 }
Dianne Hackborne26ab702011-10-16 13:21:33 -07002038 // We don't allow the system's nav bar to be hidden
2039 // again for 1 second, to prevent applications from
2040 // spamming us and keeping it from being shown.
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002041 newVal = mForceClearedSystemUiFlags |
2042 View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002043 if (mForceClearedSystemUiFlags != newVal) {
2044 mForceClearedSystemUiFlags = newVal;
2045 changed = true;
2046 mHandler.postDelayed(new Runnable() {
2047 @Override public void run() {
2048 synchronized (mLock) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002049 // Clear flags.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002050 mForceClearedSystemUiFlags &=
2051 ~View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
2052 }
2053 mWindowManagerFuncs.reevaluateStatusBarVisibility();
2054 }
2055 }, 1000);
2056 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07002057 }
2058 if (changed) {
2059 mWindowManagerFuncs.reevaluateStatusBarVisibility();
2060 }
2061 }
2062 }
2063 } finally {
Jeff Brown32cbc38552011-12-01 14:01:49 -08002064 finishInputEvent(event, handled);
Dianne Hackborndf89e652011-10-06 22:35:11 -07002065 }
2066 }
Jeff Brown32cbc38552011-12-01 14:01:49 -08002067 }
2068 final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
2069 new InputEventReceiver.Factory() {
2070 @Override
2071 public InputEventReceiver createInputEventReceiver(
2072 InputChannel inputChannel, Looper looper) {
2073 return new HideNavInputEventReceiver(inputChannel, looper);
2074 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07002075 };
2076
2077 @Override
2078 public int adjustSystemUiVisibilityLw(int visibility) {
2079 // Reset any bits in mForceClearingStatusBarVisibility that
2080 // are now clear.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002081 mResettingSystemUiFlags &= visibility;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002082 // Clear any bits in the new visibility that are currently being
2083 // force cleared, before reporting it.
Dianne Hackborne26ab702011-10-16 13:21:33 -07002084 return visibility & ~mResettingSystemUiFlags
2085 & ~mForceClearedSystemUiFlags;
Dianne Hackborndf89e652011-10-06 22:35:11 -07002086 }
2087
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002088 public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
2089 final int fl = attrs.flags;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002090
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07002091 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002092 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002093 int availRight, availBottom;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002094 if (mCanHideNavigationBar &&
2095 (attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002096 availRight = mUnrestrictedScreenLeft + mUnrestrictedScreenWidth;
2097 availBottom = mUnrestrictedScreenTop + mUnrestrictedScreenHeight;
2098 } else {
2099 availRight = mRestrictedScreenLeft + mRestrictedScreenWidth;
2100 availBottom = mRestrictedScreenTop + mRestrictedScreenHeight;
2101 }
2102 if ((attrs.systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2103 contentInset.set(mStableLeft, mStableTop,
2104 availRight - mStableRight, availBottom - mStableBottom);
2105 } else if ((attrs.systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
2106 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
2107 contentInset.set(mCurLeft, mCurTop,
2108 availRight - mCurRight, availBottom - mCurBottom);
2109 } else {
2110 contentInset.set(mCurLeft, mCurTop,
2111 availRight - mCurRight, availBottom - mCurBottom);
2112 }
2113 return;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002114 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002115 contentInset.setEmpty();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002116 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002117
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002118 /** {@inheritDoc} */
Dianne Hackborn1f903c32011-09-13 19:18:06 -07002119 public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation) {
Joe Onorato29fc2c92010-11-24 10:26:50 -08002120 mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
2121 mUnrestrictedScreenWidth = displayWidth;
2122 mUnrestrictedScreenHeight = displayHeight;
2123 mRestrictedScreenLeft = mRestrictedScreenTop = 0;
2124 mRestrictedScreenWidth = displayWidth;
2125 mRestrictedScreenHeight = displayHeight;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002126 mDockLeft = mContentLeft = mStableLeft = mCurLeft = 0;
2127 mDockTop = mContentTop = mStableTop = mCurTop = 0;
2128 mDockRight = mContentRight = mStableRight = mCurRight = displayWidth;
2129 mDockBottom = mContentBottom = mStableBottom = mCurBottom = displayHeight;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002130 mDockLayer = 0x10000000;
2131
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002132 // start with the current dock rect, which will be (0,0,displayWidth,displayHeight)
2133 final Rect pf = mTmpParentFrame;
2134 final Rect df = mTmpDisplayFrame;
2135 final Rect vf = mTmpVisibleFrame;
2136 pf.left = df.left = vf.left = mDockLeft;
2137 pf.top = df.top = vf.top = mDockTop;
2138 pf.right = df.right = vf.right = mDockRight;
2139 pf.bottom = df.bottom = vf.bottom = mDockBottom;
2140
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002141 // For purposes of putting out fake window up to steal focus, we will
2142 // drive nav being hidden only by whether it is requested.
2143 boolean navVisible = (mLastSystemUiFlags&View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
Dianne Hackborne26ab702011-10-16 13:21:33 -07002144
2145 // When the navigation bar isn't visible, we put up a fake
2146 // input window to catch all touch events. This way we can
2147 // detect when the user presses anywhere to bring back the nav
2148 // bar and ensure the application doesn't see the event.
2149 if (navVisible) {
2150 if (mHideNavFakeWindow != null) {
2151 mHideNavFakeWindow.dismiss();
2152 mHideNavFakeWindow = null;
2153 }
2154 } else if (mHideNavFakeWindow == null) {
2155 mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
Jeff Brown32cbc38552011-12-01 14:01:49 -08002156 mHandler.getLooper(), mHideNavInputEventReceiverFactory,
Dianne Hackborne26ab702011-10-16 13:21:33 -07002157 "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
2158 0, false, false, true);
2159 }
2160
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002161 // For purposes of positioning and showing the nav bar, if we have
2162 // decided that it can't be hidden (because of the screen aspect ratio),
2163 // then take that into account.
2164 navVisible |= !mCanHideNavigationBar;
2165
2166 if (mNavigationBar != null) {
2167 // Force the navigation bar to its appropriate place and
2168 // size. We need to do this directly, instead of relying on
2169 // it to bubble up from the nav bar, because this needs to
2170 // change atomically with screen rotations.
2171 mNavigationBarOnBottom = !mHasNavigationBar || displayWidth < displayHeight;
2172 if (mNavigationBarOnBottom) {
2173 // It's a system nav bar or a portrait screen; nav bar goes on bottom.
2174 int top = displayHeight - mNavigationBarHeight;
2175 if (mHdmiPlugged) {
2176 if (top > mExternalDisplayHeight) {
2177 top = mExternalDisplayHeight;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002178 }
2179 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002180 mTmpNavigationFrame.set(0, top, displayWidth, displayHeight);
2181 mStableBottom = mTmpNavigationFrame.top;
2182 if (navVisible) {
2183 mNavigationBar.showLw(true);
2184 mDockBottom = mTmpNavigationFrame.top;
2185 mRestrictedScreenHeight = mDockBottom - mDockTop;
2186 } else {
2187 // We currently want to hide the navigation UI.
2188 mNavigationBar.hideLw(true);
2189 }
2190 } else {
2191 // Landscape screen; nav bar goes to the right.
2192 int left = displayWidth - mNavigationBarWidth;
2193 if (mHdmiPlugged) {
2194 if (left > mExternalDisplayWidth) {
2195 left = mExternalDisplayWidth;
2196 }
2197 }
2198 mTmpNavigationFrame.set(left, 0, displayWidth, displayHeight);
2199 mStableRight = mTmpNavigationFrame.left;
2200 if (navVisible) {
2201 mNavigationBar.showLw(true);
2202 mDockRight = mTmpNavigationFrame.left;
2203 mRestrictedScreenWidth = mDockRight - mDockLeft;
2204 } else {
2205 // We currently want to hide the navigation UI.
2206 mNavigationBar.hideLw(true);
2207 }
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002208 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002209 // Make sure the content and current rectangles are updated to
2210 // account for the restrictions from the navigation bar.
2211 mContentTop = mCurTop = mDockTop;
2212 mContentBottom = mCurBottom = mDockBottom;
2213 mContentLeft = mCurLeft = mDockLeft;
2214 mContentRight = mCurRight = mDockRight;
2215 // And compute the final frame.
2216 mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
2217 mTmpNavigationFrame, mTmpNavigationFrame);
2218 if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
2219 }
2220 if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
2221 mDockLeft, mDockTop, mDockRight, mDockBottom));
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002222
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002223 // decide where the status bar goes ahead of time
2224 if (mStatusBar != null) {
2225 // apply any navigation bar insets
Dianne Hackborn98014352012-04-05 18:31:41 -07002226 pf.left = df.left = mUnrestrictedScreenLeft;
2227 pf.top = df.top = mUnrestrictedScreenTop;
2228 pf.right = df.right = mUnrestrictedScreenWidth - mUnrestrictedScreenLeft;
2229 pf.bottom = df.bottom = mUnrestrictedScreenHeight - mUnrestrictedScreenTop;
2230 vf.left = mStableLeft;
2231 vf.top = mStableTop;
2232 vf.right = mStableRight;
2233 vf.bottom = mStableBottom;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002234
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002235 mStatusBar.computeFrameLw(pf, df, vf, vf);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002236 final Rect r = mStatusBar.getFrameLw();
2237
2238 // Compute the stable dimensions whether or not the status bar is hidden.
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002239 if (mDockTop == r.top) mStableTop = r.bottom;
2240 else if (mDockBottom == r.bottom) mStableBottom = r.top;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002241
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002242 // If the status bar is hidden, we don't want to cause
2243 // windows behind it to scroll.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002244 if (mStatusBar.isVisibleLw()) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002245 // Status bar may go away, so the screen area it occupies
2246 // is available to apps but just covering them when the
2247 // status bar is visible.
2248 if (mDockTop == r.top) mDockTop = r.bottom;
2249 else if (mDockBottom == r.bottom) mDockBottom = r.top;
2250
2251 mContentTop = mCurTop = mDockTop;
2252 mContentBottom = mCurBottom = mDockBottom;
2253 mContentLeft = mCurLeft = mDockLeft;
2254 mContentRight = mCurRight = mDockRight;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002255
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002256 if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: " +
2257 String.format(
2258 "dock=[%d,%d][%d,%d] content=[%d,%d][%d,%d] cur=[%d,%d][%d,%d]",
2259 mDockLeft, mDockTop, mDockRight, mDockBottom,
2260 mContentLeft, mContentTop, mContentRight, mContentBottom,
2261 mCurLeft, mCurTop, mCurRight, mCurBottom));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002262 }
2263 }
2264 }
2265
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002266 void setAttachedWindowFrames(WindowState win, int fl, int adjust,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002267 WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
2268 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
2269 // Here's a special case: if this attached window is a panel that is
2270 // above the dock window, and the window it is attached to is below
2271 // the dock window, then the frames we computed for the window it is
2272 // attached to can not be used because the dock is effectively part
2273 // of the underlying window and the attached window is floating on top
2274 // of the whole thing. So, we ignore the attached window and explicitly
2275 // compute the frames that would be appropriate without the dock.
2276 df.left = cf.left = vf.left = mDockLeft;
2277 df.top = cf.top = vf.top = mDockTop;
2278 df.right = cf.right = vf.right = mDockRight;
2279 df.bottom = cf.bottom = vf.bottom = mDockBottom;
2280 } else {
2281 // The effective display frame of the attached window depends on
2282 // whether it is taking care of insetting its content. If not,
2283 // we need to use the parent's content frame so that the entire
2284 // window is positioned within that content. Otherwise we can use
2285 // the display frame and let the attached window take care of
2286 // positioning its content appropriately.
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002287 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002288 cf.set(attached.getDisplayFrameLw());
2289 } else {
2290 // If the window is resizing, then we want to base the content
2291 // frame on our attached content frame to resize... however,
2292 // things can be tricky if the attached window is NOT in resize
2293 // mode, in which case its content frame will be larger.
2294 // Ungh. So to deal with that, make sure the content frame
2295 // we end up using is not covering the IM dock.
2296 cf.set(attached.getContentFrameLw());
2297 if (attached.getSurfaceLayer() < mDockLayer) {
2298 if (cf.left < mContentLeft) cf.left = mContentLeft;
2299 if (cf.top < mContentTop) cf.top = mContentTop;
2300 if (cf.right > mContentRight) cf.right = mContentRight;
2301 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
2302 }
2303 }
2304 df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
2305 vf.set(attached.getVisibleFrameLw());
2306 }
2307 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
2308 // window should be positioned relative to its parent or the entire
2309 // screen.
2310 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
2311 ? attached.getFrameLw() : df);
2312 }
2313
2314 /** {@inheritDoc} */
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07002315 public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
2316 WindowState attached) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002317 // we've already done the status bar
Dianne Hackborn1f903c32011-09-13 19:18:06 -07002318 if (win == mStatusBar || win == mNavigationBar) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002319 return;
2320 }
2321
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002322 final int fl = attrs.flags;
2323 final int sim = attrs.softInputMode;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002324 final int sysUiFl = win.getSystemUiVisibility();
2325
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002326 final Rect pf = mTmpParentFrame;
2327 final Rect df = mTmpDisplayFrame;
2328 final Rect cf = mTmpContentFrame;
2329 final Rect vf = mTmpVisibleFrame;
2330
Daniel Sandler36412a72011-08-04 09:35:13 -04002331 final boolean hasNavBar = (mHasNavigationBar
2332 && mNavigationBar != null && mNavigationBar.isVisibleLw());
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002333
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002334 if (attrs.type == TYPE_INPUT_METHOD) {
2335 pf.left = df.left = cf.left = vf.left = mDockLeft;
2336 pf.top = df.top = cf.top = vf.top = mDockTop;
2337 pf.right = df.right = cf.right = vf.right = mDockRight;
2338 pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
2339 // IM dock windows always go to the bottom of the screen.
2340 attrs.gravity = Gravity.BOTTOM;
2341 mDockLayer = win.getSurfaceLayer();
2342 } else {
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002343 final int adjust = sim & SOFT_INPUT_MASK_ADJUST;
2344
Dianne Hackborn82de1ae2010-10-28 11:28:39 -07002345 if ((fl & (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002346 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)
2347 && (sysUiFl & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002348 if (DEBUG_LAYOUT)
2349 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle()
2350 + "): IN_SCREEN, INSET_DECOR, !FULLSCREEN");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002351 // This is the case for a normal activity window: we want it
2352 // to cover all of the screen space, and it can take care of
2353 // moving its contents to account for screen decorations that
2354 // intrude into that space.
2355 if (attached != null) {
2356 // If this window is attached to another, our display
2357 // frame is the same as the one we are attached to.
2358 setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
2359 } else {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002360 if (attrs.type == TYPE_STATUS_BAR_PANEL
2361 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
Joe Onorato29fc2c92010-11-24 10:26:50 -08002362 // Status bar panels are the only windows who can go on top of
2363 // the status bar. They are protected by the STATUS_BAR_SERVICE
2364 // permission, so they have the same privileges as the status
2365 // bar itself.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002366 //
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002367 // However, they should still dodge the navigation bar if it exists.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002368
2369 pf.left = df.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002370 pf.top = df.top = mUnrestrictedScreenTop;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002371 pf.right = df.right = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002372 ? mRestrictedScreenLeft+mRestrictedScreenWidth
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002373 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2374 pf.bottom = df.bottom = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002375 ? mRestrictedScreenTop+mRestrictedScreenHeight
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002376 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
2377
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002378 if (DEBUG_LAYOUT) {
2379 Log.v(TAG, String.format(
2380 "Laying out status bar window: (%d,%d - %d,%d)",
2381 pf.left, pf.top, pf.right, pf.bottom));
2382 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002383 } else if (mCanHideNavigationBar
2384 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002385 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
2386 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
2387 // Asking for layout as if the nav bar is hidden, lets the
2388 // application extend into the unrestricted screen area. We
2389 // only do this for application windows to ensure no window that
2390 // can be above the nav bar can do this.
2391 pf.left = df.left = mUnrestrictedScreenLeft;
2392 pf.top = df.top = mUnrestrictedScreenTop;
2393 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2394 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002395 } else {
2396 pf.left = df.left = mRestrictedScreenLeft;
2397 pf.top = df.top = mRestrictedScreenTop;
2398 pf.right = df.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2399 pf.bottom = df.bottom = mRestrictedScreenTop+mRestrictedScreenHeight;
2400 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002401 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002402 cf.left = mDockLeft;
2403 cf.top = mDockTop;
2404 cf.right = mDockRight;
2405 cf.bottom = mDockBottom;
2406 } else {
2407 cf.left = mContentLeft;
2408 cf.top = mContentTop;
2409 cf.right = mContentRight;
2410 cf.bottom = mContentBottom;
2411 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002412 if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2413 // If app is requesting a stable layout, don't let the
2414 // content insets go below the stable values.
2415 if (cf.left < mStableLeft) cf.left = mStableLeft;
2416 if (cf.top < mStableTop) cf.top = mStableTop;
2417 if (cf.right > mStableRight) cf.right = mStableRight;
2418 if (cf.bottom > mStableBottom) cf.bottom = mStableBottom;
2419 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002420 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2421 vf.left = mCurLeft;
2422 vf.top = mCurTop;
2423 vf.right = mCurRight;
2424 vf.bottom = mCurBottom;
2425 } else {
2426 vf.set(cf);
2427 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002428 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002429 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0 || (sysUiFl
2430 & (View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
2431 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)) != 0) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002432 if (DEBUG_LAYOUT)
2433 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): IN_SCREEN");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002434 // A window that has requested to fill the entire screen just
2435 // gets everything, period.
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002436 if (attrs.type == TYPE_STATUS_BAR_PANEL
2437 || attrs.type == TYPE_STATUS_BAR_SUB_PANEL) {
2438 pf.left = df.left = cf.left = hasNavBar ? mDockLeft : mUnrestrictedScreenLeft;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002439 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002440 pf.right = df.right = cf.right = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002441 ? mRestrictedScreenLeft+mRestrictedScreenWidth
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002442 : mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2443 pf.bottom = df.bottom = cf.bottom = hasNavBar
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002444 ? mRestrictedScreenTop+mRestrictedScreenHeight
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002445 : mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Daniel Sandler36412a72011-08-04 09:35:13 -04002446 if (DEBUG_LAYOUT) {
2447 Log.v(TAG, String.format(
2448 "Laying out IN_SCREEN status bar window: (%d,%d - %d,%d)",
2449 pf.left, pf.top, pf.right, pf.bottom));
2450 }
Daniel Sandler8e8b4152011-07-21 01:16:43 -04002451 } else if (attrs.type == TYPE_NAVIGATION_BAR) {
2452 // The navigation bar has Real Ultimate Power.
2453 pf.left = df.left = mUnrestrictedScreenLeft;
2454 pf.top = df.top = mUnrestrictedScreenTop;
2455 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2456 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
2457 if (DEBUG_LAYOUT) {
2458 Log.v(TAG, String.format(
2459 "Laying out navigation bar window: (%d,%d - %d,%d)",
2460 pf.left, pf.top, pf.right, pf.bottom));
2461 }
Dianne Hackborn01011c32012-02-21 13:54:21 -08002462 } else if ((attrs.type == TYPE_SECURE_SYSTEM_OVERLAY
2463 || attrs.type == TYPE_BOOT_PROGRESS)
Jeff Brownbfcb60a2011-09-08 18:51:14 -07002464 && ((fl & FLAG_FULLSCREEN) != 0)) {
2465 // Fullscreen secure system overlays get what they ask for.
2466 pf.left = df.left = mUnrestrictedScreenLeft;
2467 pf.top = df.top = mUnrestrictedScreenTop;
2468 pf.right = df.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2469 pf.bottom = df.bottom = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Dianne Hackborn01011c32012-02-21 13:54:21 -08002470 } else if (attrs.type == TYPE_BOOT_PROGRESS) {
2471 // Boot progress screen always covers entire display.
2472 pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
2473 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
2474 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2475 pf.bottom = df.bottom = cf.bottom
2476 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002477 } else if (mCanHideNavigationBar
2478 && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002479 && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
2480 && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
2481 // Asking for layout as if the nav bar is hidden, lets the
2482 // application extend into the unrestricted screen area. We
2483 // only do this for application windows to ensure no window that
2484 // can be above the nav bar can do this.
2485 // XXX This assumes that an app asking for this will also
2486 // ask for layout in only content. We can't currently figure out
2487 // what the screen would be if only laying out to hide the nav bar.
2488 pf.left = df.left = cf.left = mUnrestrictedScreenLeft;
2489 pf.top = df.top = cf.top = mUnrestrictedScreenTop;
2490 pf.right = df.right = cf.right = mUnrestrictedScreenLeft+mUnrestrictedScreenWidth;
2491 pf.bottom = df.bottom = cf.bottom
2492 = mUnrestrictedScreenTop+mUnrestrictedScreenHeight;
Joe Onorato29fc2c92010-11-24 10:26:50 -08002493 } else {
2494 pf.left = df.left = cf.left = mRestrictedScreenLeft;
2495 pf.top = df.top = cf.top = mRestrictedScreenTop;
2496 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2497 pf.bottom = df.bottom = cf.bottom
2498 = mRestrictedScreenTop+mRestrictedScreenHeight;
2499 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002500 if ((sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
2501 // If app is requesting a stable layout, don't let the
2502 // content insets go below the stable values.
2503 if (cf.left < mStableLeft) cf.left = mStableLeft;
2504 if (cf.top < mStableTop) cf.top = mStableTop;
2505 if (cf.right > mStableRight) cf.right = mStableRight;
2506 if (cf.bottom > mStableBottom) cf.bottom = mStableBottom;
2507 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002508 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2509 vf.left = mCurLeft;
2510 vf.top = mCurTop;
2511 vf.right = mCurRight;
2512 vf.bottom = mCurBottom;
2513 } else {
2514 vf.set(cf);
2515 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002516 } else if (attached != null) {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002517 if (DEBUG_LAYOUT)
2518 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): attached to " + attached);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002519 // A child window should be placed inside of the same visible
2520 // frame that its parent had.
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002521 setAttachedWindowFrames(win, fl, adjust, attached, false, pf, df, cf, vf);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002522 } else {
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002523 if (DEBUG_LAYOUT)
2524 Log.v(TAG, "layoutWindowLw(" + attrs.getTitle() + "): normal window");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002525 // Otherwise, a normal window must be placed inside the content
2526 // of all screen decorations.
Dianne Hackborna239c842011-06-01 12:28:20 -07002527 if (attrs.type == TYPE_STATUS_BAR_PANEL) {
2528 // Status bar panels are the only windows who can go on top of
2529 // the status bar. They are protected by the STATUS_BAR_SERVICE
2530 // permission, so they have the same privileges as the status
2531 // bar itself.
Dianne Hackborn7d049322011-06-14 15:00:32 -07002532 pf.left = df.left = cf.left = mRestrictedScreenLeft;
2533 pf.top = df.top = cf.top = mRestrictedScreenTop;
2534 pf.right = df.right = cf.right = mRestrictedScreenLeft+mRestrictedScreenWidth;
2535 pf.bottom = df.bottom = cf.bottom
2536 = mRestrictedScreenTop+mRestrictedScreenHeight;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002537 } else {
Dianne Hackborna239c842011-06-01 12:28:20 -07002538 pf.left = mContentLeft;
2539 pf.top = mContentTop;
2540 pf.right = mContentRight;
2541 pf.bottom = mContentBottom;
2542 if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
2543 df.left = cf.left = mDockLeft;
2544 df.top = cf.top = mDockTop;
2545 df.right = cf.right = mDockRight;
2546 df.bottom = cf.bottom = mDockBottom;
2547 } else {
2548 df.left = cf.left = mContentLeft;
2549 df.top = cf.top = mContentTop;
2550 df.right = cf.right = mContentRight;
2551 df.bottom = cf.bottom = mContentBottom;
2552 }
2553 if (adjust != SOFT_INPUT_ADJUST_NOTHING) {
2554 vf.left = mCurLeft;
2555 vf.top = mCurTop;
2556 vf.right = mCurRight;
2557 vf.bottom = mCurBottom;
2558 } else {
2559 vf.set(cf);
2560 }
Dianne Hackborndea3ef72010-10-28 14:24:22 -07002561 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002562 }
2563 }
2564
2565 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
2566 df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
2567 df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
2568 }
2569
The Android Open Source Project11267662009-03-18 17:39:47 -07002570 if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
2571 + ": sim=#" + Integer.toHexString(sim)
Daniel Sandler8956dbb2011-04-22 07:55:02 -04002572 + " attach=" + attached + " type=" + attrs.type
2573 + String.format(" flags=0x%08x", fl)
The Android Open Source Project11267662009-03-18 17:39:47 -07002574 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
2575 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
2576
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002577 win.computeFrameLw(pf, df, cf, vf);
2578
2579 // Dock windows carve out the bottom of the screen, so normal windows
2580 // can't appear underneath them.
2581 if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
2582 int top = win.getContentFrameLw().top;
2583 top += win.getGivenContentInsetsLw().top;
2584 if (mContentBottom > top) {
2585 mContentBottom = top;
2586 }
2587 top = win.getVisibleFrameLw().top;
2588 top += win.getGivenVisibleInsetsLw().top;
2589 if (mCurBottom > top) {
2590 mCurBottom = top;
2591 }
The Android Open Source Project11267662009-03-18 17:39:47 -07002592 if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom="
2593 + mDockBottom + " mContentBottom="
2594 + mContentBottom + " mCurBottom=" + mCurBottom);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002595 }
2596 }
2597
2598 /** {@inheritDoc} */
Craig Mautner61ac6bb2012-02-02 17:29:33 -08002599 @Override
2600 public void finishLayoutLw() {
2601 return;
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002602 }
2603
2604 /** {@inheritDoc} */
2605 public void beginAnimationLw(int displayWidth, int displayHeight) {
2606 mTopFullscreenOpaqueWindowState = null;
2607 mForceStatusBar = false;
2608
2609 mHideLockScreen = false;
2610 mAllowLockscreenWhenOn = false;
2611 mDismissKeyguard = false;
2612 }
2613
2614 /** {@inheritDoc} */
2615 public void animatingWindowLw(WindowState win,
2616 WindowManager.LayoutParams attrs) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002617 if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
2618 + win.isVisibleOrBehindKeyguardLw());
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002619 if (mTopFullscreenOpaqueWindowState == null &&
Dianne Hackborn01b02a72012-01-12 14:05:03 -08002620 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002621 if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
2622 mForceStatusBar = true;
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002623 }
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002624 if (attrs.type >= FIRST_APPLICATION_WINDOW
2625 && attrs.type <= LAST_APPLICATION_WINDOW
Dianne Hackborn6493e642010-10-01 13:06:30 -07002626 && attrs.x == 0 && attrs.y == 0
2627 && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
2628 && attrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
Dianne Hackborn5f3063e2010-03-10 16:01:58 -08002629 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win);
2630 mTopFullscreenOpaqueWindowState = win;
2631 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
2632 if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
2633 mHideLockScreen = true;
2634 }
2635 if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
2636 if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win);
2637 mDismissKeyguard = true;
2638 }
2639 if ((attrs.flags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
2640 mAllowLockscreenWhenOn = true;
2641 }
2642 }
2643 }
2644 }
2645
2646 /** {@inheritDoc} */
2647 public int finishAnimationLw() {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002648 int changes = 0;
Joe Onorato93056472010-09-10 10:30:46 -04002649 boolean topIsFullscreen = false;
Daniel Sandlere02d8082010-10-08 15:13:22 -04002650
2651 final WindowManager.LayoutParams lp = (mTopFullscreenOpaqueWindowState != null)
2652 ? mTopFullscreenOpaqueWindowState.getAttrs()
2653 : null;
2654
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002655 if (mStatusBar != null) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002656 if (DEBUG_LAYOUT) Log.i(TAG, "force=" + mForceStatusBar
Dianne Hackbornd70bc2f2009-10-06 23:25:51 -07002657 + " top=" + mTopFullscreenOpaqueWindowState);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002658 if (mForceStatusBar) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002659 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: forced");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002660 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002661 } else if (mTopFullscreenOpaqueWindowState != null) {
Joe Onorato93056472010-09-10 10:30:46 -04002662 if (localLOGV) {
2663 Log.d(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
2664 + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
2665 Log.d(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs()
2666 + " lp.flags=0x" + Integer.toHexString(lp.flags));
2667 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002668 topIsFullscreen = (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0
2669 || (mLastSystemUiFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
Joe Onorato93056472010-09-10 10:30:46 -04002670 // The subtle difference between the window for mTopFullscreenOpaqueWindowState
2671 // and mTopIsFullscreen is that that mTopIsFullscreen is set only if the window
2672 // has the FLAG_FULLSCREEN set. Not sure if there is another way that to be the
2673 // case though.
2674 if (topIsFullscreen) {
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002675 if (DEBUG_LAYOUT) Log.v(TAG, "** HIDING status bar");
2676 if (mStatusBar.hideLw(true)) {
2677 changes |= FINISH_LAYOUT_REDO_LAYOUT;
Daniel Sandler9c00d5b2011-09-13 14:04:26 -04002678
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002679 mHandler.post(new Runnable() { public void run() {
2680 if (mStatusBarService != null) {
2681 try {
2682 mStatusBarService.collapse();
2683 } catch (RemoteException ex) {}
2684 }
2685 }});
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07002686 } else if (DEBUG_LAYOUT) {
Daniel Sandler40427442010-07-16 11:44:52 -04002687 Log.v(TAG, "Preventing status bar from hiding by policy");
2688 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002689 } else {
Dianne Hackborn01b02a72012-01-12 14:05:03 -08002690 if (DEBUG_LAYOUT) Log.v(TAG, "** SHOWING status bar: top is not fullscreen");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002691 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002692 }
2693 }
2694 }
Daniel Sandlere02d8082010-10-08 15:13:22 -04002695
Joe Onorato644f9c32011-01-25 12:06:23 -08002696 mTopIsFullscreen = topIsFullscreen;
Daniel Sandlere02d8082010-10-08 15:13:22 -04002697
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002698 // Hide the key guard if a visible window explicitly specifies that it wants to be displayed
2699 // when the screen is locked
2700 if (mKeyguard != null) {
Joe Onorato93056472010-09-10 10:30:46 -04002701 if (localLOGV) Log.v(TAG, "finishAnimationLw::mHideKeyguard="+mHideLockScreen);
Dianne Hackborn05726582009-09-22 17:28:24 -07002702 if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
Dianne Hackborn08743722009-12-21 12:16:51 -08002703 if (mKeyguard.hideLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002704 changes |= FINISH_LAYOUT_REDO_LAYOUT
2705 | FINISH_LAYOUT_REDO_CONFIG
2706 | FINISH_LAYOUT_REDO_WALLPAPER;
2707 }
Dianne Hackborn05726582009-09-22 17:28:24 -07002708 if (mKeyguardMediator.isShowing()) {
Dianne Hackbornb446e972009-09-20 15:23:25 -07002709 mHandler.post(new Runnable() {
2710 public void run() {
Dianne Hackborn05726582009-09-22 17:28:24 -07002711 mKeyguardMediator.keyguardDone(false, false);
Dianne Hackbornb446e972009-09-20 15:23:25 -07002712 }
2713 });
2714 }
Dianne Hackborn05726582009-09-22 17:28:24 -07002715 } else if (mHideLockScreen) {
Dianne Hackborn08743722009-12-21 12:16:51 -08002716 if (mKeyguard.hideLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002717 changes |= FINISH_LAYOUT_REDO_LAYOUT
2718 | FINISH_LAYOUT_REDO_CONFIG
2719 | FINISH_LAYOUT_REDO_WALLPAPER;
2720 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05002721 mKeyguardMediator.setHidden(true);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002722 } else {
Dianne Hackborn08743722009-12-21 12:16:51 -08002723 if (mKeyguard.showLw(true)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002724 changes |= FINISH_LAYOUT_REDO_LAYOUT
2725 | FINISH_LAYOUT_REDO_CONFIG
2726 | FINISH_LAYOUT_REDO_WALLPAPER;
2727 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05002728 mKeyguardMediator.setHidden(false);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07002729 }
2730 }
Joe Onorato664644d2011-01-23 17:53:23 -08002731
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002732 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002733 // If the navigation bar has been hidden or shown, we need to do another
2734 // layout pass to update that window.
2735 changes |= FINISH_LAYOUT_REDO_LAYOUT;
2736 }
Joe Onorato664644d2011-01-23 17:53:23 -08002737
Mike Lockwood28569302010-01-28 11:54:40 -05002738 // update since mAllowLockscreenWhenOn might have changed
2739 updateLockScreenTimeout();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002740 return changes;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002741 }
2742
Dianne Hackborn08743722009-12-21 12:16:51 -08002743 public boolean allowAppAnimationsLw() {
2744 if (mKeyguard != null && mKeyguard.isVisibleLw()) {
2745 // If keyguard is currently visible, no reason to animate
2746 // behind it.
2747 return false;
2748 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002749 if (mStatusBar != null && mStatusBar.isVisibleLw()) {
2750 RectF rect = new RectF(mStatusBar.getShownFrameLw());
2751 for (int i=mStatusBarPanels.size()-1; i>=0; i--) {
2752 WindowState w = mStatusBarPanels.get(i);
2753 if (w.isVisibleLw()) {
2754 rect.union(w.getShownFrameLw());
Dianne Hackborn08743722009-12-21 12:16:51 -08002755 }
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002756 }
2757 final int insetw = mRestrictedScreenWidth/10;
2758 final int inseth = mRestrictedScreenHeight/10;
2759 if (rect.contains(insetw, inseth, mRestrictedScreenWidth-insetw,
2760 mRestrictedScreenHeight-inseth)) {
2761 // All of the status bar windows put together cover the
2762 // screen, so the app can't be seen. (Note this test doesn't
2763 // work if the rects of these windows are at odd offsets or
2764 // sizes, causing gaps in the rect union we have computed.)
2765 return false;
Dianne Hackborn08743722009-12-21 12:16:51 -08002766 }
2767 }
2768 return true;
2769 }
2770
Dianne Hackborndf89e652011-10-06 22:35:11 -07002771 public int focusChangedLw(WindowState lastFocus, WindowState newFocus) {
Joe Onorato664644d2011-01-23 17:53:23 -08002772 mFocusedWindow = newFocus;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002773 if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07002774 // If the navigation bar has been hidden or shown, we need to do another
2775 // layout pass to update that window.
2776 return FINISH_LAYOUT_REDO_LAYOUT;
2777 }
2778 return 0;
Joe Onorato664644d2011-01-23 17:53:23 -08002779 }
2780
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07002781 /** {@inheritDoc} */
Jeff Brown46b9ac02010-04-22 18:58:52 -07002782 public void notifyLidSwitchChanged(long whenNanos, boolean lidOpen) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002783 // do nothing if headless
Mike Lockwoodd747dc82011-09-13 16:28:22 -04002784 if (mHeadless) return;
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002785
Jeff Brown46b9ac02010-04-22 18:58:52 -07002786 // lid changed state
Jeff Brown4aed78b2011-01-14 17:36:55 -08002787 mLidOpen = lidOpen ? LID_OPEN : LID_CLOSED;
Jeff Brown01a98dd2011-09-20 15:08:29 -07002788 updateKeyboardVisibility();
2789
Jeff Brown4aed78b2011-01-14 17:36:55 -08002790 boolean awakeNow = mKeyguardMediator.doLidChangeTq(lidOpen);
Jeff Brown01a98dd2011-09-20 15:08:29 -07002791 updateRotation(true);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002792 if (awakeNow) {
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002793 // If the lid is opening and we don't have to keep the
Jeff Brown46b9ac02010-04-22 18:58:52 -07002794 // keyguard up, then we can turn on the screen
2795 // immediately.
2796 mKeyguardMediator.pokeWakelock();
2797 } else if (keyguardIsShowingTq()) {
Jeff Brown4aed78b2011-01-14 17:36:55 -08002798 if (lidOpen) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002799 // If we are opening the lid and not hiding the
2800 // keyguard, then we need to have it turn on the
2801 // screen once it is shown.
2802 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
Jeff Brown43150bf2011-11-08 20:22:03 -08002803 KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002804 }
2805 } else {
2806 // Light up the keyboard if we are sliding up.
Jeff Brown4aed78b2011-01-14 17:36:55 -08002807 if (lidOpen) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002808 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
2809 LocalPowerManager.BUTTON_EVENT);
2810 } else {
2811 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
2812 LocalPowerManager.OTHER_EVENT);
2813 }
2814 }
2815 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002816
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002817 void setHdmiPlugged(boolean plugged) {
2818 if (mHdmiPlugged != plugged) {
2819 mHdmiPlugged = plugged;
Dianne Hackbornf87d1962012-04-04 12:48:24 -07002820 if (plugged && mDisplay != null) {
2821 mExternalDisplayWidth = mDisplay.getRawExternalWidth();
2822 mExternalDisplayHeight = mDisplay.getRawExternalHeight();
2823 }
2824 updateRotation(true, true);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002825 Intent intent = new Intent(ACTION_HDMI_PLUGGED);
Joe Onoratodc100302011-01-11 17:07:41 -08002826 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
Dianne Hackbornad7fa7f2011-01-07 14:06:50 -08002827 intent.putExtra(EXTRA_HDMI_PLUGGED_STATE, plugged);
2828 mContext.sendStickyBroadcast(intent);
2829 }
2830 }
2831
Joe Onoratoea495d42011-04-06 11:41:11 -07002832 void initializeHdmiState() {
Joe Onorato7ba631f2011-05-04 15:28:00 -07002833 boolean plugged = false;
Joe Onoratoea495d42011-04-06 11:41:11 -07002834 // watch for HDMI plug messages if the hdmi switch exists
2835 if (new File("/sys/devices/virtual/switch/hdmi/state").exists()) {
2836 mHDMIObserver.startObserving("DEVPATH=/devices/virtual/switch/hdmi");
2837
Joe Onoratoea495d42011-04-06 11:41:11 -07002838 final String filename = "/sys/class/switch/hdmi/state";
2839 FileReader reader = null;
2840 try {
2841 reader = new FileReader(filename);
2842 char[] buf = new char[15];
2843 int n = reader.read(buf);
2844 if (n > 1) {
2845 plugged = 0 != Integer.parseInt(new String(buf, 0, n-1));
2846 }
2847 } catch (IOException ex) {
2848 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
2849 } catch (NumberFormatException ex) {
2850 Slog.w(TAG, "Couldn't read hdmi state from " + filename + ": " + ex);
2851 } finally {
2852 if (reader != null) {
2853 try {
2854 reader.close();
2855 } catch (IOException ex) {
2856 }
Joe Onoratodc100302011-01-11 17:07:41 -08002857 }
2858 }
2859 }
Joe Onorato7ba631f2011-05-04 15:28:00 -07002860 // This dance forces the code in setHdmiPlugged to run.
2861 // Always do this so the sticky intent is stuck (to false) if there is no hdmi.
2862 mHdmiPlugged = !plugged;
2863 setHdmiPlugged(!mHdmiPlugged);
Joe Onoratodc100302011-01-11 17:07:41 -08002864 }
2865
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002866 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002867 * @return Whether music is being played right now.
2868 */
2869 boolean isMusicActive() {
Eric Laurent413cb9d2009-07-17 11:52:43 -07002870 final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
2871 if (am == null) {
2872 Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002873 return false;
2874 }
Eric Laurent413cb9d2009-07-17 11:52:43 -07002875 return am.isMusicActive();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002876 }
2877
2878 /**
2879 * Tell the audio service to adjust the volume appropriate to the event.
2880 * @param keycode
2881 */
Mike Lockwooda53e3812009-09-25 10:51:39 -04002882 void handleVolumeKey(int stream, int keycode) {
Jeff Brown4d396052010-10-29 21:50:21 -07002883 IAudioService audioService = getAudioService();
2884 if (audioService == null) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002885 return;
2886 }
2887 try {
2888 // since audio is playing, we shouldn't have to hold a wake lock
2889 // during the call, but we do it as a precaution for the rare possibility
2890 // that the music stops right before we call this
Jeff Brownb0418da2010-11-01 15:24:01 -07002891 // TODO: Actually handle MUTE.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002892 mBroadcastWakeLock.acquire();
Jeff Brown4d396052010-10-29 21:50:21 -07002893 audioService.adjustStreamVolume(stream,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002894 keycode == KeyEvent.KEYCODE_VOLUME_UP
2895 ? AudioManager.ADJUST_RAISE
2896 : AudioManager.ADJUST_LOWER,
2897 0);
2898 } catch (RemoteException e) {
2899 Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e);
2900 } finally {
2901 mBroadcastWakeLock.release();
2902 }
2903 }
Jeff Brown4d396052010-10-29 21:50:21 -07002904
Dianne Hackbornc0e3f242011-08-19 14:19:10 -07002905 final Object mScreenshotLock = new Object();
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07002906 ServiceConnection mScreenshotConnection = null;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07002907
Jeff Brownd5bb82d2011-10-12 13:57:59 -07002908 final Runnable mScreenshotTimeout = new Runnable() {
2909 @Override public void run() {
2910 synchronized (mScreenshotLock) {
2911 if (mScreenshotConnection != null) {
2912 mContext.unbindService(mScreenshotConnection);
2913 mScreenshotConnection = null;
Dianne Hackbornfc8fa632011-08-17 16:20:47 -07002914 }
Winson Chung9112ec32011-06-27 13:15:32 -07002915 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07002916 }
2917 };
2918
2919 // Assume this is called from the Handler thread.
2920 private void takeScreenshot() {
2921 synchronized (mScreenshotLock) {
2922 if (mScreenshotConnection != null) {
2923 return;
2924 }
2925 ComponentName cn = new ComponentName("com.android.systemui",
2926 "com.android.systemui.screenshot.TakeScreenshotService");
2927 Intent intent = new Intent();
2928 intent.setComponent(cn);
2929 ServiceConnection conn = new ServiceConnection() {
2930 @Override
2931 public void onServiceConnected(ComponentName name, IBinder service) {
2932 synchronized (mScreenshotLock) {
2933 if (mScreenshotConnection != this) {
2934 return;
2935 }
2936 Messenger messenger = new Messenger(service);
2937 Message msg = Message.obtain(null, 1);
2938 final ServiceConnection myConn = this;
2939 Handler h = new Handler(mHandler.getLooper()) {
2940 @Override
2941 public void handleMessage(Message msg) {
2942 synchronized (mScreenshotLock) {
2943 if (mScreenshotConnection == myConn) {
2944 mContext.unbindService(mScreenshotConnection);
2945 mScreenshotConnection = null;
2946 mHandler.removeCallbacks(mScreenshotTimeout);
2947 }
2948 }
2949 }
2950 };
2951 msg.replyTo = new Messenger(h);
Winson Chunga63bb842011-10-17 10:26:28 -07002952 msg.arg1 = msg.arg2 = 0;
2953 if (mStatusBar != null && mStatusBar.isVisibleLw())
2954 msg.arg1 = 1;
2955 if (mNavigationBar != null && mNavigationBar.isVisibleLw())
2956 msg.arg2 = 1;
Jeff Brownd5bb82d2011-10-12 13:57:59 -07002957 try {
2958 messenger.send(msg);
2959 } catch (RemoteException e) {
2960 }
2961 }
2962 }
2963 @Override
2964 public void onServiceDisconnected(ComponentName name) {}
2965 };
2966 if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
2967 mScreenshotConnection = conn;
2968 mHandler.postDelayed(mScreenshotTimeout, 10000);
2969 }
2970 }
Winson Chung9112ec32011-06-27 13:15:32 -07002971 }
2972
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002973 /** {@inheritDoc} */
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002974 @Override
Jeff Brown1f245102010-11-18 20:53:46 -08002975 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
2976 final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
2977 final boolean canceled = event.isCanceled();
2978 final int keyCode = event.getKeyCode();
Jeff Browne20c9e02010-10-11 14:20:19 -07002979
Jeff Brown3122e442010-10-11 23:32:49 -07002980 final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
Jeff Brown3122e442010-10-11 23:32:49 -07002981
Mike Lockwoodc72b15f2009-11-28 20:58:22 -05002982 // If screen is off then we treat the case where the keyguard is open but hidden
2983 // the same as if it were open and in front.
2984 // This will prevent any keys other than the power button from waking the screen
2985 // when the keyguard is hidden by another activity.
Mike Lockwood3a74bd32011-08-12 13:55:22 -07002986 final boolean keyguardActive = (mKeyguardMediator == null ? false :
2987 (isScreenOn ?
2988 mKeyguardMediator.isShowingAndNotHidden() :
2989 mKeyguardMediator.isShowing()));
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002990
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07002991 if (!mSystemBooted) {
2992 // If we have not yet booted, don't let key events do anything.
2993 return 0;
2994 }
2995
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002996 if (false) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07002997 Log.d(TAG, "interceptKeyTq keycode=" + keyCode
2998 + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002999 }
3000
Jeff Brown98392ef2011-09-12 18:24:59 -07003001 if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
3002 && event.getRepeatCount() == 0) {
Jeff Brown4d396052010-10-29 21:50:21 -07003003 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
3004 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003005
Jeff Brownbc072da2011-11-15 12:56:55 -08003006 if (keyCode == KeyEvent.KEYCODE_POWER) {
3007 policyFlags |= WindowManagerPolicy.FLAG_WAKE;
3008 }
3009 final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
3010 | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
3011
Jeff Brown4d396052010-10-29 21:50:21 -07003012 // Basic policy based on screen state and keyguard.
3013 // FIXME: This policy isn't quite correct. We shouldn't care whether the screen
3014 // is on or off, really. We should care about whether the device is in an
3015 // interactive state or is in suspend pretending to be "off".
3016 // The primary screen might be turned off due to proximity sensor or
3017 // because we are presenting media on an auxiliary screen or remotely controlling
3018 // the device some other way (which is why we have an exemption here for injected
3019 // events).
3020 int result;
Mike Lockwoodd747dc82011-09-13 16:28:22 -04003021 if ((isScreenOn && !mHeadless) || (isInjected && !isWakeKey)) {
Jeff Brown4d396052010-10-29 21:50:21 -07003022 // When the screen is on or if the key is injected pass the key to the application.
3023 result = ACTION_PASS_TO_USER;
3024 } else {
3025 // When the screen is off and the key is not injected, determine whether
3026 // to wake the device but don't pass the key to the application.
3027 result = 0;
Jeff Brown4d396052010-10-29 21:50:21 -07003028 if (down && isWakeKey) {
3029 if (keyguardActive) {
3030 // If the keyguard is showing, let it decide what to do with the wake key.
Jeff Brown43150bf2011-11-08 20:22:03 -08003031 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(keyCode,
3032 mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
Jeff Brown4d396052010-10-29 21:50:21 -07003033 } else {
3034 // Otherwise, wake the device ourselves.
3035 result |= ACTION_POKE_USER_ACTIVITY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003036 }
3037 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003038 }
3039
Jeff Brown4d396052010-10-29 21:50:21 -07003040 // Handle special keys.
3041 switch (keyCode) {
3042 case KeyEvent.KEYCODE_VOLUME_DOWN:
Jeff Brownb0418da2010-11-01 15:24:01 -07003043 case KeyEvent.KEYCODE_VOLUME_UP:
3044 case KeyEvent.KEYCODE_VOLUME_MUTE: {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003045 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
3046 if (down) {
3047 if (isScreenOn && !mVolumeDownKeyTriggered
3048 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3049 mVolumeDownKeyTriggered = true;
3050 mVolumeDownKeyTime = event.getDownTime();
3051 mVolumeDownKeyConsumedByScreenshotChord = false;
3052 cancelPendingPowerKeyAction();
3053 interceptScreenshotChord();
3054 }
3055 } else {
3056 mVolumeDownKeyTriggered = false;
3057 cancelPendingScreenshotChordAction();
3058 }
3059 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
3060 if (down) {
3061 if (isScreenOn && !mVolumeUpKeyTriggered
3062 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3063 mVolumeUpKeyTriggered = true;
3064 cancelPendingPowerKeyAction();
3065 cancelPendingScreenshotChordAction();
3066 }
3067 } else {
3068 mVolumeUpKeyTriggered = false;
3069 cancelPendingScreenshotChordAction();
3070 }
3071 }
Jeff Brown4d396052010-10-29 21:50:21 -07003072 if (down) {
3073 ITelephony telephonyService = getTelephonyService();
3074 if (telephonyService != null) {
3075 try {
3076 if (telephonyService.isRinging()) {
3077 // If an incoming call is ringing, either VOLUME key means
3078 // "silence ringer". We handle these keys here, rather than
3079 // in the InCallScreen, to make sure we'll respond to them
3080 // even if the InCallScreen hasn't come to the foreground yet.
3081 // Look for the DOWN event here, to agree with the "fallback"
3082 // behavior in the InCallScreen.
3083 Log.i(TAG, "interceptKeyBeforeQueueing:"
3084 + " VOLUME key-down while ringing: Silence ringer!");
3085
3086 // Silence the ringer. (It's safe to call this
3087 // even if the ringer has already been silenced.)
3088 telephonyService.silenceRinger();
3089
3090 // And *don't* pass this key thru to the current activity
3091 // (which is probably the InCallScreen.)
3092 result &= ~ACTION_PASS_TO_USER;
3093 break;
3094 }
3095 if (telephonyService.isOffhook()
3096 && (result & ACTION_PASS_TO_USER) == 0) {
3097 // If we are in call but we decided not to pass the key to
3098 // the application, handle the volume change here.
3099 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, keyCode);
3100 break;
3101 }
3102 } catch (RemoteException ex) {
3103 Log.w(TAG, "ITelephony threw RemoteException", ex);
3104 }
3105 }
3106
3107 if (isMusicActive() && (result & ACTION_PASS_TO_USER) == 0) {
3108 // If music is playing but we decided not to pass the key to the
3109 // application, handle the volume change here.
3110 handleVolumeKey(AudioManager.STREAM_MUSIC, keyCode);
3111 break;
3112 }
3113 }
3114 break;
3115 }
3116
3117 case KeyEvent.KEYCODE_ENDCALL: {
3118 result &= ~ACTION_PASS_TO_USER;
3119 if (down) {
3120 ITelephony telephonyService = getTelephonyService();
3121 boolean hungUp = false;
3122 if (telephonyService != null) {
3123 try {
3124 hungUp = telephonyService.endCall();
3125 } catch (RemoteException ex) {
3126 Log.w(TAG, "ITelephony threw RemoteException", ex);
3127 }
3128 }
3129 interceptPowerKeyDown(!isScreenOn || hungUp);
3130 } else {
3131 if (interceptPowerKeyUp(canceled)) {
3132 if ((mEndcallBehavior
3133 & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
3134 if (goHome()) {
3135 break;
Dianne Hackborn0041e972009-07-24 17:14:43 -07003136 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003137 }
Jeff Brown4d396052010-10-29 21:50:21 -07003138 if ((mEndcallBehavior
3139 & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
3140 result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
3141 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003142 }
Jeff Brown4d396052010-10-29 21:50:21 -07003143 }
3144 break;
3145 }
3146
3147 case KeyEvent.KEYCODE_POWER: {
3148 result &= ~ACTION_PASS_TO_USER;
3149 if (down) {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003150 if (isScreenOn && !mPowerKeyTriggered
3151 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
3152 mPowerKeyTriggered = true;
3153 mPowerKeyTime = event.getDownTime();
3154 interceptScreenshotChord();
Winson Chung9112ec32011-06-27 13:15:32 -07003155 }
Winson Chung9112ec32011-06-27 13:15:32 -07003156
Jeff Brown4d396052010-10-29 21:50:21 -07003157 ITelephony telephonyService = getTelephonyService();
3158 boolean hungUp = false;
3159 if (telephonyService != null) {
3160 try {
3161 if (telephonyService.isRinging()) {
3162 // Pressing Power while there's a ringing incoming
3163 // call should silence the ringer.
3164 telephonyService.silenceRinger();
3165 } else if ((mIncallPowerBehavior
3166 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
3167 && telephonyService.isOffhook()) {
3168 // Otherwise, if "Power button ends call" is enabled,
3169 // the Power button will hang up any current active call.
3170 hungUp = telephonyService.endCall();
3171 }
3172 } catch (RemoteException ex) {
3173 Log.w(TAG, "ITelephony threw RemoteException", ex);
3174 }
3175 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003176 interceptPowerKeyDown(!isScreenOn || hungUp
3177 || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003178 } else {
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003179 mPowerKeyTriggered = false;
3180 cancelPendingScreenshotChordAction();
3181 if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
Jeff Brown4d396052010-10-29 21:50:21 -07003182 result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003183 }
Jeff Brownd5bb82d2011-10-12 13:57:59 -07003184 mPendingPowerKeyUpCanceled = false;
Jeff Brown4d396052010-10-29 21:50:21 -07003185 }
3186 break;
3187 }
3188
3189 case KeyEvent.KEYCODE_MEDIA_PLAY:
3190 case KeyEvent.KEYCODE_MEDIA_PAUSE:
3191 case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
3192 if (down) {
3193 ITelephony telephonyService = getTelephonyService();
3194 if (telephonyService != null) {
3195 try {
3196 if (!telephonyService.isIdle()) {
3197 // Suppress PLAY/PAUSE toggle when phone is ringing or in-call
3198 // to avoid music playback.
3199 break;
3200 }
3201 } catch (RemoteException ex) {
3202 Log.w(TAG, "ITelephony threw RemoteException", ex);
Jeff Brown3122e442010-10-11 23:32:49 -07003203 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003204 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003205 }
Jeff Brown4d396052010-10-29 21:50:21 -07003206 case KeyEvent.KEYCODE_HEADSETHOOK:
3207 case KeyEvent.KEYCODE_MUTE:
3208 case KeyEvent.KEYCODE_MEDIA_STOP:
3209 case KeyEvent.KEYCODE_MEDIA_NEXT:
3210 case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
3211 case KeyEvent.KEYCODE_MEDIA_REWIND:
3212 case KeyEvent.KEYCODE_MEDIA_RECORD:
3213 case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD: {
3214 if ((result & ACTION_PASS_TO_USER) == 0) {
3215 // Only do this if we would otherwise not pass it to the user. In that
3216 // case, the PhoneWindow class will do the same thing, except it will
3217 // only do it if the showing app doesn't process the key on its own.
Jeff Brown4d396052010-10-29 21:50:21 -07003218 mBroadcastWakeLock.acquire();
Jeff Brown1f245102010-11-18 20:53:46 -08003219 mHandler.post(new PassHeadsetKey(new KeyEvent(event)));
Jeff Brown4d396052010-10-29 21:50:21 -07003220 }
3221 break;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003222 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003223
Jeff Brown4d396052010-10-29 21:50:21 -07003224 case KeyEvent.KEYCODE_CALL: {
3225 if (down) {
3226 ITelephony telephonyService = getTelephonyService();
3227 if (telephonyService != null) {
3228 try {
3229 if (telephonyService.isRinging()) {
3230 Log.i(TAG, "interceptKeyBeforeQueueing:"
3231 + " CALL key-down while ringing: Answer the call!");
3232 telephonyService.answerRingingCall();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003233
Jeff Brown4d396052010-10-29 21:50:21 -07003234 // And *don't* pass this key thru to the current activity
3235 // (which is presumably the InCallScreen.)
3236 result &= ~ACTION_PASS_TO_USER;
3237 }
3238 } catch (RemoteException ex) {
3239 Log.w(TAG, "ITelephony threw RemoteException", ex);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003240 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003241 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07003242 }
Jeff Brown4d396052010-10-29 21:50:21 -07003243 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003244 }
3245 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003246 return result;
3247 }
3248
Jeff Brown56194eb2011-03-02 19:23:13 -08003249 /** {@inheritDoc} */
3250 @Override
3251 public int interceptMotionBeforeQueueingWhenScreenOff(int policyFlags) {
3252 int result = 0;
3253
3254 final boolean isWakeMotion = (policyFlags
3255 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
3256 if (isWakeMotion) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003257 if (mKeyguardMediator != null && mKeyguardMediator.isShowing()) {
Jeff Brown56194eb2011-03-02 19:23:13 -08003258 // If the keyguard is showing, let it decide what to do with the wake motion.
3259 mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
3260 } else {
3261 // Otherwise, wake the device ourselves.
3262 result |= ACTION_POKE_USER_ACTIVITY;
3263 }
3264 }
3265 return result;
3266 }
3267
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003268 class PassHeadsetKey implements Runnable {
3269 KeyEvent mKeyEvent;
3270
3271 PassHeadsetKey(KeyEvent keyEvent) {
3272 mKeyEvent = keyEvent;
3273 }
3274
3275 public void run() {
3276 if (ActivityManagerNative.isSystemReady()) {
3277 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
3278 intent.putExtra(Intent.EXTRA_KEY_EVENT, mKeyEvent);
3279 mContext.sendOrderedBroadcast(intent, null, mBroadcastDone,
3280 mHandler, Activity.RESULT_OK, null, null);
3281 }
3282 }
3283 }
3284
3285 BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
3286 public void onReceive(Context context, Intent intent) {
3287 mBroadcastWakeLock.release();
3288 }
3289 };
Mike Lockwood1753f7f2009-08-24 14:49:07 -07003290
3291 BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
3292 public void onReceive(Context context, Intent intent) {
Dianne Hackborn867ab6472010-04-29 13:28:56 -07003293 if (Intent.ACTION_DOCK_EVENT.equals(intent.getAction())) {
3294 mDockMode = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
3295 Intent.EXTRA_DOCK_STATE_UNDOCKED);
3296 } else {
3297 try {
3298 IUiModeManager uiModeService = IUiModeManager.Stub.asInterface(
3299 ServiceManager.getService(Context.UI_MODE_SERVICE));
3300 mUiMode = uiModeService.getCurrentModeType();
3301 } catch (RemoteException e) {
3302 }
Dianne Hackborn80fa1662009-10-07 14:02:10 -07003303 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003304 updateRotation(true);
Mike Lockwoode9867d22009-09-20 01:59:02 -04003305 updateOrientationListenerLp();
Mike Lockwood1753f7f2009-08-24 14:49:07 -07003306 }
3307 };
3308
Daniel Sandler7e37df52011-11-16 22:08:23 -08003309 BroadcastReceiver mPowerReceiver = new BroadcastReceiver() {
3310 public void onReceive(Context context, Intent intent) {
3311 if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
3312 mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
3313 if (localLOGV) Log.v(TAG, "BATTERY_CHANGED: " + intent + " plugged=" + mPluggedIn);
3314 }
3315 }
3316 };
3317
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003318 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003319 public void screenTurnedOff(int why) {
Dianne Hackborn74489012009-03-24 20:50:09 -07003320 EventLog.writeEvent(70000, 0);
The Android Open Source Project0727d222009-03-11 12:11:58 -07003321 synchronized (mLock) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003322 mScreenOnEarly = false;
3323 mScreenOnFully = false;
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003324 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003325 if (mKeyguardMediator != null) {
3326 mKeyguardMediator.onScreenTurnedOff(why);
3327 }
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003328 synchronized (mLock) {
The Android Open Source Project0727d222009-03-11 12:11:58 -07003329 updateOrientationListenerLp();
Mike Lockwood28569302010-01-28 11:54:40 -05003330 updateLockScreenTimeout();
The Android Open Source Project0727d222009-03-11 12:11:58 -07003331 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003332 }
3333
3334 /** {@inheritDoc} */
Dianne Hackborn38e29a62011-09-18 14:43:08 -07003335 public void screenTurningOn(final ScreenOnListener screenOnListener) {
Dianne Hackborn74489012009-03-24 20:50:09 -07003336 EventLog.writeEvent(70000, 1);
Dianne Hackborn40011092011-09-22 13:37:48 -07003337 if (false) {
3338 RuntimeException here = new RuntimeException("here");
3339 here.fillInStackTrace();
3340 Slog.i(TAG, "Screen turning on...", here);
3341 }
3342 if (screenOnListener != null) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003343 if (mKeyguardMediator != null) {
3344 mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
3345 @Override public void onShown(IBinder windowToken) {
3346 if (windowToken != null) {
3347 try {
3348 mWindowManager.waitForWindowDrawn(windowToken,
3349 new IRemoteCallback.Stub() {
3350 @Override public void sendResult(Bundle data) {
3351 Slog.i(TAG, "Lock screen displayed!");
3352 screenOnListener.onScreenOn();
3353 synchronized (mLock) {
3354 mScreenOnFully = true;
3355 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003356 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003357 });
3358 } catch (RemoteException e) {
3359 }
3360 } else {
3361 Slog.i(TAG, "No lock screen!");
3362 screenOnListener.onScreenOn();
3363 synchronized (mLock) {
3364 mScreenOnFully = true;
3365 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003366 }
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003367 }
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003368 });
3369 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003370 } else {
3371 synchronized (mLock) {
3372 mScreenOnFully = true;
Dianne Hackborn38e29a62011-09-18 14:43:08 -07003373 }
Dianne Hackborn40011092011-09-22 13:37:48 -07003374 }
The Android Open Source Project0727d222009-03-11 12:11:58 -07003375 synchronized (mLock) {
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003376 mScreenOnEarly = true;
The Android Open Source Project0727d222009-03-11 12:11:58 -07003377 updateOrientationListenerLp();
Mike Lockwood28569302010-01-28 11:54:40 -05003378 updateLockScreenTimeout();
The Android Open Source Project0727d222009-03-11 12:11:58 -07003379 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003380 }
3381
3382 /** {@inheritDoc} */
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07003383 public boolean isScreenOnEarly() {
3384 return mScreenOnEarly;
3385 }
3386
3387 /** {@inheritDoc} */
3388 public boolean isScreenOnFully() {
3389 return mScreenOnFully;
Dianne Hackborn08743722009-12-21 12:16:51 -08003390 }
3391
3392 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003393 public void enableKeyguard(boolean enabled) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003394 if (mKeyguardMediator != null) {
3395 mKeyguardMediator.setKeyguardEnabled(enabled);
3396 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003397 }
3398
3399 /** {@inheritDoc} */
3400 public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003401 if (mKeyguardMediator != null) {
3402 mKeyguardMediator.verifyUnlock(callback);
3403 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003404 }
3405
Mike Lockwoodf7913302009-11-28 22:27:10 -05003406 private boolean keyguardIsShowingTq() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003407 if (mKeyguardMediator == null) return false;
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08003408 return mKeyguardMediator.isShowingAndNotHidden();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003409 }
3410
Mike Lockwood520d8bc2011-02-18 13:23:13 -05003411
3412 /** {@inheritDoc} */
3413 public boolean isKeyguardLocked() {
3414 return keyguardOn();
3415 }
3416
3417 /** {@inheritDoc} */
3418 public boolean isKeyguardSecure() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003419 if (mKeyguardMediator == null) return false;
Mike Lockwood520d8bc2011-02-18 13:23:13 -05003420 return mKeyguardMediator.isSecure();
3421 }
3422
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003423 /** {@inheritDoc} */
3424 public boolean inKeyguardRestrictedKeyInputMode() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003425 if (mKeyguardMediator == null) return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003426 return mKeyguardMediator.isInputRestricted();
3427 }
3428
Dianne Hackborn90c52de2011-09-23 12:57:44 -07003429 public void dismissKeyguardLw() {
3430 if (!mKeyguardMediator.isSecure()) {
3431 if (mKeyguardMediator.isShowing()) {
3432 mHandler.post(new Runnable() {
3433 public void run() {
3434 mKeyguardMediator.keyguardDone(false, true);
3435 }
3436 });
3437 }
3438 }
3439 }
3440
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003441 void sendCloseSystemWindows() {
3442 sendCloseSystemWindows(mContext, null);
3443 }
3444
3445 void sendCloseSystemWindows(String reason) {
3446 sendCloseSystemWindows(mContext, reason);
3447 }
3448
3449 static void sendCloseSystemWindows(Context context, String reason) {
3450 if (ActivityManagerNative.isSystemReady()) {
Dianne Hackborn94a679d2009-07-28 17:51:07 -07003451 try {
3452 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
3453 } catch (RemoteException e) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003454 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003455 }
3456 }
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07003457
Jeff Brown01a98dd2011-09-20 15:08:29 -07003458 @Override
3459 public int rotationForOrientationLw(int orientation, int lastRotation) {
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003460 if (false) {
3461 Slog.v(TAG, "rotationForOrientationLw(orient="
3462 + orientation + ", last=" + lastRotation
3463 + "); user=" + mUserRotation + " "
3464 + ((mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED)
3465 ? "USER_ROTATION_LOCKED" : "")
3466 );
3467 }
3468
The Android Open Source Project0727d222009-03-11 12:11:58 -07003469 synchronized (mLock) {
Jeff Brownc0347aa2011-09-23 17:26:09 -07003470 int sensorRotation = mOrientationListener.getProposedRotation(); // may be -1
3471 if (sensorRotation < 0) {
3472 sensorRotation = lastRotation;
3473 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003474
Jeff Browndec6cf42011-11-15 14:08:20 -08003475 final int preferredRotation;
Jeff Browneb3e4b92011-12-06 19:54:24 -08003476 if (mLidOpen == LID_OPEN && mLidOpenRotation >= 0) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003477 // Ignore sensor when lid switch is open and rotation is forced.
3478 preferredRotation = mLidOpenRotation;
3479 } else if (mDockMode == Intent.EXTRA_DOCK_STATE_CAR
Jeff Brownc0347aa2011-09-23 17:26:09 -07003480 && (mCarDockEnablesAccelerometer || mCarDockRotation >= 0)) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003481 // Ignore sensor when in car dock unless explicitly enabled.
3482 // This case can override the behavior of NOSENSOR, and can also
3483 // enable 180 degree rotation while docked.
Jeff Brownc0347aa2011-09-23 17:26:09 -07003484 preferredRotation = mCarDockEnablesAccelerometer
Jeff Brown01a98dd2011-09-20 15:08:29 -07003485 ? sensorRotation : mCarDockRotation;
Jeff Brown1a693182011-11-08 14:44:16 -08003486 } else if ((mDockMode == Intent.EXTRA_DOCK_STATE_DESK
3487 || mDockMode == Intent.EXTRA_DOCK_STATE_LE_DESK
3488 || mDockMode == Intent.EXTRA_DOCK_STATE_HE_DESK)
Jeff Brownc0347aa2011-09-23 17:26:09 -07003489 && (mDeskDockEnablesAccelerometer || mDeskDockRotation >= 0)) {
Jeff Brown01a98dd2011-09-20 15:08:29 -07003490 // Ignore sensor when in desk dock unless explicitly enabled.
3491 // This case can override the behavior of NOSENSOR, and can also
3492 // enable 180 degree rotation while docked.
Jeff Brownc0347aa2011-09-23 17:26:09 -07003493 preferredRotation = mDeskDockEnablesAccelerometer
Jeff Brown01a98dd2011-09-20 15:08:29 -07003494 ? sensorRotation : mDeskDockRotation;
Jeff Browneb3e4b92011-12-06 19:54:24 -08003495 } else if (mHdmiPlugged) {
3496 // Ignore sensor when plugged into HDMI.
3497 // Note that the dock orientation overrides the HDMI orientation.
3498 preferredRotation = mHdmiRotation;
Jeff Brown4dfce202011-10-05 12:00:10 -07003499 } else if ((mAccelerometerDefault != 0 /* implies not rotation locked */
Jeff Brown01a98dd2011-09-20 15:08:29 -07003500 && (orientation == ActivityInfo.SCREEN_ORIENTATION_USER
3501 || orientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED))
3502 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR
3503 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
3504 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
3505 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
3506 // Otherwise, use sensor only if requested by the application or enabled
3507 // by default for USER or UNSPECIFIED modes. Does not apply to NOSENSOR.
Jeff Brownd3187e32011-09-21 19:26:44 -07003508 if (mAllowAllRotations < 0) {
3509 // Can't read this during init() because the context doesn't
3510 // have display metrics at that time so we cannot determine
3511 // tablet vs. phone then.
3512 mAllowAllRotations = mContext.getResources().getBoolean(
3513 com.android.internal.R.bool.config_allowAllRotations) ? 1 : 0;
3514 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003515 if (sensorRotation != Surface.ROTATION_180
Jeff Brownd3187e32011-09-21 19:26:44 -07003516 || mAllowAllRotations == 1
Jeff Brown01a98dd2011-09-20 15:08:29 -07003517 || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR) {
3518 preferredRotation = sensorRotation;
3519 } else {
3520 preferredRotation = lastRotation;
3521 }
Jeff Brown4dfce202011-10-05 12:00:10 -07003522 } else if (mUserRotationMode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
3523 // Apply rotation lock.
3524 preferredRotation = mUserRotation;
Jeff Browndec6cf42011-11-15 14:08:20 -08003525 } else {
3526 // No overriding preference.
3527 // We will do exactly what the application asked us to do.
3528 preferredRotation = -1;
Jeff Brown01a98dd2011-09-20 15:08:29 -07003529 }
3530
Dianne Hackborne5439f22010-10-02 16:53:50 -07003531 switch (orientation) {
3532 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
Jeff Browndec6cf42011-11-15 14:08:20 -08003533 // Return portrait unless overridden.
3534 if (isAnyPortrait(preferredRotation)) {
3535 return preferredRotation;
3536 }
Dianne Hackborne5439f22010-10-02 16:53:50 -07003537 return mPortraitRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003538
Jeff Brown01a98dd2011-09-20 15:08:29 -07003539 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
Jeff Browndec6cf42011-11-15 14:08:20 -08003540 // Return landscape unless overridden.
3541 if (isLandscapeOrSeascape(preferredRotation)) {
3542 return preferredRotation;
3543 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003544 return mLandscapeRotation;
3545
3546 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
Jeff Browndec6cf42011-11-15 14:08:20 -08003547 // Return reverse portrait unless overridden.
3548 if (isAnyPortrait(preferredRotation)) {
3549 return preferredRotation;
3550 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003551 return mUpsideDownRotation;
3552
3553 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
Jeff Browndec6cf42011-11-15 14:08:20 -08003554 // Return seascape unless overridden.
3555 if (isLandscapeOrSeascape(preferredRotation)) {
3556 return preferredRotation;
3557 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003558 return mSeascapeRotation;
3559
3560 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
3561 // Return either landscape rotation.
3562 if (isLandscapeOrSeascape(preferredRotation)) {
3563 return preferredRotation;
3564 }
3565 if (isLandscapeOrSeascape(lastRotation)) {
Jeff Brown4519f072011-01-23 13:16:01 -08003566 return lastRotation;
3567 }
Jeff Brown01a98dd2011-09-20 15:08:29 -07003568 return mLandscapeRotation;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003569
Jeff Brown01a98dd2011-09-20 15:08:29 -07003570 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
3571 // Return either portrait rotation.
3572 if (isAnyPortrait(preferredRotation)) {
3573 return preferredRotation;
3574 }
3575 if (isAnyPortrait(lastRotation)) {
3576 return lastRotation;
3577 }
3578 return mPortraitRotation;
3579
3580 default:
Jeff Brown4dfce202011-10-05 12:00:10 -07003581 // For USER, UNSPECIFIED, NOSENSOR, SENSOR and FULL_SENSOR,
3582 // just return the preferred orientation we already calculated.
Jeff Brown01a98dd2011-09-20 15:08:29 -07003583 if (preferredRotation >= 0) {
3584 return preferredRotation;
3585 }
Dianne Hackborndacea8c2011-04-21 17:26:39 -07003586 return Surface.ROTATION_0;
Daniel Sandlere7e5ac22011-02-22 16:10:21 -05003587 }
3588 }
Steve Howarda7bfe6a2010-09-23 16:47:49 -07003589 }
3590
Jeff Brown01a98dd2011-09-20 15:08:29 -07003591 @Override
3592 public boolean rotationHasCompatibleMetricsLw(int orientation, int rotation) {
3593 switch (orientation) {
3594 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
3595 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT:
3596 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT:
3597 return isAnyPortrait(rotation);
3598
3599 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
3600 case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE:
3601 case ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE:
3602 return isLandscapeOrSeascape(rotation);
3603
3604 default:
3605 return true;
3606 }
Steve Howarda7bfe6a2010-09-23 16:47:49 -07003607 }
3608
Jeff Brownc0347aa2011-09-23 17:26:09 -07003609 @Override
3610 public void setRotationLw(int rotation) {
3611 mOrientationListener.setCurrentRotation(rotation);
3612 }
3613
Jeff Brown01a98dd2011-09-20 15:08:29 -07003614 private boolean isLandscapeOrSeascape(int rotation) {
3615 return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003616 }
3617
Jeff Brown01a98dd2011-09-20 15:08:29 -07003618 private boolean isAnyPortrait(int rotation) {
3619 return rotation == mPortraitRotation || rotation == mUpsideDownRotation;
Dianne Hackborne5439f22010-10-02 16:53:50 -07003620 }
3621
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003622
3623 // User rotation: to be used when all else fails in assigning an orientation to the device
3624 public void setUserRotationMode(int mode, int rot) {
3625 ContentResolver res = mContext.getContentResolver();
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003626
3627 // mUserRotationMode and mUserRotation will be assigned by the content observer
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003628 if (mode == WindowManagerPolicy.USER_ROTATION_LOCKED) {
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003629 Settings.System.putInt(res,
3630 Settings.System.USER_ROTATION,
3631 rot);
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05003632 Settings.System.putInt(res,
3633 Settings.System.ACCELEROMETER_ROTATION,
3634 0);
Daniel Sandlerb73617d2010-08-17 00:41:00 -04003635 } else {
3636 Settings.System.putInt(res,
3637 Settings.System.ACCELEROMETER_ROTATION,
3638 1);
3639 }
3640 }
3641
Jeff Brownac143512012-04-05 18:57:33 -07003642 public void setSafeMode(boolean safeMode) {
3643 mSafeMode = safeMode;
3644 performHapticFeedbackLw(null, safeMode
3645 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
3646 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003647 }
3648
Dianne Hackborn181ceb52009-08-27 22:16:40 -07003649 static long[] getLongIntArray(Resources r, int resid) {
3650 int[] ar = r.getIntArray(resid);
3651 if (ar == null) {
3652 return null;
3653 }
3654 long[] out = new long[ar.length];
3655 for (int i=0; i<ar.length; i++) {
3656 out[i] = ar[i];
3657 }
3658 return out;
3659 }
3660
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003661 /** {@inheritDoc} */
3662 public void systemReady() {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003663 if (mKeyguardMediator != null) {
3664 // tell the keyguard
3665 mKeyguardMediator.onSystemReady();
3666 }
Dianne Hackbornb1a79802009-09-29 15:18:31 -07003667 synchronized (mLock) {
3668 updateOrientationListenerLp();
Dianne Hackbornc777e072010-02-12 13:07:59 -08003669 mSystemReady = true;
3670 mHandler.post(new Runnable() {
3671 public void run() {
3672 updateSettings();
3673 }
3674 });
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003675 }
3676 }
Dianne Hackborn661cd522011-08-22 00:26:20 -07003677
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07003678 /** {@inheritDoc} */
3679 public void systemBooted() {
3680 synchronized (mLock) {
3681 mSystemBooted = true;
3682 }
3683 }
3684
Dianne Hackborn661cd522011-08-22 00:26:20 -07003685 ProgressDialog mBootMsgDialog = null;
3686
3687 /** {@inheritDoc} */
3688 public void showBootMessage(final CharSequence msg, final boolean always) {
Mike Lockwoodaa5bf142011-09-21 13:03:40 -04003689 if (mHeadless) return;
Dianne Hackborn661cd522011-08-22 00:26:20 -07003690 mHandler.post(new Runnable() {
3691 @Override public void run() {
3692 if (mBootMsgDialog == null) {
Dianne Hackborn295e3c22011-08-25 13:19:08 -07003693 mBootMsgDialog = new ProgressDialog(mContext) {
3694 // This dialog will consume all events coming in to
3695 // it, to avoid it trying to do things too early in boot.
3696 @Override public boolean dispatchKeyEvent(KeyEvent event) {
3697 return true;
3698 }
3699 @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) {
3700 return true;
3701 }
3702 @Override public boolean dispatchTouchEvent(MotionEvent ev) {
3703 return true;
3704 }
3705 @Override public boolean dispatchTrackballEvent(MotionEvent ev) {
3706 return true;
3707 }
3708 @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) {
3709 return true;
3710 }
3711 @Override public boolean dispatchPopulateAccessibilityEvent(
3712 AccessibilityEvent event) {
3713 return true;
3714 }
3715 };
Dianne Hackborn661cd522011-08-22 00:26:20 -07003716 mBootMsgDialog.setTitle(R.string.android_upgrading_title);
3717 mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
3718 mBootMsgDialog.setIndeterminate(true);
3719 mBootMsgDialog.getWindow().setType(
Dianne Hackborn29aae6f2011-08-18 18:30:09 -07003720 WindowManager.LayoutParams.TYPE_BOOT_PROGRESS);
Dianne Hackborn661cd522011-08-22 00:26:20 -07003721 mBootMsgDialog.getWindow().addFlags(
3722 WindowManager.LayoutParams.FLAG_DIM_BEHIND
3723 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
3724 mBootMsgDialog.getWindow().setDimAmount(1);
Dianne Hackbornd9efb952011-12-07 14:56:51 -08003725 WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes();
3726 lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
3727 mBootMsgDialog.getWindow().setAttributes(lp);
Dianne Hackborn661cd522011-08-22 00:26:20 -07003728 mBootMsgDialog.setCancelable(false);
3729 mBootMsgDialog.show();
3730 }
3731 mBootMsgDialog.setMessage(msg);
3732 }
3733 });
3734 }
3735
3736 /** {@inheritDoc} */
3737 public void hideBootMessages() {
3738 mHandler.post(new Runnable() {
3739 @Override public void run() {
3740 if (mBootMsgDialog != null) {
3741 mBootMsgDialog.dismiss();
3742 mBootMsgDialog = null;
3743 }
3744 }
3745 });
3746 }
3747
Mike Lockwood28569302010-01-28 11:54:40 -05003748 /** {@inheritDoc} */
3749 public void userActivity() {
Dianne Hackborndf89e652011-10-06 22:35:11 -07003750 // ***************************************
3751 // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
3752 // ***************************************
3753 // THIS IS CALLED FROM DEEP IN THE POWER MANAGER
3754 // WITH ITS LOCKS HELD.
3755 //
3756 // This code must be VERY careful about the locks
3757 // it acquires.
3758 // In fact, the current code acquires way too many,
3759 // and probably has lurking deadlocks.
3760
Mike Lockwood28569302010-01-28 11:54:40 -05003761 synchronized (mScreenLockTimeout) {
3762 if (mLockScreenTimerActive) {
3763 // reset the timer
3764 mHandler.removeCallbacks(mScreenLockTimeout);
3765 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
3766 }
3767 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003768 }
3769
Daniel Sandler7d276c32012-01-30 14:33:52 -05003770 private IDreamManager getDreamManager() {
3771 if (!mScreenSaverFeatureAvailable) {
3772 return null;
3773 }
3774
3775 IDreamManager sandman = IDreamManager.Stub.asInterface(
3776 ServiceManager.checkService("dreams"));
3777 if (sandman == null) {
3778 Log.w(TAG, "Unable to find IDreamManager");
3779 }
3780 return sandman;
3781 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003782
Daniel Sandler7d276c32012-01-30 14:33:52 -05003783 @Override
3784 public boolean isScreenSaverEnabled() {
3785 return (mScreenSaverFeatureAvailable && mScreenSaverEnabledByUser
3786 && mScreenSaverMayRun && mScreenOnEarly && mPluggedIn);
3787 }
Daniel Sandler7e37df52011-11-16 22:08:23 -08003788
Daniel Sandler7d276c32012-01-30 14:33:52 -05003789 @Override
3790 public boolean startScreenSaver() {
3791 synchronized (mLock) {
3792 if (isScreenSaverEnabled()) {
3793 IDreamManager dm = getDreamManager();
3794 if (dm == null) return false;
3795
3796 try {
3797 if (localLOGV) Log.v(TAG, "startScreenSaver: entering dreamland...");
3798
3799 dm.dream();
3800 return true;
3801 } catch (RemoteException ex) {
3802 // too bad, so sad, oh mom, oh dad
Daniel Sandlerc224f762011-11-15 22:55:03 -08003803 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003804 }
3805 }
Daniel Sandler7d276c32012-01-30 14:33:52 -05003806 return false;
3807 }
Daniel Sandler0601eb72011-04-13 01:01:32 -04003808
Daniel Sandler7d276c32012-01-30 14:33:52 -05003809 @Override
3810 public void stopScreenSaver() {
3811 synchronized (mLock) {
3812 IDreamManager dm = getDreamManager();
3813 if (dm == null) return;
3814
3815 try {
3816 if (localLOGV) Log.v(TAG, "startScreenSaver: awakening...");
3817
3818 dm.awaken();
3819 } catch (RemoteException ex) {
Daniel Sandler0601eb72011-04-13 01:01:32 -04003820 }
3821 }
Mike Lockwood28569302010-01-28 11:54:40 -05003822 }
3823
3824 Runnable mScreenLockTimeout = new Runnable() {
3825 public void run() {
3826 synchronized (this) {
3827 if (localLOGV) Log.v(TAG, "mScreenLockTimeout activating keyguard");
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003828 if (mKeyguardMediator != null) {
3829 mKeyguardMediator.doKeyguardTimeout();
3830 }
Mike Lockwood28569302010-01-28 11:54:40 -05003831 mLockScreenTimerActive = false;
3832 }
3833 }
3834 };
3835
Jim Miller93c518e2012-01-17 15:55:31 -08003836 public void lockNow() {
3837 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
3838 mHandler.removeCallbacks(mScreenLockTimeout);
3839 mHandler.post(mScreenLockTimeout);
3840 }
3841
Mike Lockwood28569302010-01-28 11:54:40 -05003842 private void updateLockScreenTimeout() {
3843 synchronized (mScreenLockTimeout) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07003844 boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly &&
3845 mKeyguardMediator != null && mKeyguardMediator.isSecure());
Mike Lockwood28569302010-01-28 11:54:40 -05003846 if (mLockScreenTimerActive != enable) {
3847 if (enable) {
3848 if (localLOGV) Log.v(TAG, "setting lockscreen timer");
3849 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
3850 } else {
3851 if (localLOGV) Log.v(TAG, "clearing lockscreen timer");
3852 mHandler.removeCallbacks(mScreenLockTimeout);
3853 }
3854 mLockScreenTimerActive = enable;
3855 }
3856 }
3857 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003858
3859 /** {@inheritDoc} */
3860 public void enableScreenAfterBoot() {
3861 readLidState();
Jeff Brown01a98dd2011-09-20 15:08:29 -07003862 updateKeyboardVisibility();
3863
3864 updateRotation(true);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003865 }
Dianne Hackbornf54c8f92009-09-19 14:03:57 -07003866
Jeff Brown01a98dd2011-09-20 15:08:29 -07003867 private void updateKeyboardVisibility() {
Jeff Brown4aed78b2011-01-14 17:36:55 -08003868 mPowerManager.setKeyboardVisibility(mLidOpen == LID_OPEN);
Jeff Brown01a98dd2011-09-20 15:08:29 -07003869 }
3870
3871 void updateRotation(boolean alwaysSendConfiguration) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003872 try {
3873 //set orientation on WindowManager
Dianne Hackbornf87d1962012-04-04 12:48:24 -07003874 mWindowManager.updateRotation(alwaysSendConfiguration, false);
3875 } catch (RemoteException e) {
3876 // Ignore
3877 }
3878 }
3879
3880 void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {
3881 try {
3882 //set orientation on WindowManager
3883 mWindowManager.updateRotation(alwaysSendConfiguration, forceRelayout);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003884 } catch (RemoteException e) {
3885 // Ignore
3886 }
3887 }
3888
3889 /**
Daniel Sandler11ddf532011-11-16 11:10:03 -08003890 * Return an Intent to launch the currently active dock app as home. Returns
3891 * null if the standard home should be launched, which is the case if any of the following is
3892 * true:
3893 * <ul>
3894 * <li>The device is not in either car mode or desk mode
3895 * <li>The device is in car mode but ENABLE_CAR_DOCK_HOME_CAPTURE is false
3896 * <li>The device is in desk mode but ENABLE_DESK_DOCK_HOME_CAPTURE is false
3897 * <li>The device is in car mode but there's no CAR_DOCK app with METADATA_DOCK_HOME
3898 * <li>The device is in desk mode but there's no DESK_DOCK app with METADATA_DOCK_HOME
3899 * </ul>
Dianne Hackborn39c2d712009-09-22 11:41:31 -07003900 * @return
3901 */
3902 Intent createHomeDockIntent() {
Daniel Sandler11ddf532011-11-16 11:10:03 -08003903 Intent intent = null;
Dianne Hackborn867ab6472010-04-29 13:28:56 -07003904
3905 // What home does is based on the mode, not the dock state. That
3906 // is, when in car mode you should be taken to car home regardless
3907 // of whether we are actually in a car dock.
Dianne Hackborn78968392010-03-04 20:47:56 -08003908 if (mUiMode == Configuration.UI_MODE_TYPE_CAR) {
Daniel Sandler11ddf532011-11-16 11:10:03 -08003909 if (ENABLE_CAR_DOCK_HOME_CAPTURE) {
3910 intent = mCarDockIntent;
3911 }
Dianne Hackborn78968392010-03-04 20:47:56 -08003912 } else if (mUiMode == Configuration.UI_MODE_TYPE_DESK) {
Daniel Sandler11ddf532011-11-16 11:10:03 -08003913 if (ENABLE_DESK_DOCK_HOME_CAPTURE) {
3914 intent = mDeskDockIntent;
3915 }
3916 }
3917
3918 if (intent == null) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07003919 return null;
3920 }
3921
3922 ActivityInfo ai = intent.resolveActivityInfo(
3923 mContext.getPackageManager(), PackageManager.GET_META_DATA);
3924 if (ai == null) {
3925 return null;
3926 }
3927
3928 if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
3929 intent = new Intent(intent);
3930 intent.setClassName(ai.packageName, ai.name);
3931 return intent;
3932 }
3933
3934 return null;
3935 }
3936
3937 void startDockOrHome() {
3938 Intent dock = createHomeDockIntent();
3939 if (dock != null) {
3940 try {
3941 mContext.startActivity(dock);
3942 return;
3943 } catch (ActivityNotFoundException e) {
3944 }
3945 }
3946 mContext.startActivity(mHomeIntent);
3947 }
3948
3949 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003950 * goes to the home screen
3951 * @return whether it did anything
3952 */
3953 boolean goHome() {
3954 if (false) {
3955 // This code always brings home to the front.
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07003956 try {
3957 ActivityManagerNative.getDefault().stopAppSwitches();
3958 } catch (RemoteException e) {
3959 }
Dianne Hackborn94a679d2009-07-28 17:51:07 -07003960 sendCloseSystemWindows();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07003961 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003962 } else {
3963 // This code brings home to the front or, if it is already
3964 // at the front, puts the device to sleep.
3965 try {
Wink Savilled2e6a332010-02-12 12:12:06 -08003966 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
3967 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
3968 Log.d(TAG, "UTS-TEST-MODE");
3969 } else {
3970 ActivityManagerNative.getDefault().stopAppSwitches();
3971 sendCloseSystemWindows();
3972 Intent dock = createHomeDockIntent();
3973 if (dock != null) {
3974 int result = ActivityManagerNative.getDefault()
3975 .startActivity(null, dock,
3976 dock.resolveTypeIfNeeded(mContext.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07003977 null, null, 0,
3978 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
3979 null, null, null);
3980 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
Wink Savilled2e6a332010-02-12 12:12:06 -08003981 return false;
3982 }
Dianne Hackborn39c2d712009-09-22 11:41:31 -07003983 }
3984 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003985 int result = ActivityManagerNative.getDefault()
3986 .startActivity(null, mHomeIntent,
3987 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07003988 null, null, 0,
3989 ActivityManager.START_FLAG_ONLY_IF_NEEDED,
3990 null, null, null);
3991 if (result == ActivityManager.START_RETURN_INTENT_TO_CALLER) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003992 return false;
3993 }
3994 } catch (RemoteException ex) {
3995 // bummer, the activity manager, which is in this process, is dead
3996 }
3997 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08003998 return true;
3999 }
4000
The Android Open Source Project0727d222009-03-11 12:11:58 -07004001 public void setCurrentOrientationLw(int newOrientation) {
4002 synchronized (mLock) {
4003 if (newOrientation != mCurrentAppOrientation) {
4004 mCurrentAppOrientation = newOrientation;
4005 updateOrientationListenerLp();
4006 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004007 }
4008 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004009
The Android Open Source Project0727d222009-03-11 12:11:58 -07004010 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
Jim Miller89b17222009-10-27 14:54:09 -07004011 final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
4012 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08004013 if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004014 return false;
4015 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004016 long[] pattern = null;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004017 switch (effectId) {
4018 case HapticFeedbackConstants.LONG_PRESS:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004019 pattern = mLongPressVibePattern;
4020 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004021 case HapticFeedbackConstants.VIRTUAL_KEY:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004022 pattern = mVirtualKeyVibePattern;
4023 break;
4024 case HapticFeedbackConstants.KEYBOARD_TAP:
4025 pattern = mKeyboardTapVibePattern;
4026 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004027 case HapticFeedbackConstants.SAFE_MODE_DISABLED:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004028 pattern = mSafeModeDisabledVibePattern;
4029 break;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07004030 case HapticFeedbackConstants.SAFE_MODE_ENABLED:
Amith Yamasanic33cb712010-02-10 15:21:49 -08004031 pattern = mSafeModeEnabledVibePattern;
4032 break;
Amith Yamasanic33cb712010-02-10 15:21:49 -08004033 default:
4034 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004035 }
Amith Yamasanic33cb712010-02-10 15:21:49 -08004036 if (pattern.length == 1) {
4037 // One-shot vibration
4038 mVibrator.vibrate(pattern[0]);
4039 } else {
4040 // Pattern vibration
4041 mVibrator.vibrate(pattern, -1);
4042 }
4043 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004044 }
4045
Daniel Sandler0601eb72011-04-13 01:01:32 -04004046 public void screenOnStartedLw() {
4047 // The window manager has just grabbed a wake lock. This is our cue to disable the screen
4048 // saver.
4049 synchronized (mLock) {
Daniel Sandler2d545362011-11-17 10:38:37 -08004050 mScreenSaverMayRun = false;
Daniel Sandler0601eb72011-04-13 01:01:32 -04004051 }
4052 }
4053
The Android Open Source Project0727d222009-03-11 12:11:58 -07004054 public void screenOnStoppedLw() {
Daniel Sandler0601eb72011-04-13 01:01:32 -04004055 if (mPowerManager.isScreenOn()) {
Mike Lockwood3a74bd32011-08-12 13:55:22 -07004056 if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
Daniel Sandler0601eb72011-04-13 01:01:32 -04004057 long curTime = SystemClock.uptimeMillis();
4058 mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
4059 }
4060
4061 synchronized (mLock) {
4062 // even if the keyguard is up, now that all the wakelocks have been released, we
4063 // should re-enable the screen saver
Daniel Sandler2d545362011-11-17 10:38:37 -08004064 mScreenSaverMayRun = true;
Daniel Sandler0601eb72011-04-13 01:01:32 -04004065 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004066 }
4067 }
Mike Lockwoodfcb39242009-10-21 23:01:07 -04004068
4069 public boolean allowKeyRepeat() {
4070 // disable key repeat when screen is off
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07004071 return mScreenOnEarly;
Mike Lockwoodfcb39242009-10-21 23:01:07 -04004072 }
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004073
Dianne Hackborndf89e652011-10-06 22:35:11 -07004074 private int updateSystemUiVisibilityLw() {
Joe Onorato664644d2011-01-23 17:53:23 -08004075 // If there is no window focused, there will be nobody to handle the events
4076 // anyway, so just hang on in whatever state we're in until things settle down.
Dianne Hackborndf89e652011-10-06 22:35:11 -07004077 if (mFocusedWindow == null) {
4078 return 0;
4079 }
4080 final int visibility = mFocusedWindow.getSystemUiVisibility()
Dianne Hackborne26ab702011-10-16 13:21:33 -07004081 & ~mResettingSystemUiFlags
4082 & ~mForceClearedSystemUiFlags;
4083 int diff = visibility ^ mLastSystemUiFlags;
Dianne Hackborn73ab6a42011-12-13 11:16:23 -08004084 final boolean needsMenu = mFocusedWindow.getNeedsMenuLw(mTopFullscreenOpaqueWindowState);
Dianne Hackborne0f085d2011-11-30 18:41:15 -08004085 if (diff == 0 && mLastFocusNeedsMenu == needsMenu
4086 && mFocusedApp == mFocusedWindow.getAppToken()) {
Dianne Hackborndf89e652011-10-06 22:35:11 -07004087 return 0;
4088 }
Dianne Hackborne26ab702011-10-16 13:21:33 -07004089 mLastSystemUiFlags = visibility;
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004090 mLastFocusNeedsMenu = needsMenu;
Dianne Hackborne0f085d2011-11-30 18:41:15 -08004091 mFocusedApp = mFocusedWindow.getAppToken();
Dianne Hackborndf89e652011-10-06 22:35:11 -07004092 mHandler.post(new Runnable() {
4093 public void run() {
4094 if (mStatusBarService == null) {
4095 mStatusBarService = IStatusBarService.Stub.asInterface(
4096 ServiceManager.getService("statusbar"));
4097 }
4098 if (mStatusBarService != null) {
4099 try {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07004100 mStatusBarService.setSystemUiVisibility(visibility, 0xffffffff);
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004101 mStatusBarService.topAppWindowChanged(needsMenu);
Dianne Hackborndf89e652011-10-06 22:35:11 -07004102 } catch (RemoteException e) {
4103 // not much to be done
4104 mStatusBarService = null;
Joe Onorato664644d2011-01-23 17:53:23 -08004105 }
4106 }
Dianne Hackborndf89e652011-10-06 22:35:11 -07004107 }
4108 });
4109 return diff;
Joe Onorato664644d2011-01-23 17:53:23 -08004110 }
4111
Daniel Sandler0c4ccff2011-10-19 16:39:14 -04004112 // Use this instead of checking config_showNavigationBar so that it can be consistently
4113 // overridden by qemu.hw.mainkeys in the emulator.
4114 public boolean hasNavigationBar() {
4115 return mHasNavigationBar;
4116 }
4117
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004118 public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
4119 pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
Dianne Hackbornba24e4d2011-09-01 11:17:06 -07004120 pw.print(" mSystemReady="); pw.print(mSystemReady);
4121 pw.print(" mSystemBooted="); pw.println(mSystemBooted);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004122 pw.print(prefix); pw.print("mLidOpen="); pw.print(mLidOpen);
4123 pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
4124 pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
Dianne Hackborne26ab702011-10-16 13:21:33 -07004125 if (mLastSystemUiFlags != 0 || mResettingSystemUiFlags != 0
4126 || mForceClearedSystemUiFlags != 0) {
4127 pw.print(prefix); pw.print("mLastSystemUiFlags=0x");
4128 pw.print(Integer.toHexString(mLastSystemUiFlags));
4129 pw.print(" mResettingSystemUiFlags=0x");
4130 pw.print(Integer.toHexString(mResettingSystemUiFlags));
4131 pw.print(" mForceClearedSystemUiFlags=0x");
4132 pw.println(Integer.toHexString(mForceClearedSystemUiFlags));
Dianne Hackborndf89e652011-10-06 22:35:11 -07004133 }
Dianne Hackborn4eff8d32011-11-10 19:38:40 -08004134 if (mLastFocusNeedsMenu) {
4135 pw.print(prefix); pw.print("mLastFocusNeedsMenu=");
4136 pw.println(mLastFocusNeedsMenu);
4137 }
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004138 pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
4139 pw.print(" mDockMode="); pw.print(mDockMode);
4140 pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
4141 pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
4142 pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
4143 pw.print(" mUserRotation="); pw.print(mUserRotation);
Daniel Sandler2ed6ad62011-02-22 14:54:17 -05004144 pw.print(" mAllowAllRotations="); pw.println(mAllowAllRotations);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004145 pw.print(prefix); pw.print("mAccelerometerDefault="); pw.print(mAccelerometerDefault);
4146 pw.print(" mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
4147 pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
4148 pw.print(mCarDockEnablesAccelerometer);
4149 pw.print(" mDeskDockEnablesAccelerometer=");
4150 pw.println(mDeskDockEnablesAccelerometer);
4151 pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
4152 pw.print(mLidKeyboardAccessibility);
4153 pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
4154 pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
Dianne Hackbornbc1aa7b2011-09-20 11:20:31 -07004155 pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
4156 pw.print(" mScreenOnFully="); pw.print(mScreenOnFully);
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004157 pw.print(" mOrientationSensorEnabled="); pw.print(mOrientationSensorEnabled);
4158 pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
4159 pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
4160 pw.print(","); pw.print(mUnrestrictedScreenTop);
4161 pw.print(") "); pw.print(mUnrestrictedScreenWidth);
4162 pw.print("x"); pw.println(mUnrestrictedScreenHeight);
4163 pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
4164 pw.print(","); pw.print(mRestrictedScreenTop);
4165 pw.print(") "); pw.print(mRestrictedScreenWidth);
4166 pw.print("x"); pw.println(mRestrictedScreenHeight);
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07004167 pw.print(prefix); pw.print("mStable=("); pw.print(mStableLeft);
4168 pw.print(","); pw.print(mStableTop);
4169 pw.print(")-("); pw.print(mStableRight);
4170 pw.print(","); pw.print(mStableBottom); pw.println(")");
Dianne Hackbornf99f9c52011-01-12 15:49:25 -08004171 pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
4172 pw.print(","); pw.print(mCurTop);
4173 pw.print(")-("); pw.print(mCurRight);
4174 pw.print(","); pw.print(mCurBottom); pw.println(")");
4175 pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
4176 pw.print(","); pw.print(mContentTop);
4177 pw.print(")-("); pw.print(mContentRight);
4178 pw.print(","); pw.print(mContentBottom); pw.println(")");
4179 pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
4180 pw.print(","); pw.print(mDockTop);
4181 pw.print(")-("); pw.print(mDockRight);
4182 pw.print(","); pw.print(mDockBottom); pw.println(")");
4183 pw.print(prefix); pw.print("mDockLayer="); pw.println(mDockLayer);
4184 pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
4185 pw.println(mTopFullscreenOpaqueWindowState);
4186 pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
4187 pw.print(" mForceStatusBar="); pw.print(mForceStatusBar);
4188 pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
4189 pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
4190 pw.print(" mHomePressed="); pw.println(mHomePressed);
4191 pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
4192 pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
4193 pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
4194 pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
4195 pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
4196 pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
4197 pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
4198 pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
4199 pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
4200 pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
4201 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08004202}