blob: 7970987c6dd8ff92b18454f2aa7003b56588888d [file] [log] [blame]
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.policy.impl;
18
19import android.app.Activity;
20import android.app.ActivityManagerNative;
21import android.app.IActivityManager;
22import android.app.IStatusBar;
Dianne Hackborn39c2d712009-09-22 11:41:31 -070023import android.content.ActivityNotFoundException;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080024import android.content.BroadcastReceiver;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080025import android.content.ContentResolver;
26import android.content.Context;
27import android.content.Intent;
Mike Lockwood1753f7f2009-08-24 14:49:07 -070028import android.content.IntentFilter;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080029import android.content.pm.ActivityInfo;
30import android.content.pm.PackageManager;
31import android.content.res.Configuration;
32import android.content.res.Resources;
33import android.database.ContentObserver;
34import android.graphics.Rect;
Dianne Hackbornf54c8f92009-09-19 14:03:57 -070035import android.os.BatteryManager;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080036import android.os.Handler;
37import android.os.IBinder;
38import android.os.LocalPowerManager;
39import android.os.PowerManager;
40import android.os.RemoteException;
41import android.os.ServiceManager;
42import android.os.SystemClock;
43import android.os.SystemProperties;
44import android.os.Vibrator;
45import android.provider.Settings;
46
47import com.android.internal.policy.PolicyManager;
48import com.android.internal.telephony.ITelephony;
49import android.util.Config;
50import android.util.EventLog;
51import android.util.Log;
Mitsuru Oshima831d0d92009-06-16 18:27:18 -070052import android.view.Display;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080053import android.view.Gravity;
54import android.view.HapticFeedbackConstants;
55import android.view.IWindowManager;
56import android.view.KeyEvent;
57import android.view.MotionEvent;
58import android.view.WindowOrientationListener;
59import android.view.RawInputEvent;
60import android.view.Surface;
61import android.view.View;
62import android.view.ViewConfiguration;
63import android.view.Window;
64import android.view.WindowManager;
65import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
66import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
67import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
68import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
69import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
70import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -070071import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
Dianne Hackborn39c2d712009-09-22 11:41:31 -070072import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080073import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
74import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
75import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
76import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
Dianne Hackborn5cb8d792009-05-21 17:34:15 -070077import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080078import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
79import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
80import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
81import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
82import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
83import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
84import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
85import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
86import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
87import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -080088import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080089import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
90import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
91import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
92import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
93import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
94import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -070095import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -080096import android.view.WindowManagerImpl;
97import android.view.WindowManagerPolicy;
Dianne Hackborn01ad2f42009-09-24 19:24:56 -070098import android.view.animation.Animation;
99import android.view.animation.AnimationUtils;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800100import android.media.IAudioService;
101import android.media.AudioManager;
102
103/**
The Android Open Source Project0727d222009-03-11 12:11:58 -0700104 * WindowManagerPolicy implementation for the Android phone UI. This
105 * introduces a new method suffix, Lp, for an internal lock of the
106 * PhoneWindowManager. This is used to protect some internal state, and
107 * can be acquired with either thw Lw and Li lock held, so has the restrictions
108 * of both of those when held.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800109 */
110public class PhoneWindowManager implements WindowManagerPolicy {
111 static final String TAG = "WindowManager";
112 static final boolean DEBUG = false;
113 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
The Android Open Source Project11267662009-03-18 17:39:47 -0700114 static final boolean DEBUG_LAYOUT = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800115 static final boolean SHOW_STARTING_ANIMATIONS = true;
116 static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
117
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700118 // wallpaper is at the bottom, though the window manager may move it.
Dianne Hackborn3c3bd442009-08-19 17:09:46 -0700119 static final int WALLPAPER_LAYER = 2;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700120 static final int APPLICATION_LAYER = 2;
121 static final int PHONE_LAYER = 3;
122 static final int SEARCH_BAR_LAYER = 4;
123 static final int STATUS_BAR_PANEL_LAYER = 5;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800124 static final int SYSTEM_DIALOG_LAYER = 6;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800125 // toasts and the plugged-in battery thing
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800126 static final int TOAST_LAYER = 7;
127 static final int STATUS_BAR_LAYER = 8;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800128 // SIM errors and unlock. Not sure if this really should be in a high layer.
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800129 static final int PRIORITY_PHONE_LAYER = 9;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800130 // like the ANR / app crashed dialogs
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800131 static final int SYSTEM_ALERT_LAYER = 10;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800132 // system-level error dialogs
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800133 static final int SYSTEM_ERROR_LAYER = 11;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800134 // on-screen keyboards and other such input method user interfaces go here.
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800135 static final int INPUT_METHOD_LAYER = 12;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800136 // on-screen keyboards and other such input method user interfaces go here.
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800137 static final int INPUT_METHOD_DIALOG_LAYER = 13;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800138 // the keyguard; nothing on top of these can take focus, since they are
139 // responsible for power management when displayed.
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800140 static final int KEYGUARD_LAYER = 14;
141 static final int KEYGUARD_DIALOG_LAYER = 15;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800142 // things in here CAN NOT take focus, but are shown on top of everything else.
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800143 static final int SYSTEM_OVERLAY_LAYER = 16;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800144
Dianne Hackborn5cb8d792009-05-21 17:34:15 -0700145 static final int APPLICATION_MEDIA_SUBLAYER = -2;
146 static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800147 static final int APPLICATION_PANEL_SUBLAYER = 1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800148 static final int APPLICATION_SUB_PANEL_SUBLAYER = 2;
149
150 static final float SLIDE_TOUCH_EVENT_SIZE_LIMIT = 0.6f;
151
152 // Debugging: set this to have the system act like there is no hard keyboard.
153 static final boolean KEYBOARD_ALWAYS_HIDDEN = false;
154
155 static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
156 static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
157 static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
Joe Onoratof275f0c2009-11-24 16:11:13 -0500158 static public final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800159
The Android Open Source Project0727d222009-03-11 12:11:58 -0700160 final Object mLock = new Object();
161
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800162 Context mContext;
163 IWindowManager mWindowManager;
164 LocalPowerManager mPowerManager;
165 Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
166
Dianne Hackborn181ceb52009-08-27 22:16:40 -0700167 // Vibrator pattern for haptic feedback of a long press.
168 long[] mLongPressVibePattern;
169
170 // Vibrator pattern for haptic feedback of virtual key press.
171 long[] mVirtualKeyVibePattern;
172
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700173 // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
174 long[] mSafeModeDisabledVibePattern;
175
176 // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
177 long[] mSafeModeEnabledVibePattern;
178
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800179 /** If true, hitting shift & menu will broadcast Intent.ACTION_BUG_REPORT */
180 boolean mEnableShiftMenuBugReports = false;
181
182 boolean mSafeMode;
183 WindowState mStatusBar = null;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800184 WindowState mKeyguard = null;
185 KeyguardViewMediator mKeyguardMediator;
186 GlobalActions mGlobalActions;
187 boolean mShouldTurnOffOnKeyUp;
188 RecentApplicationsDialog mRecentAppsDialog;
189 Handler mHandler;
190
Dianne Hackborn05726582009-09-22 17:28:24 -0700191 final IntentFilter mBatteryStatusFilter = new IntentFilter();
192
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800193 boolean mLidOpen;
Dianne Hackborn05726582009-09-22 17:28:24 -0700194 int mPlugged;
Dianne Hackborn80fa1662009-10-07 14:02:10 -0700195 boolean mRegisteredBatteryReceiver;
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400196 int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700197 int mLidOpenRotation;
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400198 int mCarDockRotation;
199 int mDeskDockRotation;
Dianne Hackborn05726582009-09-22 17:28:24 -0700200 int mCarDockKeepsScreenOn;
201 int mDeskDockKeepsScreenOn;
Mike Lockwoode9867d22009-09-20 01:59:02 -0400202 boolean mCarDockEnablesAccelerometer;
203 boolean mDeskDockEnablesAccelerometer;
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700204 int mLidKeyboardAccessibility;
205 int mLidNavigationAccessibility;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800206 boolean mScreenOn = false;
207 boolean mOrientationSensorEnabled = false;
208 int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
209 static final int DEFAULT_ACCELEROMETER_ROTATION = 0;
210 int mAccelerometerDefault = DEFAULT_ACCELEROMETER_ROTATION;
211 boolean mHasSoftInput = false;
212
213 // The current size of the screen.
214 int mW, mH;
215 // During layout, the current screen borders with all outer decoration
216 // (status bar, input method dock) accounted for.
217 int mCurLeft, mCurTop, mCurRight, mCurBottom;
218 // During layout, the frame in which content should be displayed
219 // to the user, accounting for all screen decoration except for any
220 // space they deem as available for other content. This is usually
221 // the same as mCur*, but may be larger if the screen decor has supplied
222 // content insets.
223 int mContentLeft, mContentTop, mContentRight, mContentBottom;
224 // During layout, the current screen borders along with input method
225 // windows are placed.
226 int mDockLeft, mDockTop, mDockRight, mDockBottom;
227 // During layout, the layer at which the doc window is placed.
228 int mDockLayer;
229
230 static final Rect mTmpParentFrame = new Rect();
231 static final Rect mTmpDisplayFrame = new Rect();
232 static final Rect mTmpContentFrame = new Rect();
233 static final Rect mTmpVisibleFrame = new Rect();
234
235 WindowState mTopFullscreenOpaqueWindowState;
236 boolean mForceStatusBar;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700237 boolean mHideLockScreen;
238 boolean mDismissKeyguard;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800239 boolean mHomePressed;
240 Intent mHomeIntent;
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700241 Intent mCarDockIntent;
242 Intent mDeskDockIntent;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800243 boolean mSearchKeyPressed;
244 boolean mConsumeSearchKeyUp;
245
246 static final int ENDCALL_HOME = 0x1;
247 static final int ENDCALL_SLEEPS = 0x2;
248 static final int DEFAULT_ENDCALL_BEHAVIOR = ENDCALL_SLEEPS;
249 int mEndcallBehavior;
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700250
Mitsuru Oshima831d0d92009-06-16 18:27:18 -0700251 int mLandscapeRotation = -1;
252 int mPortraitRotation = -1;
253
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700254 // Nothing to see here, move along...
255 int mFancyRotationAnimation;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800256
257 ShortcutManager mShortcutManager;
258 PowerManager.WakeLock mBroadcastWakeLock;
Dianne Hackbornf54c8f92009-09-19 14:03:57 -0700259 PowerManager.WakeLock mDockWakeLock;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800260
261 class SettingsObserver extends ContentObserver {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800262 SettingsObserver(Handler handler) {
263 super(handler);
264 }
265
266 void observe() {
267 ContentResolver resolver = mContext.getContentResolver();
268 resolver.registerContentObserver(Settings.System.getUriFor(
269 Settings.System.END_BUTTON_BEHAVIOR), false, this);
270 resolver.registerContentObserver(Settings.System.getUriFor(
271 Settings.System.ACCELEROMETER_ROTATION), false, this);
272 resolver.registerContentObserver(Settings.Secure.getUriFor(
273 Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700274 resolver.registerContentObserver(Settings.System.getUriFor(
275 "fancy_rotation_anim"), false, this);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800276 update();
277 }
278
279 @Override public void onChange(boolean selfChange) {
280 update();
281 try {
Dianne Hackborn32bc91d2009-03-27 16:16:03 -0700282 mWindowManager.setRotation(USE_LAST_ROTATION, false,
283 mFancyRotationAnimation);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800284 } catch (RemoteException e) {
285 // Ignore
286 }
287 }
288
289 public void update() {
290 ContentResolver resolver = mContext.getContentResolver();
Dianne Hackbornae585e82009-03-27 20:56:50 -0700291 boolean updateRotation = false;
The Android Open Source Project0727d222009-03-11 12:11:58 -0700292 synchronized (mLock) {
293 mEndcallBehavior = Settings.System.getInt(resolver,
294 Settings.System.END_BUTTON_BEHAVIOR, DEFAULT_ENDCALL_BEHAVIOR);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700295 mFancyRotationAnimation = Settings.System.getInt(resolver,
Dianne Hackborn32bc91d2009-03-27 16:16:03 -0700296 "fancy_rotation_anim", 0) != 0 ? 0x80 : 0;
The Android Open Source Project0727d222009-03-11 12:11:58 -0700297 int accelerometerDefault = Settings.System.getInt(resolver,
298 Settings.System.ACCELEROMETER_ROTATION, DEFAULT_ACCELEROMETER_ROTATION);
299 if (mAccelerometerDefault != accelerometerDefault) {
300 mAccelerometerDefault = accelerometerDefault;
301 updateOrientationListenerLp();
302 }
303 String imId = Settings.Secure.getString(resolver,
304 Settings.Secure.DEFAULT_INPUT_METHOD);
305 boolean hasSoftInput = imId != null && imId.length() > 0;
306 if (mHasSoftInput != hasSoftInput) {
307 mHasSoftInput = hasSoftInput;
Dianne Hackbornae585e82009-03-27 20:56:50 -0700308 updateRotation = true;
The Android Open Source Project0727d222009-03-11 12:11:58 -0700309 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800310 }
Dianne Hackbornae585e82009-03-27 20:56:50 -0700311 if (updateRotation) {
312 updateRotation(0);
313 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800314 }
315 }
316
317 class MyOrientationListener extends WindowOrientationListener {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800318 MyOrientationListener(Context context) {
319 super(context);
320 }
321
322 @Override
The Android Open Source Projectd06b0972009-03-13 13:04:23 -0700323 public void onOrientationChanged(int rotation) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800324 // Send updates based on orientation value
Dianne Hackborn05726582009-09-22 17:28:24 -0700325 if (localLOGV) Log.v(TAG, "onOrientationChanged, rotation changed to " +rotation);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700326 try {
Dianne Hackborn32bc91d2009-03-27 16:16:03 -0700327 mWindowManager.setRotation(rotation, false,
328 mFancyRotationAnimation);
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700329 } catch (RemoteException e) {
330 // Ignore
Wink Saville37c124c2009-04-02 01:37:02 -0700331
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800332 }
333 }
334 }
335 MyOrientationListener mOrientationListener;
336
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700337 boolean useSensorForOrientationLp(int appOrientation) {
Joe Onorato1b58b3e2009-09-22 16:44:16 -0700338 // The app says use the sensor.
Dianne Hackborn03759ed2009-03-27 16:04:08 -0700339 if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800340 return true;
341 }
Joe Onorato1b58b3e2009-09-22 16:44:16 -0700342 // The user preference says we can rotate, and the app is willing to rotate.
343 if (mAccelerometerDefault != 0 &&
344 (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
345 || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800346 return true;
347 }
Joe Onorato1b58b3e2009-09-22 16:44:16 -0700348 // We're in a dock that has a rotation affinity, an the app is willing to rotate.
349 if ((mCarDockEnablesAccelerometer && mDockState == Intent.EXTRA_DOCK_STATE_CAR)
350 || (mDeskDockEnablesAccelerometer && mDockState == Intent.EXTRA_DOCK_STATE_DESK)) {
351 // Note we override the nosensor flag here.
352 if (appOrientation == ActivityInfo.SCREEN_ORIENTATION_USER
353 || appOrientation == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
354 || appOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
355 return true;
356 }
357 }
358 // Else, don't use the sensor.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800359 return false;
360 }
361
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700362 /*
363 * We always let the sensor be switched on by default except when
364 * the user has explicitly disabled sensor based rotation or when the
365 * screen is switched off.
366 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700367 boolean needSensorRunningLp() {
368 if (mCurrentAppOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800369 // If the application has explicitly requested to follow the
370 // orientation, then we need to turn the sensor or.
371 return true;
372 }
Mike Lockwoode9867d22009-09-20 01:59:02 -0400373 if ((mCarDockEnablesAccelerometer && mDockState == Intent.EXTRA_DOCK_STATE_CAR) ||
374 (mDeskDockEnablesAccelerometer && mDockState == Intent.EXTRA_DOCK_STATE_DESK)) {
375 // enable accelerometer if we are docked in a dock that enables accelerometer
376 // orientation management,
377 return true;
378 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700379 if (mAccelerometerDefault == 0) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800380 // If the setting for using the sensor by default is enabled, then
381 // we will always leave it on. Note that the user could go to
382 // a window that forces an orientation that does not use the
383 // sensor and in theory we could turn it off... however, when next
384 // turning it on we won't have a good value for the current
385 // orientation for a little bit, which can cause orientation
386 // changes to lag, so we'd like to keep it always on. (It will
387 // still be turned off when the screen is off.)
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700388 return false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800389 }
Suchi Amalapurapua9e1b162009-03-24 22:24:47 -0700390 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800391 }
392
393 /*
394 * Various use cases for invoking this function
395 * screen turning off, should always disable listeners if already enabled
396 * screen turned on and current app has sensor based orientation, enable listeners
397 * if not already enabled
398 * screen turned on and current app does not have sensor orientation, disable listeners if
399 * already enabled
400 * screen turning on and current app has sensor based orientation, enable listeners if needed
401 * screen turning on and current app has nosensor based orientation, do nothing
402 */
The Android Open Source Project0727d222009-03-11 12:11:58 -0700403 void updateOrientationListenerLp() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800404 if (!mOrientationListener.canDetectOrientation()) {
405 // If sensor is turned off or nonexistent for some reason
406 return;
407 }
408 //Could have been invoked due to screen turning on or off or
409 //change of the currently visible window's orientation
Dianne Hackborn05726582009-09-22 17:28:24 -0700410 if (localLOGV) Log.v(TAG, "Screen status="+mScreenOn+
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800411 ", current orientation="+mCurrentAppOrientation+
412 ", SensorEnabled="+mOrientationSensorEnabled);
413 boolean disable = true;
The Android Open Source Project0727d222009-03-11 12:11:58 -0700414 if (mScreenOn) {
415 if (needSensorRunningLp()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800416 disable = false;
417 //enable listener if not already enabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700418 if (!mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800419 mOrientationListener.enable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700420 if(localLOGV) Log.v(TAG, "Enabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800421 mOrientationSensorEnabled = true;
422 }
423 }
424 }
425 //check if sensors need to be disabled
The Android Open Source Project0727d222009-03-11 12:11:58 -0700426 if (disable && mOrientationSensorEnabled) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800427 mOrientationListener.disable();
Dianne Hackborn05726582009-09-22 17:28:24 -0700428 if(localLOGV) Log.v(TAG, "Disabling listeners");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800429 mOrientationSensorEnabled = false;
430 }
431 }
432
Dianne Hackborn0041e972009-07-24 17:14:43 -0700433 Runnable mPowerLongPress = new Runnable() {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800434 public void run() {
435 mShouldTurnOffOnKeyUp = false;
The Android Open Source Project0727d222009-03-11 12:11:58 -0700436 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800437 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
438 showGlobalActionsDialog();
439 }
440 };
441
442 void showGlobalActionsDialog() {
443 if (mGlobalActions == null) {
444 mGlobalActions = new GlobalActions(mContext);
445 }
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -0800446 final boolean keyguardShowing = mKeyguardMediator.isShowingAndNotHidden();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800447 mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
448 if (keyguardShowing) {
449 // since it took two seconds of long press to bring this up,
450 // poke the wake lock so they have some time to see the dialog.
451 mKeyguardMediator.pokeWakelock();
452 }
453 }
454
455 boolean isDeviceProvisioned() {
456 return Settings.Secure.getInt(
457 mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
458 }
459
460 /**
461 * When a home-key longpress expires, close other system windows and launch the recent apps
462 */
463 Runnable mHomeLongPress = new Runnable() {
464 public void run() {
465 /*
466 * Eat the longpress so it won't dismiss the recent apps dialog when
467 * the user lets go of the home key
468 */
469 mHomePressed = false;
The Android Open Source Project0727d222009-03-11 12:11:58 -0700470 performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800471 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_RECENT_APPS);
472 showRecentAppsDialog();
473 }
474 };
475
476 /**
477 * Create (if necessary) and launch the recent apps dialog
478 */
479 void showRecentAppsDialog() {
480 if (mRecentAppsDialog == null) {
481 mRecentAppsDialog = new RecentApplicationsDialog(mContext);
482 }
483 mRecentAppsDialog.show();
484 }
485
486 /** {@inheritDoc} */
487 public void init(Context context, IWindowManager windowManager,
488 LocalPowerManager powerManager) {
489 mContext = context;
490 mWindowManager = windowManager;
491 mPowerManager = powerManager;
492 mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
493 mHandler = new Handler();
494 mOrientationListener = new MyOrientationListener(mContext);
495 SettingsObserver settingsObserver = new SettingsObserver(mHandler);
496 settingsObserver.observe();
497 mShortcutManager = new ShortcutManager(context, mHandler);
498 mShortcutManager.observe();
499 mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
500 mHomeIntent.addCategory(Intent.CATEGORY_HOME);
501 mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
502 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
Dianne Hackborn39c2d712009-09-22 11:41:31 -0700503 mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
504 mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
505 mCarDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
506 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
507 mDeskDockIntent = new Intent(Intent.ACTION_MAIN, null);
508 mDeskDockIntent.addCategory(Intent.CATEGORY_DESK_DOCK);
509 mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
510 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800511 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
512 mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
513 "PhoneWindowManager.mBroadcastWakeLock");
Mike Lockwoode224cef2010-01-13 21:11:08 -0800514 mDockWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE,
Dianne Hackbornf54c8f92009-09-19 14:03:57 -0700515 "PhoneWindowManager.mDockWakeLock");
516 mDockWakeLock.setReferenceCounted(false);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800517 mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700518 mLidOpenRotation = readRotation(
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400519 com.android.internal.R.integer.config_lidOpenRotation);
520 mCarDockRotation = readRotation(
521 com.android.internal.R.integer.config_carDockRotation);
522 mDeskDockRotation = readRotation(
523 com.android.internal.R.integer.config_deskDockRotation);
Dianne Hackborn05726582009-09-22 17:28:24 -0700524 mCarDockKeepsScreenOn = mContext.getResources().getInteger(
525 com.android.internal.R.integer.config_carDockKeepsScreenOn);
526 mDeskDockKeepsScreenOn = mContext.getResources().getInteger(
527 com.android.internal.R.integer.config_deskDockKeepsScreenOn);
Mike Lockwoode9867d22009-09-20 01:59:02 -0400528 mCarDockEnablesAccelerometer = mContext.getResources().getBoolean(
529 com.android.internal.R.bool.config_carDockEnablesAccelerometer);
530 mDeskDockEnablesAccelerometer = mContext.getResources().getBoolean(
531 com.android.internal.R.bool.config_deskDockEnablesAccelerometer);
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700532 mLidKeyboardAccessibility = mContext.getResources().getInteger(
533 com.android.internal.R.integer.config_lidKeyboardAccessibility);
534 mLidNavigationAccessibility = mContext.getResources().getInteger(
535 com.android.internal.R.integer.config_lidNavigationAccessibility);
Dianne Hackbornf54c8f92009-09-19 14:03:57 -0700536 // register for battery events
Dianne Hackborn05726582009-09-22 17:28:24 -0700537 mBatteryStatusFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
538 mPlugged = 0;
Dianne Hackborn80fa1662009-10-07 14:02:10 -0700539 updatePlugged(context.registerReceiver(null, mBatteryStatusFilter));
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700540 // register for dock events
541 context.registerReceiver(mDockReceiver, new IntentFilter(Intent.ACTION_DOCK_EVENT));
Dianne Hackbornb1a79802009-09-29 15:18:31 -0700542 mVibrator = new Vibrator();
543 mLongPressVibePattern = getLongIntArray(mContext.getResources(),
544 com.android.internal.R.array.config_longPressVibePattern);
545 mVirtualKeyVibePattern = getLongIntArray(mContext.getResources(),
546 com.android.internal.R.array.config_virtualKeyVibePattern);
547 mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
548 com.android.internal.R.array.config_safeModeDisabledVibePattern);
549 mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
550 com.android.internal.R.array.config_safeModeEnabledVibePattern);
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700551 }
552
Dianne Hackborn80fa1662009-10-07 14:02:10 -0700553 void updatePlugged(Intent powerIntent) {
Dianne Hackborn05726582009-09-22 17:28:24 -0700554 if (localLOGV) Log.v(TAG, "New battery status: " + powerIntent.getExtras());
555 if (powerIntent != null) {
556 mPlugged = powerIntent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0);
557 if (localLOGV) Log.v(TAG, "PLUGGED: " + mPlugged);
558 }
559 }
560
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400561 private int readRotation(int resID) {
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700562 try {
563 int rotation = mContext.getResources().getInteger(resID);
564 switch (rotation) {
565 case 0:
566 return Surface.ROTATION_0;
567 case 90:
568 return Surface.ROTATION_90;
569 case 180:
570 return Surface.ROTATION_180;
571 case 270:
572 return Surface.ROTATION_270;
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700573 }
574 } catch (Resources.NotFoundException e) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400575 // fall through
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700576 }
Mike Lockwood2d1efbd2009-09-16 12:15:53 -0400577 return -1;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800578 }
579
580 /** {@inheritDoc} */
581 public int checkAddPermission(WindowManager.LayoutParams attrs) {
582 int type = attrs.type;
Mitsuru Oshima831d0d92009-06-16 18:27:18 -0700583
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800584 if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
585 || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) {
586 return WindowManagerImpl.ADD_OKAY;
587 }
588 String permission = null;
589 switch (type) {
590 case TYPE_TOAST:
591 // XXX right now the app process has complete control over
592 // this... should introduce a token to let the system
593 // monitor/control what they are doing.
594 break;
595 case TYPE_INPUT_METHOD:
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700596 case TYPE_WALLPAPER:
597 // The window manager will check these.
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800598 break;
599 case TYPE_PHONE:
600 case TYPE_PRIORITY_PHONE:
601 case TYPE_SYSTEM_ALERT:
602 case TYPE_SYSTEM_ERROR:
603 case TYPE_SYSTEM_OVERLAY:
604 permission = android.Manifest.permission.SYSTEM_ALERT_WINDOW;
605 break;
606 default:
607 permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
608 }
609 if (permission != null) {
610 if (mContext.checkCallingOrSelfPermission(permission)
611 != PackageManager.PERMISSION_GRANTED) {
612 return WindowManagerImpl.ADD_PERMISSION_DENIED;
613 }
614 }
615 return WindowManagerImpl.ADD_OKAY;
616 }
617
618 public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
619 switch (attrs.type) {
620 case TYPE_SYSTEM_OVERLAY:
621 case TYPE_TOAST:
622 // These types of windows can't receive input events.
623 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
624 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
625 break;
626 }
627 }
628
629 void readLidState() {
630 try {
Mike Lockwood1753f7f2009-08-24 14:49:07 -0700631 int sw = mWindowManager.getSwitchState(RawInputEvent.SW_LID);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800632 if (sw >= 0) {
633 mLidOpen = sw == 0;
634 }
635 } catch (RemoteException e) {
636 // Ignore
637 }
638 }
639
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700640 private int determineHiddenState(boolean lidOpen,
641 int mode, int hiddenValue, int visibleValue) {
642 switch (mode) {
643 case 1:
644 return lidOpen ? visibleValue : hiddenValue;
645 case 2:
646 return lidOpen ? hiddenValue : visibleValue;
647 }
648 return visibleValue;
649 }
650
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800651 /** {@inheritDoc} */
652 public void adjustConfigurationLw(Configuration config) {
653 readLidState();
654 final boolean lidOpen = !KEYBOARD_ALWAYS_HIDDEN && mLidOpen;
655 mPowerManager.setKeyboardVisibility(lidOpen);
Dianne Hackborn2862fff2009-09-15 22:56:29 -0700656 config.hardKeyboardHidden = determineHiddenState(lidOpen,
657 mLidKeyboardAccessibility, Configuration.HARDKEYBOARDHIDDEN_YES,
658 Configuration.HARDKEYBOARDHIDDEN_NO);
659 config.navigationHidden = determineHiddenState(lidOpen,
660 mLidNavigationAccessibility, Configuration.NAVIGATIONHIDDEN_YES,
661 Configuration.NAVIGATIONHIDDEN_NO);
662 config.keyboardHidden = (config.hardKeyboardHidden
663 == Configuration.HARDKEYBOARDHIDDEN_NO || mHasSoftInput)
664 ? Configuration.KEYBOARDHIDDEN_NO
665 : Configuration.KEYBOARDHIDDEN_YES;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800666 }
667
668 public boolean isCheekPressedAgainstScreen(MotionEvent ev) {
669 if(ev.getSize() > SLIDE_TOUCH_EVENT_SIZE_LIMIT) {
670 return true;
671 }
672 int size = ev.getHistorySize();
673 for(int i = 0; i < size; i++) {
674 if(ev.getHistoricalSize(i) > SLIDE_TOUCH_EVENT_SIZE_LIMIT) {
675 return true;
676 }
677 }
678 return false;
679 }
680
681 /** {@inheritDoc} */
682 public int windowTypeToLayerLw(int type) {
683 if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
684 return APPLICATION_LAYER;
685 }
686 switch (type) {
687 case TYPE_STATUS_BAR:
688 return STATUS_BAR_LAYER;
689 case TYPE_STATUS_BAR_PANEL:
690 return STATUS_BAR_PANEL_LAYER;
Dianne Hackborn6a294ce2009-12-03 11:37:44 -0800691 case TYPE_SYSTEM_DIALOG:
692 return SYSTEM_DIALOG_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800693 case TYPE_SEARCH_BAR:
694 return SEARCH_BAR_LAYER;
695 case TYPE_PHONE:
696 return PHONE_LAYER;
697 case TYPE_KEYGUARD:
698 return KEYGUARD_LAYER;
699 case TYPE_KEYGUARD_DIALOG:
700 return KEYGUARD_DIALOG_LAYER;
701 case TYPE_SYSTEM_ALERT:
702 return SYSTEM_ALERT_LAYER;
703 case TYPE_SYSTEM_ERROR:
704 return SYSTEM_ERROR_LAYER;
705 case TYPE_INPUT_METHOD:
706 return INPUT_METHOD_LAYER;
707 case TYPE_INPUT_METHOD_DIALOG:
708 return INPUT_METHOD_DIALOG_LAYER;
709 case TYPE_SYSTEM_OVERLAY:
710 return SYSTEM_OVERLAY_LAYER;
711 case TYPE_PRIORITY_PHONE:
712 return PRIORITY_PHONE_LAYER;
713 case TYPE_TOAST:
714 return TOAST_LAYER;
Dianne Hackbornb7cd8b92009-08-08 20:53:03 -0700715 case TYPE_WALLPAPER:
716 return WALLPAPER_LAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800717 }
718 Log.e(TAG, "Unknown window type: " + type);
719 return APPLICATION_LAYER;
720 }
721
722 /** {@inheritDoc} */
723 public int subWindowTypeToLayerLw(int type) {
724 switch (type) {
725 case TYPE_APPLICATION_PANEL:
726 case TYPE_APPLICATION_ATTACHED_DIALOG:
727 return APPLICATION_PANEL_SUBLAYER;
728 case TYPE_APPLICATION_MEDIA:
729 return APPLICATION_MEDIA_SUBLAYER;
Dianne Hackborn5cb8d792009-05-21 17:34:15 -0700730 case TYPE_APPLICATION_MEDIA_OVERLAY:
731 return APPLICATION_MEDIA_OVERLAY_SUBLAYER;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800732 case TYPE_APPLICATION_SUB_PANEL:
733 return APPLICATION_SUB_PANEL_SUBLAYER;
734 }
735 Log.e(TAG, "Unknown sub-window type: " + type);
736 return 0;
737 }
738
Dianne Hackbornabe0da02009-09-18 01:55:39 -0700739 public int getMaxWallpaperLayer() {
740 return STATUS_BAR_LAYER;
741 }
742
Dianne Hackborn01ad2f42009-09-24 19:24:56 -0700743 public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
744 return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
745 }
746
747 public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
748 return attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
749 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER;
750 }
751
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800752 /** {@inheritDoc} */
753 public View addStartingWindow(IBinder appToken, String packageName,
754 int theme, CharSequence nonLocalizedLabel,
755 int labelRes, int icon) {
756 if (!SHOW_STARTING_ANIMATIONS) {
757 return null;
758 }
759 if (packageName == null) {
760 return null;
761 }
762
763 Context context = mContext;
764 boolean setTheme = false;
765 //Log.i(TAG, "addStartingWindow " + packageName + ": nonLocalizedLabel="
766 // + nonLocalizedLabel + " theme=" + Integer.toHexString(theme));
767 if (theme != 0 || labelRes != 0) {
768 try {
769 context = context.createPackageContext(packageName, 0);
770 if (theme != 0) {
771 context.setTheme(theme);
772 setTheme = true;
773 }
774 } catch (PackageManager.NameNotFoundException e) {
775 // Ignore
776 }
777 }
778 if (!setTheme) {
779 context.setTheme(com.android.internal.R.style.Theme);
780 }
781
782 Window win = PolicyManager.makeNewWindow(context);
783 if (win.getWindowStyle().getBoolean(
784 com.android.internal.R.styleable.Window_windowDisablePreview, false)) {
785 return null;
786 }
787
788 Resources r = context.getResources();
789 win.setTitle(r.getText(labelRes, nonLocalizedLabel));
790
791 win.setType(
792 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
793 // Force the window flags: this is a fake window, so it is not really
794 // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM
795 // flag because we do know that the next window will take input
796 // focus, so we want to get the IME window up on top of us right away.
797 win.setFlags(
798 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
799 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
800 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
801 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
802 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
803 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
804
805 win.setLayout(WindowManager.LayoutParams.FILL_PARENT,
806 WindowManager.LayoutParams.FILL_PARENT);
807
808 final WindowManager.LayoutParams params = win.getAttributes();
809 params.token = appToken;
810 params.packageName = packageName;
811 params.windowAnimations = win.getWindowStyle().getResourceId(
812 com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
813 params.setTitle("Starting " + packageName);
814
815 try {
816 WindowManagerImpl wm = (WindowManagerImpl)
817 context.getSystemService(Context.WINDOW_SERVICE);
818 View view = win.getDecorView();
819
820 if (win.isFloating()) {
821 // Whoops, there is no way to display an animation/preview
822 // of such a thing! After all that work... let's skip it.
823 // (Note that we must do this here because it is in
824 // getDecorView() where the theme is evaluated... maybe
825 // we should peek the floating attribute from the theme
826 // earlier.)
827 return null;
828 }
829
830 if (localLOGV) Log.v(
831 TAG, "Adding starting window for " + packageName
832 + " / " + appToken + ": "
833 + (view.getParent() != null ? view : null));
834
835 wm.addView(view, params);
836
837 // Only return the view if it was successfully added to the
838 // window manager... which we can tell by it having a parent.
839 return view.getParent() != null ? view : null;
840 } catch (WindowManagerImpl.BadTokenException e) {
841 // ignore
842 Log.w(TAG, appToken + " already running, starting window not displayed");
843 }
844
845 return null;
846 }
847
848 /** {@inheritDoc} */
849 public void removeStartingWindow(IBinder appToken, View window) {
850 // RuntimeException e = new RuntimeException();
851 // Log.i(TAG, "remove " + appToken + " " + window, e);
852
853 if (localLOGV) Log.v(
854 TAG, "Removing starting window for " + appToken + ": " + window);
855
856 if (window != null) {
857 WindowManagerImpl wm = (WindowManagerImpl) mContext.getSystemService(Context.WINDOW_SERVICE);
858 wm.removeView(window);
859 }
860 }
861
862 /**
863 * Preflight adding a window to the system.
864 *
865 * Currently enforces that three window types are singletons:
866 * <ul>
867 * <li>STATUS_BAR_TYPE</li>
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800868 * <li>KEYGUARD_TYPE</li>
869 * </ul>
870 *
871 * @param win The window to be added
872 * @param attrs Information about the window to be added
873 *
874 * @return If ok, WindowManagerImpl.ADD_OKAY. If too many singletons, WindowManagerImpl.ADD_MULTIPLE_SINGLETON
875 */
876 public int prepareAddWindowLw(WindowState win, WindowManager.LayoutParams attrs) {
877 switch (attrs.type) {
878 case TYPE_STATUS_BAR:
879 if (mStatusBar != null) {
880 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
881 }
882 mStatusBar = win;
883 break;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800884 case TYPE_KEYGUARD:
885 if (mKeyguard != null) {
886 return WindowManagerImpl.ADD_MULTIPLE_SINGLETON;
887 }
888 mKeyguard = win;
889 break;
890 }
891 return WindowManagerImpl.ADD_OKAY;
892 }
893
894 /** {@inheritDoc} */
895 public void removeWindowLw(WindowState win) {
896 if (mStatusBar == win) {
897 mStatusBar = null;
898 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800899 else if (mKeyguard == win) {
900 mKeyguard = null;
901 }
902 }
903
904 static final boolean PRINT_ANIM = false;
905
906 /** {@inheritDoc} */
907 public int selectAnimationLw(WindowState win, int transit) {
908 if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
909 + ": transit=" + transit);
910 if (transit == TRANSIT_PREVIEW_DONE) {
911 if (win.hasAppShownWindows()) {
912 if (PRINT_ANIM) Log.i(TAG, "**** STARTING EXIT");
913 return com.android.internal.R.anim.app_starting_exit;
914 }
915 }
916
917 return 0;
918 }
919
Dianne Hackborn01ad2f42009-09-24 19:24:56 -0700920 public Animation createForceHideEnterAnimation() {
921 return AnimationUtils.loadAnimation(mContext,
922 com.android.internal.R.anim.lock_screen_behind_enter);
923 }
924
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800925 static ITelephony getPhoneInterface() {
926 return ITelephony.Stub.asInterface(ServiceManager.checkService(Context.TELEPHONY_SERVICE));
927 }
928
929 static IAudioService getAudioInterface() {
930 return IAudioService.Stub.asInterface(ServiceManager.checkService(Context.AUDIO_SERVICE));
931 }
932
933 boolean keyguardOn() {
934 return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
935 }
936
937 private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
938 WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
939 WindowManager.LayoutParams.TYPE_SYSTEM_ERROR,
940 };
941
942 /** {@inheritDoc} */
943 public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down,
Dianne Hackborn0041e972009-07-24 17:14:43 -0700944 int repeatCount, int flags) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800945 boolean keyguardOn = keyguardOn();
946
947 if (false) {
948 Log.d(TAG, "interceptKeyTi code=" + code + " down=" + down + " repeatCount="
949 + repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
950 }
951
952 // Clear a pending HOME longpress if the user releases Home
953 // TODO: This could probably be inside the next bit of logic, but that code
954 // turned out to be a bit fragile so I'm doing it here explicitly, for now.
955 if ((code == KeyEvent.KEYCODE_HOME) && !down) {
956 mHandler.removeCallbacks(mHomeLongPress);
957 }
958
959 // If the HOME button is currently being held, then we do special
960 // chording with it.
961 if (mHomePressed) {
962
963 // If we have released the home key, and didn't do anything else
964 // while it was pressed, then it is time to go home!
965 if (code == KeyEvent.KEYCODE_HOME) {
966 if (!down) {
967 mHomePressed = false;
968
Dianne Hackborn0041e972009-07-24 17:14:43 -0700969 if ((flags&KeyEvent.FLAG_CANCELED) == 0) {
970 // If an incoming call is ringing, HOME is totally disabled.
971 // (The user is already on the InCallScreen at this point,
972 // and his ONLY options are to answer or reject the call.)
973 boolean incomingRinging = false;
974 try {
975 ITelephony phoneServ = getPhoneInterface();
976 if (phoneServ != null) {
977 incomingRinging = phoneServ.isRinging();
978 } else {
979 Log.w(TAG, "Unable to find ITelephony interface");
980 }
981 } catch (RemoteException ex) {
982 Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800983 }
Dianne Hackborn0041e972009-07-24 17:14:43 -0700984
985 if (incomingRinging) {
986 Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
987 } else {
988 launchHomeFromHotKey();
989 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800990 } else {
Dianne Hackborn0041e972009-07-24 17:14:43 -0700991 Log.i(TAG, "Ignoring HOME; event canceled.");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800992 }
993 }
994 }
995
996 return true;
997 }
Dianne Hackborn0041e972009-07-24 17:14:43 -0700998
The Android Open Source Project1f838aa2009-03-03 19:32:13 -0800999 // First we always handle the home key here, so applications
1000 // can never break it, although if keyguard is on, we do let
1001 // it handle it, because that gives us the correct 5 second
1002 // timeout.
1003 if (code == KeyEvent.KEYCODE_HOME) {
1004
1005 // If a system window has focus, then it doesn't make sense
1006 // right now to interact with applications.
1007 WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
1008 if (attrs != null) {
1009 final int type = attrs.type;
1010 if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
1011 || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
1012 // the "app" is keyguard, so give it the key
1013 return false;
1014 }
1015 final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
1016 for (int i=0; i<typeCount; i++) {
1017 if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
1018 // don't do anything, but also don't pass it to the app
1019 return true;
1020 }
1021 }
1022 }
1023
1024 if (down && repeatCount == 0) {
1025 if (!keyguardOn) {
1026 mHandler.postDelayed(mHomeLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
1027 }
1028 mHomePressed = true;
1029 }
1030 return true;
1031 } else if (code == KeyEvent.KEYCODE_MENU) {
1032 // Hijack modified menu keys for debugging features
1033 final int chordBug = KeyEvent.META_SHIFT_ON;
1034
1035 if (down && repeatCount == 0) {
1036 if (mEnableShiftMenuBugReports && (metaKeys & chordBug) == chordBug) {
1037 Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
1038 mContext.sendOrderedBroadcast(intent, null);
1039 return true;
1040 } else if (SHOW_PROCESSES_ON_ALT_MENU &&
1041 (metaKeys & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
1042 Intent service = new Intent();
1043 service.setClassName(mContext, "com.android.server.LoadAverageService");
1044 ContentResolver res = mContext.getContentResolver();
1045 boolean shown = Settings.System.getInt(
1046 res, Settings.System.SHOW_PROCESSES, 0) != 0;
1047 if (!shown) {
1048 mContext.startService(service);
1049 } else {
1050 mContext.stopService(service);
1051 }
1052 Settings.System.putInt(
1053 res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
1054 return true;
1055 }
1056 }
1057 } else if (code == KeyEvent.KEYCODE_NOTIFICATION) {
1058 if (down) {
1059 // this key doesn't exist on current hardware, but if a device
1060 // didn't have a touchscreen, it would want one of these to open
1061 // the status bar.
1062 IStatusBar sbs = IStatusBar.Stub.asInterface(ServiceManager.getService("statusbar"));
1063 if (sbs != null) {
1064 try {
1065 sbs.toggle();
1066 } catch (RemoteException e) {
1067 // we're screwed anyway, since it's in this process
1068 throw new RuntimeException(e);
1069 }
1070 }
1071 }
1072 return true;
1073 } else if (code == KeyEvent.KEYCODE_SEARCH) {
1074 if (down) {
1075 if (repeatCount == 0) {
1076 mSearchKeyPressed = true;
1077 }
1078 } else {
1079 mSearchKeyPressed = false;
1080
1081 if (mConsumeSearchKeyUp) {
1082 // Consume the up-event
1083 mConsumeSearchKeyUp = false;
1084 return true;
1085 }
1086 }
1087 }
1088
1089 // Shortcuts are invoked through Search+key, so intercept those here
1090 if (mSearchKeyPressed) {
1091 if (down && repeatCount == 0 && !keyguardOn) {
1092 Intent shortcutIntent = mShortcutManager.getIntent(code, metaKeys);
1093 if (shortcutIntent != null) {
1094 shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1095 mContext.startActivity(shortcutIntent);
1096
1097 /*
1098 * We launched an app, so the up-event of the search key
1099 * should be consumed
1100 */
1101 mConsumeSearchKeyUp = true;
1102 return true;
1103 }
1104 }
1105 }
1106
1107 return false;
1108 }
1109
1110 /**
1111 * A home key -> launch home action was detected. Take the appropriate action
1112 * given the situation with the keyguard.
1113 */
1114 void launchHomeFromHotKey() {
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08001115 if (mKeyguardMediator.isShowingAndNotHidden()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001116 // don't launch home if keyguard showing
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001117 } else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001118 // when in keyguard restricted mode, must first verify unlock
1119 // before launching home
1120 mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {
1121 public void onKeyguardExitResult(boolean success) {
1122 if (success) {
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07001123 try {
1124 ActivityManagerNative.getDefault().stopAppSwitches();
1125 } catch (RemoteException e) {
1126 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05001127 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001128 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001129 }
1130 }
1131 });
1132 } else {
1133 // no keyguard stuff to worry about, just launch home!
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07001134 try {
1135 ActivityManagerNative.getDefault().stopAppSwitches();
1136 } catch (RemoteException e) {
1137 }
Joe Onoratof275f0c2009-11-24 16:11:13 -05001138 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001139 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001140 }
1141 }
1142
1143 public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
1144 final int fl = attrs.flags;
1145
1146 if ((fl &
1147 (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
1148 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
1149 contentInset.set(mCurLeft, mCurTop, mW - mCurRight, mH - mCurBottom);
1150 } else {
1151 contentInset.setEmpty();
1152 }
1153 }
1154
1155 /** {@inheritDoc} */
1156 public void beginLayoutLw(int displayWidth, int displayHeight) {
1157 mW = displayWidth;
1158 mH = displayHeight;
1159 mDockLeft = mContentLeft = mCurLeft = 0;
1160 mDockTop = mContentTop = mCurTop = 0;
1161 mDockRight = mContentRight = mCurRight = displayWidth;
1162 mDockBottom = mContentBottom = mCurBottom = displayHeight;
1163 mDockLayer = 0x10000000;
1164
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001165 mTopFullscreenOpaqueWindowState = null;
1166 mForceStatusBar = false;
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001167 mHideLockScreen = false;
1168 mDismissKeyguard = false;
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001169
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001170 // decide where the status bar goes ahead of time
1171 if (mStatusBar != null) {
1172 final Rect pf = mTmpParentFrame;
1173 final Rect df = mTmpDisplayFrame;
1174 final Rect vf = mTmpVisibleFrame;
1175 pf.left = df.left = vf.left = 0;
1176 pf.top = df.top = vf.top = 0;
1177 pf.right = df.right = vf.right = displayWidth;
1178 pf.bottom = df.bottom = vf.bottom = displayHeight;
1179
1180 mStatusBar.computeFrameLw(pf, df, vf, vf);
1181 if (mStatusBar.isVisibleLw()) {
1182 // If the status bar is hidden, we don't want to cause
1183 // windows behind it to scroll.
1184 mDockTop = mContentTop = mCurTop = mStatusBar.getFrameLw().bottom;
The Android Open Source Project11267662009-03-18 17:39:47 -07001185 if (DEBUG_LAYOUT) Log.v(TAG, "Status bar: mDockBottom="
1186 + mDockBottom + " mContentBottom="
1187 + mContentBottom + " mCurBottom=" + mCurBottom);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001188 }
1189 }
1190 }
1191
1192 void setAttachedWindowFrames(WindowState win, int fl, int sim,
1193 WindowState attached, boolean insetDecors, Rect pf, Rect df, Rect cf, Rect vf) {
1194 if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
1195 // Here's a special case: if this attached window is a panel that is
1196 // above the dock window, and the window it is attached to is below
1197 // the dock window, then the frames we computed for the window it is
1198 // attached to can not be used because the dock is effectively part
1199 // of the underlying window and the attached window is floating on top
1200 // of the whole thing. So, we ignore the attached window and explicitly
1201 // compute the frames that would be appropriate without the dock.
1202 df.left = cf.left = vf.left = mDockLeft;
1203 df.top = cf.top = vf.top = mDockTop;
1204 df.right = cf.right = vf.right = mDockRight;
1205 df.bottom = cf.bottom = vf.bottom = mDockBottom;
1206 } else {
1207 // The effective display frame of the attached window depends on
1208 // whether it is taking care of insetting its content. If not,
1209 // we need to use the parent's content frame so that the entire
1210 // window is positioned within that content. Otherwise we can use
1211 // the display frame and let the attached window take care of
1212 // positioning its content appropriately.
1213 if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
1214 cf.set(attached.getDisplayFrameLw());
1215 } else {
1216 // If the window is resizing, then we want to base the content
1217 // frame on our attached content frame to resize... however,
1218 // things can be tricky if the attached window is NOT in resize
1219 // mode, in which case its content frame will be larger.
1220 // Ungh. So to deal with that, make sure the content frame
1221 // we end up using is not covering the IM dock.
1222 cf.set(attached.getContentFrameLw());
1223 if (attached.getSurfaceLayer() < mDockLayer) {
1224 if (cf.left < mContentLeft) cf.left = mContentLeft;
1225 if (cf.top < mContentTop) cf.top = mContentTop;
1226 if (cf.right > mContentRight) cf.right = mContentRight;
1227 if (cf.bottom > mContentBottom) cf.bottom = mContentBottom;
1228 }
1229 }
1230 df.set(insetDecors ? attached.getDisplayFrameLw() : cf);
1231 vf.set(attached.getVisibleFrameLw());
1232 }
1233 // The LAYOUT_IN_SCREEN flag is used to determine whether the attached
1234 // window should be positioned relative to its parent or the entire
1235 // screen.
1236 pf.set((fl & FLAG_LAYOUT_IN_SCREEN) == 0
1237 ? attached.getFrameLw() : df);
1238 }
1239
1240 /** {@inheritDoc} */
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001241 public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
1242 WindowState attached) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001243 // we've already done the status bar
1244 if (win == mStatusBar) {
1245 return;
1246 }
1247
1248 if (false) {
1249 if ("com.google.android.youtube".equals(attrs.packageName)
1250 && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
1251 Log.i(TAG, "GOTCHA!");
1252 }
1253 }
1254
1255 final int fl = attrs.flags;
1256 final int sim = attrs.softInputMode;
1257
1258 final Rect pf = mTmpParentFrame;
1259 final Rect df = mTmpDisplayFrame;
1260 final Rect cf = mTmpContentFrame;
1261 final Rect vf = mTmpVisibleFrame;
1262
1263 if (attrs.type == TYPE_INPUT_METHOD) {
1264 pf.left = df.left = cf.left = vf.left = mDockLeft;
1265 pf.top = df.top = cf.top = vf.top = mDockTop;
1266 pf.right = df.right = cf.right = vf.right = mDockRight;
1267 pf.bottom = df.bottom = cf.bottom = vf.bottom = mDockBottom;
1268 // IM dock windows always go to the bottom of the screen.
1269 attrs.gravity = Gravity.BOTTOM;
1270 mDockLayer = win.getSurfaceLayer();
1271 } else {
1272 if ((fl &
1273 (FLAG_LAYOUT_IN_SCREEN | FLAG_FULLSCREEN | FLAG_LAYOUT_INSET_DECOR))
1274 == (FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR)) {
1275 // This is the case for a normal activity window: we want it
1276 // to cover all of the screen space, and it can take care of
1277 // moving its contents to account for screen decorations that
1278 // intrude into that space.
1279 if (attached != null) {
1280 // If this window is attached to another, our display
1281 // frame is the same as the one we are attached to.
1282 setAttachedWindowFrames(win, fl, sim, attached, true, pf, df, cf, vf);
1283 } else {
1284 pf.left = df.left = 0;
1285 pf.top = df.top = 0;
1286 pf.right = df.right = mW;
1287 pf.bottom = df.bottom = mH;
1288 if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
1289 cf.left = mDockLeft;
1290 cf.top = mDockTop;
1291 cf.right = mDockRight;
1292 cf.bottom = mDockBottom;
1293 } else {
1294 cf.left = mContentLeft;
1295 cf.top = mContentTop;
1296 cf.right = mContentRight;
1297 cf.bottom = mContentBottom;
1298 }
1299 vf.left = mCurLeft;
1300 vf.top = mCurTop;
1301 vf.right = mCurRight;
1302 vf.bottom = mCurBottom;
1303 }
1304 } else if ((fl & FLAG_LAYOUT_IN_SCREEN) != 0) {
1305 // A window that has requested to fill the entire screen just
1306 // gets everything, period.
1307 pf.left = df.left = cf.left = 0;
1308 pf.top = df.top = cf.top = 0;
1309 pf.right = df.right = cf.right = mW;
1310 pf.bottom = df.bottom = cf.bottom = mH;
1311 vf.left = mCurLeft;
1312 vf.top = mCurTop;
1313 vf.right = mCurRight;
1314 vf.bottom = mCurBottom;
1315 } else if (attached != null) {
1316 // A child window should be placed inside of the same visible
1317 // frame that its parent had.
1318 setAttachedWindowFrames(win, fl, sim, attached, false, pf, df, cf, vf);
1319 } else {
1320 // Otherwise, a normal window must be placed inside the content
1321 // of all screen decorations.
1322 pf.left = mContentLeft;
1323 pf.top = mContentTop;
1324 pf.right = mContentRight;
1325 pf.bottom = mContentBottom;
1326 if ((sim & SOFT_INPUT_MASK_ADJUST) != SOFT_INPUT_ADJUST_RESIZE) {
1327 df.left = cf.left = mDockLeft;
1328 df.top = cf.top = mDockTop;
1329 df.right = cf.right = mDockRight;
1330 df.bottom = cf.bottom = mDockBottom;
1331 } else {
1332 df.left = cf.left = mContentLeft;
1333 df.top = cf.top = mContentTop;
1334 df.right = cf.right = mContentRight;
1335 df.bottom = cf.bottom = mContentBottom;
1336 }
1337 vf.left = mCurLeft;
1338 vf.top = mCurTop;
1339 vf.right = mCurRight;
1340 vf.bottom = mCurBottom;
1341 }
1342 }
1343
1344 if ((fl & FLAG_LAYOUT_NO_LIMITS) != 0) {
1345 df.left = df.top = cf.left = cf.top = vf.left = vf.top = -10000;
1346 df.right = df.bottom = cf.right = cf.bottom = vf.right = vf.bottom = 10000;
1347 }
1348
The Android Open Source Project11267662009-03-18 17:39:47 -07001349 if (DEBUG_LAYOUT) Log.v(TAG, "Compute frame " + attrs.getTitle()
1350 + ": sim=#" + Integer.toHexString(sim)
1351 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
1352 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
1353
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001354 if (false) {
1355 if ("com.google.android.youtube".equals(attrs.packageName)
1356 && attrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
1357 if (true || localLOGV) Log.v(TAG, "Computing frame of " + win +
The Android Open Source Project11267662009-03-18 17:39:47 -07001358 ": sim=#" + Integer.toHexString(sim)
1359 + " pf=" + pf.toShortString() + " df=" + df.toShortString()
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001360 + " cf=" + cf.toShortString() + " vf=" + vf.toShortString());
1361 }
1362 }
1363
1364 win.computeFrameLw(pf, df, cf, vf);
1365
Dianne Hackborne7c8c7c2009-10-07 21:27:43 -07001366 if (mTopFullscreenOpaqueWindowState == null &&
1367 win.isVisibleOrBehindKeyguardLw()) {
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001368 if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
1369 mForceStatusBar = true;
Dianne Hackbornd70bc2f2009-10-06 23:25:51 -07001370 }
Dianne Hackborne7c8c7c2009-10-07 21:27:43 -07001371 if (attrs.type >= FIRST_APPLICATION_WINDOW
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001372 && attrs.type <= LAST_APPLICATION_WINDOW
1373 && win.fillsScreenLw(mW, mH, false, false)) {
1374 if (DEBUG_LAYOUT) Log.v(TAG, "Fullscreen window: " + win);
1375 mTopFullscreenOpaqueWindowState = win;
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001376 if ((attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
Dianne Hackborn05726582009-09-22 17:28:24 -07001377 if (localLOGV) Log.v(TAG, "Setting mHideLockScreen to true by win " + win);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001378 mHideLockScreen = true;
1379 }
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001380 }
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001381 if ((attrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
Dianne Hackborn05726582009-09-22 17:28:24 -07001382 if (localLOGV) Log.v(TAG, "Setting mDismissKeyguard to true by win " + win);
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001383 mDismissKeyguard = true;
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07001384 }
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001385 }
1386
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001387 // Dock windows carve out the bottom of the screen, so normal windows
1388 // can't appear underneath them.
1389 if (attrs.type == TYPE_INPUT_METHOD && !win.getGivenInsetsPendingLw()) {
1390 int top = win.getContentFrameLw().top;
1391 top += win.getGivenContentInsetsLw().top;
1392 if (mContentBottom > top) {
1393 mContentBottom = top;
1394 }
1395 top = win.getVisibleFrameLw().top;
1396 top += win.getGivenVisibleInsetsLw().top;
1397 if (mCurBottom > top) {
1398 mCurBottom = top;
1399 }
The Android Open Source Project11267662009-03-18 17:39:47 -07001400 if (DEBUG_LAYOUT) Log.v(TAG, "Input method: mDockBottom="
1401 + mDockBottom + " mContentBottom="
1402 + mContentBottom + " mCurBottom=" + mCurBottom);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001403 }
1404 }
1405
1406 /** {@inheritDoc} */
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001407 public int finishLayoutLw() {
1408 int changes = 0;
The Android Open Source Projectc84bf282009-03-09 11:52:14 -07001409 boolean hiding = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001410 if (mStatusBar != null) {
Dianne Hackbornd70bc2f2009-10-06 23:25:51 -07001411 if (localLOGV) Log.i(TAG, "force=" + mForceStatusBar
1412 + " top=" + mTopFullscreenOpaqueWindowState);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001413 if (mForceStatusBar) {
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001414 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001415 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001416 } else if (mTopFullscreenOpaqueWindowState != null) {
1417 //Log.i(TAG, "frame: " + mTopFullscreenOpaqueWindowState.getFrameLw()
1418 // + " shown frame: " + mTopFullscreenOpaqueWindowState.getShownFrameLw());
1419 //Log.i(TAG, "attr: " + mTopFullscreenOpaqueWindowState.getAttrs());
1420 WindowManager.LayoutParams lp =
1421 mTopFullscreenOpaqueWindowState.getAttrs();
1422 boolean hideStatusBar =
1423 (lp.flags & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
1424 if (hideStatusBar) {
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001425 if (DEBUG_LAYOUT) Log.v(TAG, "Hiding status bar");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001426 if (mStatusBar.hideLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Projectc84bf282009-03-09 11:52:14 -07001427 hiding = true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001428 } else {
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001429 if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar");
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001430 if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001431 }
1432 }
1433 }
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07001434 // Hide the key guard if a visible window explicitly specifies that it wants to be displayed
1435 // when the screen is locked
1436 if (mKeyguard != null) {
Dianne Hackborn05726582009-09-22 17:28:24 -07001437 if (localLOGV) Log.v(TAG, "finishLayoutLw::mHideKeyguard="+mHideLockScreen);
1438 if (mDismissKeyguard && !mKeyguardMediator.isSecure()) {
Dianne Hackbornd70bc2f2009-10-06 23:25:51 -07001439 if (mKeyguard.hideLw(false)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001440 changes |= FINISH_LAYOUT_REDO_LAYOUT
1441 | FINISH_LAYOUT_REDO_CONFIG
1442 | FINISH_LAYOUT_REDO_WALLPAPER;
1443 }
Dianne Hackborn05726582009-09-22 17:28:24 -07001444 if (mKeyguardMediator.isShowing()) {
Dianne Hackbornb446e972009-09-20 15:23:25 -07001445 mHandler.post(new Runnable() {
1446 public void run() {
Dianne Hackborn05726582009-09-22 17:28:24 -07001447 mKeyguardMediator.keyguardDone(false, false);
Dianne Hackbornb446e972009-09-20 15:23:25 -07001448 }
1449 });
1450 }
Dianne Hackborn05726582009-09-22 17:28:24 -07001451 } else if (mHideLockScreen) {
Dianne Hackbornd70bc2f2009-10-06 23:25:51 -07001452 if (mKeyguard.hideLw(false)) {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001453 changes |= FINISH_LAYOUT_REDO_LAYOUT
1454 | FINISH_LAYOUT_REDO_CONFIG
1455 | FINISH_LAYOUT_REDO_WALLPAPER;
1456 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05001457 mKeyguardMediator.setHidden(true);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07001458 } else {
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001459 if (mKeyguard.showLw(false)) {
1460 changes |= FINISH_LAYOUT_REDO_LAYOUT
1461 | FINISH_LAYOUT_REDO_CONFIG
1462 | FINISH_LAYOUT_REDO_WALLPAPER;
1463 }
Mike Lockwoodf3bfed52010-01-21 16:38:44 -05001464 mKeyguardMediator.setHidden(false);
Suchi Amalapurapu9cdc9032009-05-14 18:01:07 -07001465 }
1466 }
The Android Open Source Projectc84bf282009-03-09 11:52:14 -07001467
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001468 if (changes != 0 && hiding) {
The Android Open Source Projectc84bf282009-03-09 11:52:14 -07001469 IStatusBar sbs = IStatusBar.Stub.asInterface(ServiceManager.getService("statusbar"));
1470 if (sbs != null) {
1471 try {
1472 // Make sure the window shade is hidden.
1473 sbs.deactivate();
1474 } catch (RemoteException e) {
1475 }
1476 }
1477 }
1478
Dianne Hackborn39c2d712009-09-22 11:41:31 -07001479 return changes;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001480 }
1481
1482 /** {@inheritDoc} */
Dianne Hackborn0ecadf72009-03-31 18:00:37 -07001483 public void beginAnimationLw(int displayWidth, int displayHeight) {
1484 }
1485
1486 /** {@inheritDoc} */
1487 public void animatingWindowLw(WindowState win,
1488 WindowManager.LayoutParams attrs) {
1489 }
1490
1491 /** {@inheritDoc} */
1492 public boolean finishAnimationLw() {
1493 return false;
1494 }
1495
1496 /** {@inheritDoc} */
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001497 public boolean preprocessInputEventTq(RawInputEvent event) {
1498 switch (event.type) {
1499 case RawInputEvent.EV_SW:
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001500 if (event.keycode == RawInputEvent.SW_LID) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001501 // lid changed state
1502 mLidOpen = event.value == 0;
Dianne Hackbornb446e972009-09-20 15:23:25 -07001503 boolean awakeNow = mKeyguardMediator.doLidChangeTq(mLidOpen);
Dianne Hackborn32bc91d2009-03-27 16:16:03 -07001504 updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
Dianne Hackbornb446e972009-09-20 15:23:25 -07001505 if (awakeNow) {
1506 // If the lid opening and we don't have to keep the
1507 // keyguard up, then we can turn on the screen
1508 // immediately.
1509 mKeyguardMediator.pokeWakelock();
1510 } else if (keyguardIsShowingTq()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001511 if (mLidOpen) {
Dianne Hackbornb446e972009-09-20 15:23:25 -07001512 // If we are opening the lid and not hiding the
1513 // keyguard, then we need to have it turn on the
1514 // screen once it is shown.
1515 mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
1516 KeyEvent.KEYCODE_POWER);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001517 }
1518 } else {
1519 // Light up the keyboard if we are sliding up.
1520 if (mLidOpen) {
1521 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
1522 LocalPowerManager.BUTTON_EVENT);
1523 } else {
1524 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
1525 LocalPowerManager.OTHER_EVENT);
1526 }
1527 }
1528 }
1529 }
1530 return false;
1531 }
1532
1533
1534 /** {@inheritDoc} */
1535 public boolean isAppSwitchKeyTqTiLwLi(int keycode) {
1536 return keycode == KeyEvent.KEYCODE_HOME
1537 || keycode == KeyEvent.KEYCODE_ENDCALL;
1538 }
1539
1540 /** {@inheritDoc} */
1541 public boolean isMovementKeyTi(int keycode) {
1542 switch (keycode) {
1543 case KeyEvent.KEYCODE_DPAD_UP:
1544 case KeyEvent.KEYCODE_DPAD_DOWN:
1545 case KeyEvent.KEYCODE_DPAD_LEFT:
1546 case KeyEvent.KEYCODE_DPAD_RIGHT:
1547 return true;
1548 }
1549 return false;
1550 }
1551
1552
1553 /**
1554 * @return Whether a telephone call is in progress right now.
1555 */
1556 boolean isInCall() {
1557 final ITelephony phone = getPhoneInterface();
1558 if (phone == null) {
1559 Log.w(TAG, "couldn't get ITelephony reference");
1560 return false;
1561 }
1562 try {
1563 return phone.isOffhook();
1564 } catch (RemoteException e) {
1565 Log.w(TAG, "ITelephony.isOffhhook threw RemoteException " + e);
1566 return false;
1567 }
1568 }
1569
1570 /**
1571 * @return Whether music is being played right now.
1572 */
1573 boolean isMusicActive() {
Eric Laurent413cb9d2009-07-17 11:52:43 -07001574 final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
1575 if (am == null) {
1576 Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001577 return false;
1578 }
Eric Laurent413cb9d2009-07-17 11:52:43 -07001579 return am.isMusicActive();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001580 }
1581
1582 /**
1583 * Tell the audio service to adjust the volume appropriate to the event.
1584 * @param keycode
1585 */
Mike Lockwooda53e3812009-09-25 10:51:39 -04001586 void handleVolumeKey(int stream, int keycode) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001587 final IAudioService audio = getAudioInterface();
1588 if (audio == null) {
Mike Lockwooda53e3812009-09-25 10:51:39 -04001589 Log.w(TAG, "handleVolumeKey: couldn't get IAudioService reference");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001590 return;
1591 }
1592 try {
1593 // since audio is playing, we shouldn't have to hold a wake lock
1594 // during the call, but we do it as a precaution for the rare possibility
1595 // that the music stops right before we call this
1596 mBroadcastWakeLock.acquire();
Mike Lockwooda53e3812009-09-25 10:51:39 -04001597 audio.adjustStreamVolume(stream,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001598 keycode == KeyEvent.KEYCODE_VOLUME_UP
1599 ? AudioManager.ADJUST_RAISE
1600 : AudioManager.ADJUST_LOWER,
1601 0);
1602 } catch (RemoteException e) {
1603 Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e);
1604 } finally {
1605 mBroadcastWakeLock.release();
1606 }
1607 }
1608
1609 static boolean isMediaKey(int code) {
1610 if (code == KeyEvent.KEYCODE_HEADSETHOOK ||
Andy Stadler8b89d692009-04-10 16:24:49 -07001611 code == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE ||
1612 code == KeyEvent.KEYCODE_MEDIA_STOP ||
1613 code == KeyEvent.KEYCODE_MEDIA_NEXT ||
1614 code == KeyEvent.KEYCODE_MEDIA_PREVIOUS ||
1615 code == KeyEvent.KEYCODE_MEDIA_PREVIOUS ||
1616 code == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001617 return true;
1618 }
1619 return false;
1620 }
1621
1622 /** {@inheritDoc} */
1623 public int interceptKeyTq(RawInputEvent event, boolean screenIsOn) {
1624 int result = ACTION_PASS_TO_USER;
1625 final boolean isWakeKey = isWakeKeyTq(event);
Mike Lockwoodc72b15f2009-11-28 20:58:22 -05001626 // If screen is off then we treat the case where the keyguard is open but hidden
1627 // the same as if it were open and in front.
1628 // This will prevent any keys other than the power button from waking the screen
1629 // when the keyguard is hidden by another activity.
1630 final boolean keyguardActive = (screenIsOn ?
1631 mKeyguardMediator.isShowingAndNotHidden() :
1632 mKeyguardMediator.isShowing());
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001633
1634 if (false) {
1635 Log.d(TAG, "interceptKeyTq event=" + event + " keycode=" + event.keycode
Mike Lockwoodc72b15f2009-11-28 20:58:22 -05001636 + " screenIsOn=" + screenIsOn + " keyguardActive=" + keyguardActive);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001637 }
1638
Mike Lockwoodc72b15f2009-11-28 20:58:22 -05001639 if (keyguardActive) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001640 if (screenIsOn) {
1641 // when the screen is on, always give the event to the keyguard
1642 result |= ACTION_PASS_TO_USER;
1643 } else {
1644 // otherwise, don't pass it to the user
1645 result &= ~ACTION_PASS_TO_USER;
1646
1647 final boolean isKeyDown =
1648 (event.type == RawInputEvent.EV_KEY) && (event.value != 0);
1649 if (isWakeKey && isKeyDown) {
1650
1651 // tell the mediator about a wake key, it may decide to
1652 // turn on the screen depending on whether the key is
1653 // appropriate.
1654 if (!mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(event.keycode)
1655 && (event.keycode == KeyEvent.KEYCODE_VOLUME_DOWN
1656 || event.keycode == KeyEvent.KEYCODE_VOLUME_UP)) {
Mike Lockwood99ff0a82009-12-02 01:37:38 -05001657 // when keyguard is showing and screen off, we need
1658 // to handle the volume key for calls and music here
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001659 if (isInCall()) {
Mike Lockwood99ff0a82009-12-02 01:37:38 -05001660 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, event.keycode);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001661 } else if (isMusicActive()) {
Mike Lockwooda53e3812009-09-25 10:51:39 -04001662 handleVolumeKey(AudioManager.STREAM_MUSIC, event.keycode);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001663 }
1664 }
1665 }
1666 }
1667 } else if (!screenIsOn) {
Mike Lockwooda53e3812009-09-25 10:51:39 -04001668 // If we are in-call with screen off and keyguard is not showing,
1669 // then handle the volume key ourselves.
1670 // This is necessary because the phone app will disable the keyguard
1671 // when the proximity sensor is in use.
1672 if (isInCall() && event.type == RawInputEvent.EV_KEY &&
1673 (event.keycode == KeyEvent.KEYCODE_VOLUME_DOWN
1674 || event.keycode == KeyEvent.KEYCODE_VOLUME_UP)) {
1675 result &= ~ACTION_PASS_TO_USER;
1676 handleVolumeKey(AudioManager.STREAM_VOICE_CALL, event.keycode);
1677 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001678 if (isWakeKey) {
1679 // a wake key has a sole purpose of waking the device; don't pass
1680 // it to the user
1681 result |= ACTION_POKE_USER_ACTIVITY;
1682 result &= ~ACTION_PASS_TO_USER;
1683 }
1684 }
1685
1686 int type = event.type;
1687 int code = event.keycode;
1688 boolean down = event.value != 0;
1689
1690 if (type == RawInputEvent.EV_KEY) {
Dianne Hackborn0041e972009-07-24 17:14:43 -07001691 if (code == KeyEvent.KEYCODE_ENDCALL
1692 || code == KeyEvent.KEYCODE_POWER) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001693 if (down) {
Mike Lockwood2eb47962009-10-23 11:29:52 -04001694 boolean handled = false;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001695 // key repeats are generated by the window manager, and we don't see them
1696 // here, so unless the driver is doing something it shouldn't be, we know
1697 // this is the real press event.
Mike Lockwood75d3caa2009-10-22 13:14:31 -04001698 ITelephony phoneServ = getPhoneInterface();
1699 if (phoneServ != null) {
Dianne Hackborn0041e972009-07-24 17:14:43 -07001700 try {
Mike Lockwood2eb47962009-10-23 11:29:52 -04001701 if (code == KeyEvent.KEYCODE_ENDCALL) {
1702 handled = phoneServ.endCall();
1703 } else if (code == KeyEvent.KEYCODE_POWER && phoneServ.isRinging()) {
1704 // Pressing power during incoming call should silence the ringer
1705 phoneServ.silenceRinger();
1706 handled = true;
Dianne Hackborn0041e972009-07-24 17:14:43 -07001707 }
1708 } catch (RemoteException ex) {
Mike Lockwood75d3caa2009-10-22 13:14:31 -04001709 Log.w(TAG, "ITelephony threw RemoteException" + ex);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001710 }
Mike Lockwood75d3caa2009-10-22 13:14:31 -04001711 } else {
1712 Log.w(TAG, "!!! Unable to find ITelephony interface !!!");
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001713 }
Mike Lockwood75d3caa2009-10-22 13:14:31 -04001714 // power button should turn off screen in addition to hanging up the phone
Mike Lockwood2eb47962009-10-23 11:29:52 -04001715 if ((handled && code != KeyEvent.KEYCODE_POWER) || !screenIsOn) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001716 mShouldTurnOffOnKeyUp = false;
1717 } else {
1718 // only try to turn off the screen if we didn't already hang up
1719 mShouldTurnOffOnKeyUp = true;
Dianne Hackborn0041e972009-07-24 17:14:43 -07001720 mHandler.postDelayed(mPowerLongPress,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001721 ViewConfiguration.getGlobalActionKeyTimeout());
1722 result &= ~ACTION_PASS_TO_USER;
1723 }
1724 } else {
Dianne Hackborn0041e972009-07-24 17:14:43 -07001725 mHandler.removeCallbacks(mPowerLongPress);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001726 if (mShouldTurnOffOnKeyUp) {
1727 mShouldTurnOffOnKeyUp = false;
1728 boolean gohome = (mEndcallBehavior & ENDCALL_HOME) != 0;
1729 boolean sleeps = (mEndcallBehavior & ENDCALL_SLEEPS) != 0;
Mike Lockwoodc72b15f2009-11-28 20:58:22 -05001730 if (keyguardActive
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001731 || (sleeps && !gohome)
1732 || (gohome && !goHome() && sleeps)) {
1733 // they must already be on the keyguad or home screen,
1734 // go to sleep instead
1735 Log.d(TAG, "I'm tired mEndcallBehavior=0x"
1736 + Integer.toHexString(mEndcallBehavior));
1737 result &= ~ACTION_POKE_USER_ACTIVITY;
1738 result |= ACTION_GO_TO_SLEEP;
1739 }
1740 result &= ~ACTION_PASS_TO_USER;
1741 }
1742 }
1743 } else if (isMediaKey(code)) {
1744 // This key needs to be handled even if the screen is off.
1745 // If others need to be handled while it's off, this is a reasonable
1746 // pattern to follow.
1747 if ((result & ACTION_PASS_TO_USER) == 0) {
1748 // Only do this if we would otherwise not pass it to the user. In that
1749 // case, the PhoneWindow class will do the same thing, except it will
1750 // only do it if the showing app doesn't process the key on its own.
1751 KeyEvent keyEvent = new KeyEvent(event.when, event.when,
1752 down ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP,
1753 code, 0);
1754 mBroadcastWakeLock.acquire();
1755 mHandler.post(new PassHeadsetKey(keyEvent));
1756 }
1757 } else if (code == KeyEvent.KEYCODE_CALL) {
1758 // If an incoming call is ringing, answer it!
1759 // (We handle this key here, rather than in the InCallScreen, to make
1760 // sure we'll respond to the key even if the InCallScreen hasn't come to
1761 // the foreground yet.)
1762
1763 // We answer the call on the DOWN event, to agree with
1764 // the "fallback" behavior in the InCallScreen.
1765 if (down) {
1766 try {
1767 ITelephony phoneServ = getPhoneInterface();
1768 if (phoneServ != null) {
1769 if (phoneServ.isRinging()) {
1770 Log.i(TAG, "interceptKeyTq:"
1771 + " CALL key-down while ringing: Answer the call!");
1772 phoneServ.answerRingingCall();
1773
1774 // And *don't* pass this key thru to the current activity
1775 // (which is presumably the InCallScreen.)
1776 result &= ~ACTION_PASS_TO_USER;
1777 }
1778 } else {
1779 Log.w(TAG, "CALL button: Unable to find ITelephony interface");
1780 }
1781 } catch (RemoteException ex) {
1782 Log.w(TAG, "CALL button: RemoteException from getPhoneInterface()", ex);
1783 }
1784 }
1785 } else if ((code == KeyEvent.KEYCODE_VOLUME_UP)
1786 || (code == KeyEvent.KEYCODE_VOLUME_DOWN)) {
1787 // If an incoming call is ringing, either VOLUME key means
1788 // "silence ringer". We handle these keys here, rather than
1789 // in the InCallScreen, to make sure we'll respond to them
1790 // even if the InCallScreen hasn't come to the foreground yet.
1791
1792 // Look for the DOWN event here, to agree with the "fallback"
1793 // behavior in the InCallScreen.
1794 if (down) {
1795 try {
1796 ITelephony phoneServ = getPhoneInterface();
1797 if (phoneServ != null) {
1798 if (phoneServ.isRinging()) {
1799 Log.i(TAG, "interceptKeyTq:"
1800 + " VOLUME key-down while ringing: Silence ringer!");
1801 // Silence the ringer. (It's safe to call this
1802 // even if the ringer has already been silenced.)
1803 phoneServ.silenceRinger();
1804
1805 // And *don't* pass this key thru to the current activity
1806 // (which is probably the InCallScreen.)
1807 result &= ~ACTION_PASS_TO_USER;
1808 }
1809 } else {
1810 Log.w(TAG, "VOLUME button: Unable to find ITelephony interface");
1811 }
1812 } catch (RemoteException ex) {
1813 Log.w(TAG, "VOLUME button: RemoteException from getPhoneInterface()", ex);
1814 }
1815 }
1816 }
1817 }
1818
1819 return result;
1820 }
1821
1822 class PassHeadsetKey implements Runnable {
1823 KeyEvent mKeyEvent;
1824
1825 PassHeadsetKey(KeyEvent keyEvent) {
1826 mKeyEvent = keyEvent;
1827 }
1828
1829 public void run() {
1830 if (ActivityManagerNative.isSystemReady()) {
1831 Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON, null);
1832 intent.putExtra(Intent.EXTRA_KEY_EVENT, mKeyEvent);
1833 mContext.sendOrderedBroadcast(intent, null, mBroadcastDone,
1834 mHandler, Activity.RESULT_OK, null, null);
1835 }
1836 }
1837 }
1838
1839 BroadcastReceiver mBroadcastDone = new BroadcastReceiver() {
1840 public void onReceive(Context context, Intent intent) {
1841 mBroadcastWakeLock.release();
1842 }
1843 };
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001844
Dianne Hackborn80fa1662009-10-07 14:02:10 -07001845 BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
Dianne Hackbornf54c8f92009-09-19 14:03:57 -07001846 public void onReceive(Context context, Intent intent) {
Dianne Hackborn80fa1662009-10-07 14:02:10 -07001847 updatePlugged(intent);
1848 updateDockKeepingScreenOn();
Dianne Hackbornf54c8f92009-09-19 14:03:57 -07001849 }
1850 };
1851
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001852 BroadcastReceiver mDockReceiver = new BroadcastReceiver() {
1853 public void onReceive(Context context, Intent intent) {
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001854 mDockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001855 Intent.EXTRA_DOCK_STATE_UNDOCKED);
Dianne Hackborn80fa1662009-10-07 14:02:10 -07001856 boolean watchBattery = mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED;
1857 if (watchBattery != mRegisteredBatteryReceiver) {
1858 mRegisteredBatteryReceiver = watchBattery;
1859 if (watchBattery) {
1860 updatePlugged(mContext.registerReceiver(mBatteryReceiver,
1861 mBatteryStatusFilter));
1862 } else {
1863 mContext.unregisterReceiver(mBatteryReceiver);
1864 }
1865 }
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001866 updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
Dianne Hackborn80fa1662009-10-07 14:02:10 -07001867 updateDockKeepingScreenOn();
Mike Lockwoode9867d22009-09-20 01:59:02 -04001868 updateOrientationListenerLp();
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001869 }
1870 };
1871
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001872 /** {@inheritDoc} */
1873 public boolean isWakeRelMovementTq(int device, int classes,
1874 RawInputEvent event) {
1875 // if it's tagged with one of the wake bits, it wakes up the device
1876 return ((event.flags & (FLAG_WAKE | FLAG_WAKE_DROPPED)) != 0);
1877 }
1878
1879 /** {@inheritDoc} */
1880 public boolean isWakeAbsMovementTq(int device, int classes,
1881 RawInputEvent event) {
1882 // if it's tagged with one of the wake bits, it wakes up the device
1883 return ((event.flags & (FLAG_WAKE | FLAG_WAKE_DROPPED)) != 0);
1884 }
1885
1886 /**
1887 * Given the current state of the world, should this key wake up the device?
1888 */
1889 protected boolean isWakeKeyTq(RawInputEvent event) {
1890 // There are not key maps for trackball devices, but we'd still
1891 // like to have pressing it wake the device up, so force it here.
1892 int keycode = event.keycode;
1893 int flags = event.flags;
1894 if (keycode == RawInputEvent.BTN_MOUSE) {
1895 flags |= WindowManagerPolicy.FLAG_WAKE;
1896 }
1897 return (flags
1898 & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
1899 }
1900
1901 /** {@inheritDoc} */
1902 public void screenTurnedOff(int why) {
Dianne Hackborn74489012009-03-24 20:50:09 -07001903 EventLog.writeEvent(70000, 0);
1904 mKeyguardMediator.onScreenTurnedOff(why);
The Android Open Source Project0727d222009-03-11 12:11:58 -07001905 synchronized (mLock) {
The Android Open Source Project0727d222009-03-11 12:11:58 -07001906 mScreenOn = false;
1907 updateOrientationListenerLp();
1908 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001909 }
1910
1911 /** {@inheritDoc} */
1912 public void screenTurnedOn() {
Dianne Hackborn74489012009-03-24 20:50:09 -07001913 EventLog.writeEvent(70000, 1);
1914 mKeyguardMediator.onScreenTurnedOn();
The Android Open Source Project0727d222009-03-11 12:11:58 -07001915 synchronized (mLock) {
The Android Open Source Project0727d222009-03-11 12:11:58 -07001916 mScreenOn = true;
1917 updateOrientationListenerLp();
1918 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001919 }
1920
1921 /** {@inheritDoc} */
1922 public void enableKeyguard(boolean enabled) {
1923 mKeyguardMediator.setKeyguardEnabled(enabled);
1924 }
1925
1926 /** {@inheritDoc} */
1927 public void exitKeyguardSecurely(OnKeyguardExitResult callback) {
1928 mKeyguardMediator.verifyUnlock(callback);
1929 }
1930
1931 /** {@inheritDoc} */
1932 public boolean keyguardIsShowingTq() {
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08001933 return mKeyguardMediator.isShowingAndNotHidden();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001934 }
1935
1936 /** {@inheritDoc} */
1937 public boolean inKeyguardRestrictedKeyInputMode() {
1938 return mKeyguardMediator.isInputRestricted();
1939 }
1940
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001941 void sendCloseSystemWindows() {
1942 sendCloseSystemWindows(mContext, null);
1943 }
1944
1945 void sendCloseSystemWindows(String reason) {
1946 sendCloseSystemWindows(mContext, reason);
1947 }
1948
1949 static void sendCloseSystemWindows(Context context, String reason) {
1950 if (ActivityManagerNative.isSystemReady()) {
Dianne Hackborn94a679d2009-07-28 17:51:07 -07001951 try {
1952 ActivityManagerNative.getDefault().closeSystemDialogs(reason);
1953 } catch (RemoteException e) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001954 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001955 }
1956 }
1957
The Android Open Source Project0727d222009-03-11 12:11:58 -07001958 public int rotationForOrientationLw(int orientation, int lastRotation,
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001959 boolean displayEnabled) {
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07001960
1961 if (mPortraitRotation < 0) {
1962 // Initialize the rotation angles for each orientation once.
1963 Display d = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
1964 .getDefaultDisplay();
1965 if (d.getWidth() > d.getHeight()) {
1966 mPortraitRotation = Surface.ROTATION_90;
1967 mLandscapeRotation = Surface.ROTATION_0;
1968 } else {
1969 mPortraitRotation = Surface.ROTATION_0;
1970 mLandscapeRotation = Surface.ROTATION_90;
1971 }
1972 }
1973
The Android Open Source Project0727d222009-03-11 12:11:58 -07001974 synchronized (mLock) {
1975 switch (orientation) {
1976 case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE:
1977 //always return landscape if orientation set to landscape
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07001978 return mLandscapeRotation;
The Android Open Source Project0727d222009-03-11 12:11:58 -07001979 case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT:
1980 //always return portrait if orientation set to portrait
Mitsuru Oshima831d0d92009-06-16 18:27:18 -07001981 return mPortraitRotation;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08001982 }
The Android Open Source Project0727d222009-03-11 12:11:58 -07001983 // case for nosensor meaning ignore sensor and consider only lid
1984 // or orientation sensor disabled
1985 //or case.unspecified
1986 if (mLidOpen) {
Mike Lockwood1753f7f2009-08-24 14:49:07 -07001987 return mLidOpenRotation;
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04001988 } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
1989 return mCarDockRotation;
1990 } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
1991 return mDeskDockRotation;
The Android Open Source Project0727d222009-03-11 12:11:58 -07001992 } else {
Dianne Hackborn03759ed2009-03-27 16:04:08 -07001993 if (useSensorForOrientationLp(orientation)) {
The Android Open Source Project0727d222009-03-11 12:11:58 -07001994 // If the user has enabled auto rotation by default, do it.
Dianne Hackborn03759ed2009-03-27 16:04:08 -07001995 int curRotation = mOrientationListener.getCurrentRotation();
1996 return curRotation >= 0 ? curRotation : lastRotation;
The Android Open Source Project0727d222009-03-11 12:11:58 -07001997 }
1998 return Surface.ROTATION_0;
1999 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002000 }
2001 }
2002
2003 public boolean detectSafeMode() {
2004 try {
2005 int menuState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_MENU);
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002006 int sState = mWindowManager.getKeycodeState(KeyEvent.KEYCODE_S);
Dianne Hackborna8730f92009-11-17 15:53:36 -08002007 int dpadState = mWindowManager.getDPadKeycodeState(KeyEvent.KEYCODE_DPAD_CENTER);
2008 int trackballState = mWindowManager.getTrackballScancodeState(RawInputEvent.BTN_MOUSE);
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002009 mSafeMode = menuState > 0 || sState > 0 || dpadState > 0 || trackballState > 0;
2010 performHapticFeedbackLw(null, mSafeMode
2011 ? HapticFeedbackConstants.SAFE_MODE_ENABLED
2012 : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
Dianne Hackborn73b1ec82009-10-04 13:33:00 -07002013 if (mSafeMode) {
2014 Log.i(TAG, "SAFE MODE ENABLED (menu=" + menuState + " s=" + sState
2015 + " dpad=" + dpadState + " trackball=" + trackballState + ")");
2016 } else {
2017 Log.i(TAG, "SAFE MODE not enabled");
2018 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002019 return mSafeMode;
2020 } catch (RemoteException e) {
2021 // Doom! (it's also local)
2022 throw new RuntimeException("window manager dead");
2023 }
2024 }
2025
Dianne Hackborn181ceb52009-08-27 22:16:40 -07002026 static long[] getLongIntArray(Resources r, int resid) {
2027 int[] ar = r.getIntArray(resid);
2028 if (ar == null) {
2029 return null;
2030 }
2031 long[] out = new long[ar.length];
2032 for (int i=0; i<ar.length; i++) {
2033 out[i] = ar[i];
2034 }
2035 return out;
2036 }
2037
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002038 /** {@inheritDoc} */
2039 public void systemReady() {
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002040 // tell the keyguard
2041 mKeyguardMediator.onSystemReady();
2042 android.os.SystemProperties.set("dev.bootcomplete", "1");
2043 synchronized (mLock) {
2044 updateOrientationListenerLp();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002045 }
2046 }
2047
2048
2049 /** {@inheritDoc} */
2050 public void enableScreenAfterBoot() {
2051 readLidState();
Dianne Hackborn32bc91d2009-03-27 16:16:03 -07002052 updateRotation(Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002053 }
2054
Dianne Hackborn80fa1662009-10-07 14:02:10 -07002055 void updateDockKeepingScreenOn() {
Dianne Hackborn05726582009-09-22 17:28:24 -07002056 if (mPlugged != 0) {
2057 if (localLOGV) Log.v(TAG, "Update: mDockState=" + mDockState
2058 + " mPlugged=" + mPlugged
2059 + " mCarDockKeepsScreenOn" + mCarDockKeepsScreenOn
2060 + " mDeskDockKeepsScreenOn" + mDeskDockKeepsScreenOn);
Dianne Hackbornf54c8f92009-09-19 14:03:57 -07002061 if (mDockState == Intent.EXTRA_DOCK_STATE_CAR
Dianne Hackborn05726582009-09-22 17:28:24 -07002062 && (mPlugged&mCarDockKeepsScreenOn) != 0) {
Dianne Hackbornf54c8f92009-09-19 14:03:57 -07002063 if (!mDockWakeLock.isHeld()) {
2064 mDockWakeLock.acquire();
2065 }
2066 return;
2067 } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK
Dianne Hackborn05726582009-09-22 17:28:24 -07002068 && (mPlugged&mDeskDockKeepsScreenOn) != 0) {
Dianne Hackbornf54c8f92009-09-19 14:03:57 -07002069 if (!mDockWakeLock.isHeld()) {
2070 mDockWakeLock.acquire();
2071 }
2072 return;
2073 }
2074 }
2075
2076 if (mDockWakeLock.isHeld()) {
2077 mDockWakeLock.release();
2078 }
2079 }
2080
Dianne Hackborn03759ed2009-03-27 16:04:08 -07002081 void updateRotation(int animFlags) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002082 mPowerManager.setKeyboardVisibility(mLidOpen);
Mike Lockwood1753f7f2009-08-24 14:49:07 -07002083 int rotation = Surface.ROTATION_0;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002084 if (mLidOpen) {
Mike Lockwood1753f7f2009-08-24 14:49:07 -07002085 rotation = mLidOpenRotation;
Mike Lockwood2d1efbd2009-09-16 12:15:53 -04002086 } else if (mDockState == Intent.EXTRA_DOCK_STATE_CAR && mCarDockRotation >= 0) {
2087 rotation = mCarDockRotation;
2088 } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK && mDeskDockRotation >= 0) {
2089 rotation = mDeskDockRotation;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002090 }
2091 //if lid is closed orientation will be portrait
2092 try {
2093 //set orientation on WindowManager
Dianne Hackborn32bc91d2009-03-27 16:16:03 -07002094 mWindowManager.setRotation(rotation, true,
2095 mFancyRotationAnimation | animFlags);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002096 } catch (RemoteException e) {
2097 // Ignore
2098 }
2099 }
2100
2101 /**
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002102 * Return an Intent to launch the currently active dock as home. Returns
2103 * null if the standard home should be launched.
2104 * @return
2105 */
2106 Intent createHomeDockIntent() {
2107 if (mDockState == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
2108 return null;
2109 }
2110
2111 Intent intent;
2112 if (mDockState == Intent.EXTRA_DOCK_STATE_CAR) {
2113 intent = mCarDockIntent;
2114 } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
2115 intent = mDeskDockIntent;
2116 } else {
2117 Log.w(TAG, "Unknown dock state: " + mDockState);
2118 return null;
2119 }
2120
2121 ActivityInfo ai = intent.resolveActivityInfo(
2122 mContext.getPackageManager(), PackageManager.GET_META_DATA);
2123 if (ai == null) {
2124 return null;
2125 }
2126
2127 if (ai.metaData != null && ai.metaData.getBoolean(Intent.METADATA_DOCK_HOME)) {
2128 intent = new Intent(intent);
2129 intent.setClassName(ai.packageName, ai.name);
2130 return intent;
2131 }
2132
2133 return null;
2134 }
2135
2136 void startDockOrHome() {
2137 Intent dock = createHomeDockIntent();
2138 if (dock != null) {
2139 try {
2140 mContext.startActivity(dock);
2141 return;
2142 } catch (ActivityNotFoundException e) {
2143 }
2144 }
2145 mContext.startActivity(mHomeIntent);
2146 }
2147
2148 /**
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002149 * goes to the home screen
2150 * @return whether it did anything
2151 */
2152 boolean goHome() {
2153 if (false) {
2154 // This code always brings home to the front.
Dianne Hackborn256dd3b2009-05-19 18:51:21 -07002155 try {
2156 ActivityManagerNative.getDefault().stopAppSwitches();
2157 } catch (RemoteException e) {
2158 }
Dianne Hackborn94a679d2009-07-28 17:51:07 -07002159 sendCloseSystemWindows();
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002160 startDockOrHome();
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002161 } else {
2162 // This code brings home to the front or, if it is already
2163 // at the front, puts the device to sleep.
2164 try {
Wink Savilled2e6a332010-02-12 12:12:06 -08002165 if (SystemProperties.getInt("persist.sys.uts-test-mode", 0) == 1) {
2166 /// Roll back EndcallBehavior as the cupcake design to pass P1 lab entry.
2167 Log.d(TAG, "UTS-TEST-MODE");
2168 } else {
2169 ActivityManagerNative.getDefault().stopAppSwitches();
2170 sendCloseSystemWindows();
2171 Intent dock = createHomeDockIntent();
2172 if (dock != null) {
2173 int result = ActivityManagerNative.getDefault()
2174 .startActivity(null, dock,
2175 dock.resolveTypeIfNeeded(mContext.getContentResolver()),
2176 null, 0, null, null, 0, true /* onlyIfNeeded*/, false);
2177 if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
2178 return false;
2179 }
Dianne Hackborn39c2d712009-09-22 11:41:31 -07002180 }
2181 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002182 int result = ActivityManagerNative.getDefault()
2183 .startActivity(null, mHomeIntent,
2184 mHomeIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
2185 null, 0, null, null, 0, true /* onlyIfNeeded*/, false);
2186 if (result == IActivityManager.START_RETURN_INTENT_TO_CALLER) {
2187 return false;
2188 }
2189 } catch (RemoteException ex) {
2190 // bummer, the activity manager, which is in this process, is dead
2191 }
2192 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002193 return true;
2194 }
2195
The Android Open Source Project0727d222009-03-11 12:11:58 -07002196 public void setCurrentOrientationLw(int newOrientation) {
2197 synchronized (mLock) {
2198 if (newOrientation != mCurrentAppOrientation) {
2199 mCurrentAppOrientation = newOrientation;
2200 updateOrientationListenerLp();
2201 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002202 }
2203 }
2204
The Android Open Source Project0727d222009-03-11 12:11:58 -07002205 public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
Jim Miller89b17222009-10-27 14:54:09 -07002206 final boolean hapticsDisabled = Settings.System.getInt(mContext.getContentResolver(),
2207 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0) == 0;
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08002208 if (!always && (hapticsDisabled || mKeyguardMediator.isShowingAndNotHidden())) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002209 return false;
2210 }
2211 switch (effectId) {
2212 case HapticFeedbackConstants.LONG_PRESS:
Dianne Hackborn181ceb52009-08-27 22:16:40 -07002213 mVibrator.vibrate(mLongPressVibePattern, -1);
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002214 return true;
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002215 case HapticFeedbackConstants.VIRTUAL_KEY:
2216 mVibrator.vibrate(mVirtualKeyVibePattern, -1);
2217 return true;
2218 case HapticFeedbackConstants.SAFE_MODE_DISABLED:
2219 mVibrator.vibrate(mSafeModeDisabledVibePattern, -1);
2220 return true;
2221 case HapticFeedbackConstants.SAFE_MODE_ENABLED:
2222 mVibrator.vibrate(mSafeModeEnabledVibePattern, -1);
2223 return true;
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002224 }
2225 return false;
2226 }
2227
Dianne Hackborn0041e972009-07-24 17:14:43 -07002228 public void keyFeedbackFromInput(KeyEvent event) {
2229 if (event.getAction() == KeyEvent.ACTION_DOWN
2230 && (event.getFlags()&KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
Dianne Hackbornb1a79802009-09-29 15:18:31 -07002231 performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
Dianne Hackborn0041e972009-07-24 17:14:43 -07002232 }
2233 }
2234
The Android Open Source Project0727d222009-03-11 12:11:58 -07002235 public void screenOnStoppedLw() {
Dianne Hackborn9dc06cc2009-11-17 18:19:23 -08002236 if (!mKeyguardMediator.isShowingAndNotHidden() && mPowerManager.isScreenOn()) {
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002237 long curTime = SystemClock.uptimeMillis();
2238 mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
2239 }
2240 }
Mike Lockwoodfcb39242009-10-21 23:01:07 -04002241
2242 public boolean allowKeyRepeat() {
2243 // disable key repeat when screen is off
2244 return mScreenOn;
2245 }
The Android Open Source Project1f838aa2009-03-03 19:32:13 -08002246}
Wink Saville37c124c2009-04-02 01:37:02 -07002247