blob: 483f9ebde7e436464952dec16d3e48c092d08c22 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 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.server;
18
19import static android.os.LocalPowerManager.CHEEK_EVENT;
20import static android.os.LocalPowerManager.OTHER_EVENT;
21import static android.os.LocalPowerManager.TOUCH_EVENT;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -070022import static android.os.LocalPowerManager.LONG_TOUCH_EVENT;
23import static android.os.LocalPowerManager.TOUCH_UP_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
25import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
26import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070027import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
29import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -070030import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
32import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
33import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070034import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
36import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_PUSH_BUFFERS;
38import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
39import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
40import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
41import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070042import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043
44import com.android.internal.app.IBatteryStats;
45import com.android.internal.policy.PolicyManager;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080046import com.android.internal.policy.impl.PhoneWindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import com.android.internal.view.IInputContext;
48import com.android.internal.view.IInputMethodClient;
49import com.android.internal.view.IInputMethodManager;
Dianne Hackbornac3587d2010-03-11 11:12:11 -080050import com.android.internal.view.WindowManagerPolicyThread;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import com.android.server.KeyInputQueue.QueuedEvent;
52import com.android.server.am.BatteryStatsService;
53
54import android.Manifest;
55import android.app.ActivityManagerNative;
56import android.app.IActivityManager;
Jim Millerd6b57052010-06-07 17:52:42 -070057import android.app.admin.DevicePolicyManager;
Jim Miller284b62e2010-06-08 14:27:42 -070058import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.Context;
Jim Miller284b62e2010-06-08 14:27:42 -070060import android.content.Intent;
61import android.content.IntentFilter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.content.pm.ActivityInfo;
63import android.content.pm.PackageManager;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070064import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.res.Configuration;
66import android.graphics.Matrix;
67import android.graphics.PixelFormat;
68import android.graphics.Rect;
69import android.graphics.Region;
70import android.os.BatteryStats;
71import android.os.Binder;
Dianne Hackborn75804932009-10-20 20:15:20 -070072import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.os.Debug;
74import android.os.Handler;
75import android.os.IBinder;
Michael Chan53071d62009-05-13 17:29:48 -070076import android.os.LatencyTimer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.os.LocalPowerManager;
78import android.os.Looper;
79import android.os.Message;
80import android.os.Parcel;
81import android.os.ParcelFileDescriptor;
82import android.os.Power;
83import android.os.PowerManager;
84import android.os.Process;
85import android.os.RemoteException;
86import android.os.ServiceManager;
87import android.os.SystemClock;
88import android.os.SystemProperties;
89import android.os.TokenWatcher;
90import android.provider.Settings;
Dianne Hackborn723738c2009-06-25 19:48:04 -070091import android.util.DisplayMetrics;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.util.EventLog;
Jim Millerd6b57052010-06-07 17:52:42 -070093import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080094import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.util.SparseIntArray;
96import android.view.Display;
97import android.view.Gravity;
98import android.view.IApplicationToken;
99import android.view.IOnKeyguardExitResult;
100import android.view.IRotationWatcher;
101import android.view.IWindow;
102import android.view.IWindowManager;
103import android.view.IWindowSession;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700104import android.view.InputChannel;
105import android.view.InputQueue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106import android.view.KeyEvent;
107import android.view.MotionEvent;
108import android.view.RawInputEvent;
109import android.view.Surface;
110import android.view.SurfaceSession;
111import android.view.View;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700112import android.view.ViewConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113import android.view.ViewTreeObserver;
114import android.view.WindowManager;
115import android.view.WindowManagerImpl;
116import android.view.WindowManagerPolicy;
117import android.view.WindowManager.LayoutParams;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700118import android.view.animation.AccelerateInterpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119import android.view.animation.Animation;
120import android.view.animation.AnimationUtils;
121import android.view.animation.Transformation;
122
123import java.io.BufferedWriter;
124import java.io.File;
125import java.io.FileDescriptor;
126import java.io.IOException;
127import java.io.OutputStream;
128import java.io.OutputStreamWriter;
129import java.io.PrintWriter;
130import java.io.StringWriter;
131import java.net.Socket;
132import java.util.ArrayList;
133import java.util.HashMap;
134import java.util.HashSet;
135import java.util.Iterator;
136import java.util.List;
137
138/** {@hide} */
Dianne Hackbornddca3ee2009-07-23 19:01:31 -0700139public class WindowManagerService extends IWindowManager.Stub
140 implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 static final String TAG = "WindowManager";
142 static final boolean DEBUG = false;
143 static final boolean DEBUG_FOCUS = false;
144 static final boolean DEBUG_ANIM = false;
Dianne Hackborn9b52a212009-12-11 14:51:35 -0800145 static final boolean DEBUG_LAYOUT = false;
Dianne Hackbornac3587d2010-03-11 11:12:11 -0800146 static final boolean DEBUG_RESIZE = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800147 static final boolean DEBUG_LAYERS = false;
148 static final boolean DEBUG_INPUT = false;
149 static final boolean DEBUG_INPUT_METHOD = false;
150 static final boolean DEBUG_VISIBILITY = false;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -0700151 static final boolean DEBUG_WINDOW_MOVEMENT = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 static final boolean DEBUG_ORIENTATION = false;
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700153 static final boolean DEBUG_CONFIGURATION = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final boolean DEBUG_APP_TRANSITIONS = false;
155 static final boolean DEBUG_STARTING_WINDOW = false;
156 static final boolean DEBUG_REORDER = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700157 static final boolean DEBUG_WALLPAPER = false;
Dianne Hackbornce73c1e2010-04-12 23:11:38 -0700158 static final boolean DEBUG_FREEZE = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean SHOW_TRANSACTIONS = false;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700160 static final boolean HIDE_STACK_CRAWLS = true;
Michael Chan53071d62009-05-13 17:29:48 -0700161 static final boolean MEASURE_LATENCY = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700162 static final boolean ENABLE_NATIVE_INPUT_DISPATCH =
163 WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH;
Michael Chan53071d62009-05-13 17:29:48 -0700164 static private LatencyTimer lt;
165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 static final boolean PROFILE_ORIENTATION = false;
167 static final boolean BLUR = true;
Dave Bortcfe65242009-04-09 14:51:04 -0700168 static final boolean localLOGV = DEBUG;
Romain Guy06882f82009-06-10 13:36:04 -0700169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 /** How long to wait for subsequent key repeats, in milliseconds */
171 static final int KEY_REPEAT_DELAY = 50;
172
173 /** How much to multiply the policy's type layer, to reserve room
174 * for multiple windows of the same type and Z-ordering adjustment
175 * with TYPE_LAYER_OFFSET. */
176 static final int TYPE_LAYER_MULTIPLIER = 10000;
Romain Guy06882f82009-06-10 13:36:04 -0700177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
179 * or below others in the same layer. */
180 static final int TYPE_LAYER_OFFSET = 1000;
Romain Guy06882f82009-06-10 13:36:04 -0700181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 /** How much to increment the layer for each window, to reserve room
183 * for effect surfaces between them.
184 */
185 static final int WINDOW_LAYER_MULTIPLIER = 5;
Romain Guy06882f82009-06-10 13:36:04 -0700186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 /** The maximum length we will accept for a loaded animation duration:
188 * this is 10 seconds.
189 */
190 static final int MAX_ANIMATION_DURATION = 10*1000;
191
192 /** Amount of time (in milliseconds) to animate the dim surface from one
193 * value to another, when no window animation is driving it.
194 */
195 static final int DEFAULT_DIM_DURATION = 200;
196
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700197 /** Amount of time (in milliseconds) to animate the fade-in-out transition for
198 * compatible windows.
199 */
200 static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 /** Adjustment to time to perform a dim, to make it more dramatic.
203 */
204 static final int DIM_DURATION_MULTIPLIER = 6;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700205
206 // Maximum number of milliseconds to wait for input event injection.
207 // FIXME is this value reasonable?
208 private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
Jeff Brown349703e2010-06-22 01:27:15 -0700209
210 // Default input dispatching timeout in nanoseconds.
211 private static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
Romain Guy06882f82009-06-10 13:36:04 -0700212
Dianne Hackborncfaef692009-06-15 14:24:44 -0700213 static final int INJECT_FAILED = 0;
214 static final int INJECT_SUCCEEDED = 1;
215 static final int INJECT_NO_PERMISSION = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 static final int UPDATE_FOCUS_NORMAL = 0;
218 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
219 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
220 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
Romain Guy06882f82009-06-10 13:36:04 -0700221
Michael Chane96440f2009-05-06 10:27:36 -0700222 /** The minimum time between dispatching touch events. */
223 int mMinWaitTimeBetweenTouchEvents = 1000 / 35;
224
225 // Last touch event time
226 long mLastTouchEventTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700227
Michael Chane96440f2009-05-06 10:27:36 -0700228 // Last touch event type
229 int mLastTouchEventType = OTHER_EVENT;
Romain Guy06882f82009-06-10 13:36:04 -0700230
Michael Chane96440f2009-05-06 10:27:36 -0700231 // Time to wait before calling useractivity again. This saves CPU usage
232 // when we get a flood of touch events.
233 static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000;
234
235 // Last time we call user activity
236 long mLastUserActivityCallTime = 0;
237
Romain Guy06882f82009-06-10 13:36:04 -0700238 // Last time we updated battery stats
Michael Chane96440f2009-05-06 10:27:36 -0700239 long mLastBatteryStatsCallTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 private static final String SYSTEM_SECURE = "ro.secure";
Romain Guy06882f82009-06-10 13:36:04 -0700242 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243
244 /**
245 * Condition waited on by {@link #reenableKeyguard} to know the call to
246 * the window policy has finished.
Mike Lockwood983ee092009-11-22 01:42:24 -0500247 * This is set to true only if mKeyguardTokenWatcher.acquired() has
248 * actually disabled the keyguard.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 */
Mike Lockwood983ee092009-11-22 01:42:24 -0500250 private boolean mKeyguardDisabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251
Jim Miller284b62e2010-06-08 14:27:42 -0700252 private static final int ALLOW_DISABLE_YES = 1;
253 private static final int ALLOW_DISABLE_NO = 0;
254 private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
255 private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
256
Mike Lockwood983ee092009-11-22 01:42:24 -0500257 final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
258 new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 public void acquired() {
Jim Miller284b62e2010-06-08 14:27:42 -0700260 if (shouldAllowDisableKeyguard()) {
261 mPolicy.enableKeyguard(false);
262 mKeyguardDisabled = true;
263 } else {
264 Log.v(TAG, "Not disabling keyguard since device policy is enforced");
265 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 }
267 public void released() {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700268 mPolicy.enableKeyguard(true);
Mike Lockwood983ee092009-11-22 01:42:24 -0500269 synchronized (mKeyguardTokenWatcher) {
270 mKeyguardDisabled = false;
271 mKeyguardTokenWatcher.notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 }
273 }
274 };
275
Jim Miller284b62e2010-06-08 14:27:42 -0700276 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
277 @Override
278 public void onReceive(Context context, Intent intent) {
279 mPolicy.enableKeyguard(true);
280 synchronized(mKeyguardTokenWatcher) {
281 // lazily evaluate this next time we're asked to disable keyguard
282 mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
283 mKeyguardDisabled = false;
284 }
285 }
286 };
287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 final Context mContext;
289
290 final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 final boolean mLimitedAlphaCompositing;
Romain Guy06882f82009-06-10 13:36:04 -0700293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
295
296 final IActivityManager mActivityManager;
Romain Guy06882f82009-06-10 13:36:04 -0700297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 final IBatteryStats mBatteryStats;
Romain Guy06882f82009-06-10 13:36:04 -0700299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 /**
301 * All currently active sessions with clients.
302 */
303 final HashSet<Session> mSessions = new HashSet<Session>();
Romain Guy06882f82009-06-10 13:36:04 -0700304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 /**
306 * Mapping from an IWindow IBinder to the server's Window object.
307 * This is also used as the lock for all of our state.
308 */
309 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
310
311 /**
312 * Mapping from a token IBinder to a WindowToken object.
313 */
314 final HashMap<IBinder, WindowToken> mTokenMap =
315 new HashMap<IBinder, WindowToken>();
316
317 /**
318 * The same tokens as mTokenMap, stored in a list for efficient iteration
319 * over them.
320 */
321 final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800323 /**
324 * Window tokens that are in the process of exiting, but still
325 * on screen for animations.
326 */
327 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
328
329 /**
330 * Z-ordered (bottom-most first) list of all application tokens, for
331 * controlling the ordering of windows in different applications. This
332 * contains WindowToken objects.
333 */
334 final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
335
336 /**
337 * Application tokens that are in the process of exiting, but still
338 * on screen for animations.
339 */
340 final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
341
342 /**
343 * List of window tokens that have finished starting their application,
344 * and now need to have the policy remove their windows.
345 */
346 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
347
348 /**
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700349 * This was the app token that was used to retrieve the last enter
350 * animation. It will be used for the next exit animation.
351 */
352 AppWindowToken mLastEnterAnimToken;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800353
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700354 /**
355 * These were the layout params used to retrieve the last enter animation.
356 * They will be used for the next exit animation.
357 */
358 LayoutParams mLastEnterAnimParams;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800359
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700360 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361 * Z-ordered (bottom-most first) list of all Window objects.
362 */
363 final ArrayList mWindows = new ArrayList();
364
365 /**
366 * Windows that are being resized. Used so we can tell the client about
367 * the resize after closing the transaction in which we resized the
368 * underlying surface.
369 */
370 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
371
372 /**
373 * Windows whose animations have ended and now must be removed.
374 */
375 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
376
377 /**
378 * Windows whose surface should be destroyed.
379 */
380 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
381
382 /**
383 * Windows that have lost input focus and are waiting for the new
384 * focus window to be displayed before they are told about this.
385 */
386 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
387
388 /**
389 * This is set when we have run out of memory, and will either be an empty
390 * list or contain windows that need to be force removed.
391 */
392 ArrayList<WindowState> mForceRemoves;
Romain Guy06882f82009-06-10 13:36:04 -0700393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 IInputMethodManager mInputMethodManager;
Romain Guy06882f82009-06-10 13:36:04 -0700395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 SurfaceSession mFxSession;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700397 private DimAnimator mDimAnimator = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 Surface mBlurSurface;
399 boolean mBlurShown;
Romain Guy06882f82009-06-10 13:36:04 -0700400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800401 int mTransactionSequence = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 final float[] mTmpFloats = new float[9];
404
405 boolean mSafeMode;
406 boolean mDisplayEnabled = false;
407 boolean mSystemBooted = false;
Christopher Tateb696aee2010-04-02 19:08:30 -0700408 int mInitialDisplayWidth = 0;
409 int mInitialDisplayHeight = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 int mRotation = 0;
411 int mRequestedRotation = 0;
412 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Dianne Hackborn321ae682009-03-27 16:16:03 -0700413 int mLastRotationFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 ArrayList<IRotationWatcher> mRotationWatchers
415 = new ArrayList<IRotationWatcher>();
Romain Guy06882f82009-06-10 13:36:04 -0700416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800417 boolean mLayoutNeeded = true;
418 boolean mAnimationPending = false;
419 boolean mDisplayFrozen = false;
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800420 boolean mWaitingForConfig = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 boolean mWindowsFreezingScreen = false;
422 long mFreezeGcPending = 0;
423 int mAppsFreezingScreen = 0;
424
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800425 int mLayoutSeq = 0;
426
Dianne Hackbornb601ce12010-03-01 23:36:02 -0800427 // State while inside of layoutAndPlaceSurfacesLocked().
428 boolean mFocusMayChange;
429
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800430 Configuration mCurConfiguration = new Configuration();
431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 // This is held as long as we have the screen frozen, to give us time to
433 // perform a rotation animation when turning off shows the lock screen which
434 // changes the orientation.
435 PowerManager.WakeLock mScreenFrozenLock;
Romain Guy06882f82009-06-10 13:36:04 -0700436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 // State management of app transitions. When we are preparing for a
438 // transition, mNextAppTransition will be the kind of transition to
439 // perform or TRANSIT_NONE if we are not waiting. If we are waiting,
440 // mOpeningApps and mClosingApps are the lists of tokens that will be
441 // made visible or hidden at the next transition.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700442 int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700443 String mNextAppTransitionPackage;
444 int mNextAppTransitionEnter;
445 int mNextAppTransitionExit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 boolean mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -0700447 boolean mAppTransitionRunning = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 boolean mAppTransitionTimeout = false;
449 boolean mStartingIconInTransition = false;
450 boolean mSkipAppTransitionAnimation = false;
451 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
452 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
Dianne Hackborna8f60182009-09-01 19:01:50 -0700453 final ArrayList<AppWindowToken> mToTopApps = new ArrayList<AppWindowToken>();
454 final ArrayList<AppWindowToken> mToBottomApps = new ArrayList<AppWindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 Display mDisplay;
Romain Guy06882f82009-06-10 13:36:04 -0700457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 H mH = new H();
459
460 WindowState mCurrentFocus = null;
461 WindowState mLastFocus = null;
Romain Guy06882f82009-06-10 13:36:04 -0700462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 // This just indicates the window the input method is on top of, not
464 // necessarily the window its input is going to.
465 WindowState mInputMethodTarget = null;
466 WindowState mUpcomingInputMethodTarget = null;
467 boolean mInputMethodTargetWaitingAnim;
468 int mInputMethodAnimLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -0700469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800470 WindowState mInputMethodWindow = null;
471 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
472
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700473 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800474
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700475 // If non-null, this is the currently visible window that is associated
476 // with the wallpaper.
477 WindowState mWallpaperTarget = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700478 // If non-null, we are in the middle of animating from one wallpaper target
479 // to another, and this is the lower one in Z-order.
480 WindowState mLowerWallpaperTarget = null;
481 // If non-null, we are in the middle of animating from one wallpaper target
482 // to another, and this is the higher one in Z-order.
483 WindowState mUpperWallpaperTarget = null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700484 int mWallpaperAnimLayerAdjustment;
Dianne Hackborn73e92b42009-10-15 14:29:19 -0700485 float mLastWallpaperX = -1;
486 float mLastWallpaperY = -1;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800487 float mLastWallpaperXStep = -1;
488 float mLastWallpaperYStep = -1;
Dianne Hackborn6adba242009-11-10 11:10:09 -0800489 boolean mSendingPointersToWallpaper = false;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700490 // This is set when we are waiting for a wallpaper to tell us it is done
491 // changing its scroll position.
492 WindowState mWaitingOnWallpaper;
493 // The last time we had a timeout when waiting for a wallpaper.
494 long mLastWallpaperTimeoutTime;
495 // We give a wallpaper up to 150ms to finish scrolling.
496 static final long WALLPAPER_TIMEOUT = 150;
497 // Time we wait after a timeout before trying to wait again.
498 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 AppWindowToken mFocusedApp = null;
501
502 PowerManagerService mPowerManager;
Romain Guy06882f82009-06-10 13:36:04 -0700503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 float mWindowAnimationScale = 1.0f;
505 float mTransitionAnimationScale = 1.0f;
Romain Guy06882f82009-06-10 13:36:04 -0700506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 final KeyWaiter mKeyWaiter = new KeyWaiter();
508 final KeyQ mQueue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700509 final InputManager mInputManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 final InputDispatcherThread mInputThread;
511
512 // Who is holding the screen on.
513 Session mHoldingScreenOn;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700514 PowerManager.WakeLock mHoldingScreenWakeLock;
Romain Guy06882f82009-06-10 13:36:04 -0700515
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700516 boolean mTurnOnScreen;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 /**
519 * Whether the UI is currently running in touch mode (not showing
520 * navigational focus because the user is directly pressing the screen).
521 */
522 boolean mInTouchMode = false;
523
524 private ViewServer mViewServer;
525
526 final Rect mTempRect = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -0700527
Dianne Hackbornc485a602009-03-24 22:39:49 -0700528 final Configuration mTempConfiguration = new Configuration();
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700529 int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700530
531 // The frame use to limit the size of the app running in compatibility mode.
532 Rect mCompatibleScreenFrame = new Rect();
533 // The surface used to fill the outer rim of the app running in compatibility mode.
534 Surface mBackgroundFillerSurface = null;
535 boolean mBackgroundFillerShown = false;
536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 public static WindowManagerService main(Context context,
538 PowerManagerService pm, boolean haveInputMethods) {
539 WMThread thr = new WMThread(context, pm, haveInputMethods);
540 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 synchronized (thr) {
543 while (thr.mService == null) {
544 try {
545 thr.wait();
546 } catch (InterruptedException e) {
547 }
548 }
549 }
Romain Guy06882f82009-06-10 13:36:04 -0700550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 return thr.mService;
552 }
Romain Guy06882f82009-06-10 13:36:04 -0700553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 static class WMThread extends Thread {
555 WindowManagerService mService;
Romain Guy06882f82009-06-10 13:36:04 -0700556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 private final Context mContext;
558 private final PowerManagerService mPM;
559 private final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 public WMThread(Context context, PowerManagerService pm,
562 boolean haveInputMethods) {
563 super("WindowManager");
564 mContext = context;
565 mPM = pm;
566 mHaveInputMethods = haveInputMethods;
567 }
Romain Guy06882f82009-06-10 13:36:04 -0700568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 public void run() {
570 Looper.prepare();
571 WindowManagerService s = new WindowManagerService(mContext, mPM,
572 mHaveInputMethods);
573 android.os.Process.setThreadPriority(
574 android.os.Process.THREAD_PRIORITY_DISPLAY);
Christopher Tate160edb32010-06-30 17:46:30 -0700575 android.os.Process.setCanSelfBackground(false);
Romain Guy06882f82009-06-10 13:36:04 -0700576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 synchronized (this) {
578 mService = s;
579 notifyAll();
580 }
Romain Guy06882f82009-06-10 13:36:04 -0700581
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800582 Looper.loop();
583 }
584 }
585
586 static class PolicyThread extends Thread {
587 private final WindowManagerPolicy mPolicy;
588 private final WindowManagerService mService;
589 private final Context mContext;
590 private final PowerManagerService mPM;
591 boolean mRunning = false;
Romain Guy06882f82009-06-10 13:36:04 -0700592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 public PolicyThread(WindowManagerPolicy policy,
594 WindowManagerService service, Context context,
595 PowerManagerService pm) {
596 super("WindowManagerPolicy");
597 mPolicy = policy;
598 mService = service;
599 mContext = context;
600 mPM = pm;
601 }
Romain Guy06882f82009-06-10 13:36:04 -0700602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 public void run() {
604 Looper.prepare();
Dianne Hackbornac3587d2010-03-11 11:12:11 -0800605 WindowManagerPolicyThread.set(this, Looper.myLooper());
606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607 //Looper.myLooper().setMessageLogging(new LogPrinter(
Joe Onorato8a9b2202010-02-26 18:56:32 -0800608 // Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609 android.os.Process.setThreadPriority(
610 android.os.Process.THREAD_PRIORITY_FOREGROUND);
Christopher Tate160edb32010-06-30 17:46:30 -0700611 android.os.Process.setCanSelfBackground(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800612 mPolicy.init(mContext, mService, mPM);
Romain Guy06882f82009-06-10 13:36:04 -0700613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 synchronized (this) {
615 mRunning = true;
616 notifyAll();
617 }
Romain Guy06882f82009-06-10 13:36:04 -0700618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 Looper.loop();
620 }
621 }
622
623 private WindowManagerService(Context context, PowerManagerService pm,
624 boolean haveInputMethods) {
Michael Chan53071d62009-05-13 17:29:48 -0700625 if (MEASURE_LATENCY) {
626 lt = new LatencyTimer(100, 1000);
627 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 mContext = context;
630 mHaveInputMethods = haveInputMethods;
631 mLimitedAlphaCompositing = context.getResources().getBoolean(
632 com.android.internal.R.bool.config_sf_limitedAlpha);
Romain Guy06882f82009-06-10 13:36:04 -0700633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800634 mPowerManager = pm;
635 mPowerManager.setPolicy(mPolicy);
636 PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
637 mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
638 "SCREEN_FROZEN");
639 mScreenFrozenLock.setReferenceCounted(false);
640
641 mActivityManager = ActivityManagerNative.getDefault();
642 mBatteryStats = BatteryStatsService.getService();
643
644 // Get persisted window scale setting
645 mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
646 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
647 mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
648 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
Romain Guy06882f82009-06-10 13:36:04 -0700649
Jim Miller284b62e2010-06-08 14:27:42 -0700650 // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
651 IntentFilter filter = new IntentFilter();
652 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
653 mContext.registerReceiver(mBroadcastReceiver, filter);
654
Michael Chan9f028e62009-08-04 17:37:46 -0700655 int max_events_per_sec = 35;
656 try {
657 max_events_per_sec = Integer.parseInt(SystemProperties
658 .get("windowsmgr.max_events_per_sec"));
659 if (max_events_per_sec < 1) {
660 max_events_per_sec = 35;
661 }
662 } catch (NumberFormatException e) {
663 }
664 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
665
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700666 mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
667 "KEEP_SCREEN_ON_FLAG");
668 mHoldingScreenWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700670 if (ENABLE_NATIVE_INPUT_DISPATCH) {
671 mInputManager = new InputManager(context, this, mPolicy, pmc, mPowerManager);
672 } else {
673 mInputManager = null;
674 }
675 mQueue = new KeyQ();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 mInputThread = new InputDispatcherThread();
Romain Guy06882f82009-06-10 13:36:04 -0700677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
679 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681 synchronized (thr) {
682 while (!thr.mRunning) {
683 try {
684 thr.wait();
685 } catch (InterruptedException e) {
686 }
687 }
688 }
Romain Guy06882f82009-06-10 13:36:04 -0700689
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700690 if (ENABLE_NATIVE_INPUT_DISPATCH) {
691 mInputManager.start();
692 } else {
693 mInputThread.start();
694 }
Romain Guy06882f82009-06-10 13:36:04 -0700695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 // Add ourself to the Watchdog monitors.
697 Watchdog.getInstance().addMonitor(this);
698 }
699
700 @Override
701 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
702 throws RemoteException {
703 try {
704 return super.onTransact(code, data, reply, flags);
705 } catch (RuntimeException e) {
706 // The window manager only throws security exceptions, so let's
707 // log all others.
708 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800709 Slog.e(TAG, "Window Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 }
711 throw e;
712 }
713 }
714
715 private void placeWindowAfter(Object pos, WindowState window) {
716 final int i = mWindows.indexOf(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800717 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 TAG, "Adding window " + window + " at "
719 + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
720 mWindows.add(i+1, window);
721 }
722
723 private void placeWindowBefore(Object pos, WindowState window) {
724 final int i = mWindows.indexOf(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800725 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 TAG, "Adding window " + window + " at "
727 + i + " of " + mWindows.size() + " (before " + pos + ")");
728 mWindows.add(i, window);
729 }
730
731 //This method finds out the index of a window that has the same app token as
732 //win. used for z ordering the windows in mWindows
733 private int findIdxBasedOnAppTokens(WindowState win) {
734 //use a local variable to cache mWindows
735 ArrayList localmWindows = mWindows;
736 int jmax = localmWindows.size();
737 if(jmax == 0) {
738 return -1;
739 }
740 for(int j = (jmax-1); j >= 0; j--) {
741 WindowState wentry = (WindowState)localmWindows.get(j);
742 if(wentry.mAppToken == win.mAppToken) {
743 return j;
744 }
745 }
746 return -1;
747 }
Romain Guy06882f82009-06-10 13:36:04 -0700748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
750 final IWindow client = win.mClient;
751 final WindowToken token = win.mToken;
752 final ArrayList localmWindows = mWindows;
Romain Guy06882f82009-06-10 13:36:04 -0700753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800754 final int N = localmWindows.size();
755 final WindowState attached = win.mAttachedWindow;
756 int i;
757 if (attached == null) {
758 int tokenWindowsPos = token.windows.size();
759 if (token.appWindowToken != null) {
760 int index = tokenWindowsPos-1;
761 if (index >= 0) {
762 // If this application has existing windows, we
763 // simply place the new window on top of them... but
764 // keep the starting window on top.
765 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
766 // Base windows go behind everything else.
767 placeWindowBefore(token.windows.get(0), win);
768 tokenWindowsPos = 0;
769 } else {
770 AppWindowToken atoken = win.mAppToken;
771 if (atoken != null &&
772 token.windows.get(index) == atoken.startingWindow) {
773 placeWindowBefore(token.windows.get(index), win);
774 tokenWindowsPos--;
775 } else {
776 int newIdx = findIdxBasedOnAppTokens(win);
777 if(newIdx != -1) {
Romain Guy06882f82009-06-10 13:36:04 -0700778 //there is a window above this one associated with the same
779 //apptoken note that the window could be a floating window
780 //that was created later or a window at the top of the list of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800781 //windows associated with this token.
Joe Onorato8a9b2202010-02-26 18:56:32 -0800782 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700783 TAG, "Adding window " + win + " at "
784 + (newIdx+1) + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800785 localmWindows.add(newIdx+1, win);
Romain Guy06882f82009-06-10 13:36:04 -0700786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 }
788 }
789 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800790 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 TAG, "Figuring out where to add app window "
792 + client.asBinder() + " (token=" + token + ")");
793 // Figure out where the window should go, based on the
794 // order of applications.
795 final int NA = mAppTokens.size();
796 Object pos = null;
797 for (i=NA-1; i>=0; i--) {
798 AppWindowToken t = mAppTokens.get(i);
799 if (t == token) {
800 i--;
801 break;
802 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800803
Dianne Hackborna8f60182009-09-01 19:01:50 -0700804 // We haven't reached the token yet; if this token
805 // is not going to the bottom and has windows, we can
806 // use it as an anchor for when we do reach the token.
807 if (!t.sendingToBottom && t.windows.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 pos = t.windows.get(0);
809 }
810 }
811 // We now know the index into the apps. If we found
812 // an app window above, that gives us the position; else
813 // we need to look some more.
814 if (pos != null) {
815 // Move behind any windows attached to this one.
Romain Guy06882f82009-06-10 13:36:04 -0700816 WindowToken atoken =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 mTokenMap.get(((WindowState)pos).mClient.asBinder());
818 if (atoken != null) {
819 final int NC = atoken.windows.size();
820 if (NC > 0) {
821 WindowState bottom = atoken.windows.get(0);
822 if (bottom.mSubLayer < 0) {
823 pos = bottom;
824 }
825 }
826 }
827 placeWindowBefore(pos, win);
828 } else {
Dianne Hackborna8f60182009-09-01 19:01:50 -0700829 // Continue looking down until we find the first
830 // token that has windows.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 while (i >= 0) {
832 AppWindowToken t = mAppTokens.get(i);
833 final int NW = t.windows.size();
834 if (NW > 0) {
835 pos = t.windows.get(NW-1);
836 break;
837 }
838 i--;
839 }
840 if (pos != null) {
841 // Move in front of any windows attached to this
842 // one.
843 WindowToken atoken =
844 mTokenMap.get(((WindowState)pos).mClient.asBinder());
845 if (atoken != null) {
846 final int NC = atoken.windows.size();
847 if (NC > 0) {
848 WindowState top = atoken.windows.get(NC-1);
849 if (top.mSubLayer >= 0) {
850 pos = top;
851 }
852 }
853 }
854 placeWindowAfter(pos, win);
855 } else {
856 // Just search for the start of this layer.
857 final int myLayer = win.mBaseLayer;
858 for (i=0; i<N; i++) {
859 WindowState w = (WindowState)localmWindows.get(i);
860 if (w.mBaseLayer > myLayer) {
861 break;
862 }
863 }
Joe Onorato8a9b2202010-02-26 18:56:32 -0800864 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700865 TAG, "Adding window " + win + " at "
866 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 localmWindows.add(i, win);
868 }
869 }
870 }
871 } else {
872 // Figure out where window should go, based on layer.
873 final int myLayer = win.mBaseLayer;
874 for (i=N-1; i>=0; i--) {
875 if (((WindowState)localmWindows.get(i)).mBaseLayer <= myLayer) {
876 i++;
877 break;
878 }
879 }
880 if (i < 0) i = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800881 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700882 TAG, "Adding window " + win + " at "
883 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 localmWindows.add(i, win);
885 }
886 if (addToToken) {
887 token.windows.add(tokenWindowsPos, win);
888 }
889
890 } else {
891 // Figure out this window's ordering relative to the window
892 // it is attached to.
893 final int NA = token.windows.size();
894 final int sublayer = win.mSubLayer;
895 int largestSublayer = Integer.MIN_VALUE;
896 WindowState windowWithLargestSublayer = null;
897 for (i=0; i<NA; i++) {
898 WindowState w = token.windows.get(i);
899 final int wSublayer = w.mSubLayer;
900 if (wSublayer >= largestSublayer) {
901 largestSublayer = wSublayer;
902 windowWithLargestSublayer = w;
903 }
904 if (sublayer < 0) {
905 // For negative sublayers, we go below all windows
906 // in the same sublayer.
907 if (wSublayer >= sublayer) {
908 if (addToToken) {
909 token.windows.add(i, win);
910 }
911 placeWindowBefore(
912 wSublayer >= 0 ? attached : w, win);
913 break;
914 }
915 } else {
916 // For positive sublayers, we go above all windows
917 // in the same sublayer.
918 if (wSublayer > sublayer) {
919 if (addToToken) {
920 token.windows.add(i, win);
921 }
922 placeWindowBefore(w, win);
923 break;
924 }
925 }
926 }
927 if (i >= NA) {
928 if (addToToken) {
929 token.windows.add(win);
930 }
931 if (sublayer < 0) {
932 placeWindowBefore(attached, win);
933 } else {
934 placeWindowAfter(largestSublayer >= 0
935 ? windowWithLargestSublayer
936 : attached,
937 win);
938 }
939 }
940 }
Romain Guy06882f82009-06-10 13:36:04 -0700941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 if (win.mAppToken != null && addToToken) {
943 win.mAppToken.allAppWindows.add(win);
944 }
945 }
Romain Guy06882f82009-06-10 13:36:04 -0700946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 static boolean canBeImeTarget(WindowState w) {
948 final int fl = w.mAttrs.flags
949 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
950 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
951 return w.isVisibleOrAdding();
952 }
953 return false;
954 }
Romain Guy06882f82009-06-10 13:36:04 -0700955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
957 final ArrayList localmWindows = mWindows;
958 final int N = localmWindows.size();
959 WindowState w = null;
960 int i = N;
961 while (i > 0) {
962 i--;
963 w = (WindowState)localmWindows.get(i);
Romain Guy06882f82009-06-10 13:36:04 -0700964
Joe Onorato8a9b2202010-02-26 18:56:32 -0800965 //Slog.i(TAG, "Checking window @" + i + " " + w + " fl=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 // + Integer.toHexString(w.mAttrs.flags));
967 if (canBeImeTarget(w)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800968 //Slog.i(TAG, "Putting input method here!");
Romain Guy06882f82009-06-10 13:36:04 -0700969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970 // Yet more tricksyness! If this window is a "starting"
971 // window, we do actually want to be on top of it, but
972 // it is not -really- where input will go. So if the caller
973 // is not actually looking to move the IME, look down below
974 // for a real window to target...
975 if (!willMove
976 && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
977 && i > 0) {
978 WindowState wb = (WindowState)localmWindows.get(i-1);
979 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
980 i--;
981 w = wb;
982 }
983 }
984 break;
985 }
986 }
Romain Guy06882f82009-06-10 13:36:04 -0700987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 mUpcomingInputMethodTarget = w;
Romain Guy06882f82009-06-10 13:36:04 -0700989
Joe Onorato8a9b2202010-02-26 18:56:32 -0800990 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 + w + " willMove=" + willMove);
Romain Guy06882f82009-06-10 13:36:04 -0700992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 if (willMove && w != null) {
994 final WindowState curTarget = mInputMethodTarget;
995 if (curTarget != null && curTarget.mAppToken != null) {
Romain Guy06882f82009-06-10 13:36:04 -0700996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 // Now some fun for dealing with window animations that
998 // modify the Z order. We need to look at all windows below
999 // the current target that are in this app, finding the highest
1000 // visible one in layering.
1001 AppWindowToken token = curTarget.mAppToken;
1002 WindowState highestTarget = null;
1003 int highestPos = 0;
1004 if (token.animating || token.animation != null) {
1005 int pos = 0;
1006 pos = localmWindows.indexOf(curTarget);
1007 while (pos >= 0) {
1008 WindowState win = (WindowState)localmWindows.get(pos);
1009 if (win.mAppToken != token) {
1010 break;
1011 }
1012 if (!win.mRemoved) {
1013 if (highestTarget == null || win.mAnimLayer >
1014 highestTarget.mAnimLayer) {
1015 highestTarget = win;
1016 highestPos = pos;
1017 }
1018 }
1019 pos--;
1020 }
1021 }
Romain Guy06882f82009-06-10 13:36:04 -07001022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 if (highestTarget != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001024 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "mNextAppTransition="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 + mNextAppTransition + " " + highestTarget
1026 + " animating=" + highestTarget.isAnimating()
1027 + " layer=" + highestTarget.mAnimLayer
1028 + " new layer=" + w.mAnimLayer);
Romain Guy06882f82009-06-10 13:36:04 -07001029
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001030 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 // If we are currently setting up for an animation,
1032 // hold everything until we can find out what will happen.
1033 mInputMethodTargetWaitingAnim = true;
1034 mInputMethodTarget = highestTarget;
1035 return highestPos + 1;
1036 } else if (highestTarget.isAnimating() &&
1037 highestTarget.mAnimLayer > w.mAnimLayer) {
1038 // If the window we are currently targeting is involved
1039 // with an animation, and it is on top of the next target
1040 // we will be over, then hold off on moving until
1041 // that is done.
1042 mInputMethodTarget = highestTarget;
1043 return highestPos + 1;
1044 }
1045 }
1046 }
1047 }
Romain Guy06882f82009-06-10 13:36:04 -07001048
Joe Onorato8a9b2202010-02-26 18:56:32 -08001049 //Slog.i(TAG, "Placing input method @" + (i+1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001050 if (w != null) {
1051 if (willMove) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08001052 if (DEBUG_INPUT_METHOD) {
1053 RuntimeException e = null;
1054 if (!HIDE_STACK_CRAWLS) {
1055 e = new RuntimeException();
1056 e.fillInStackTrace();
1057 }
1058 Slog.w(TAG, "Moving IM target from "
1059 + mInputMethodTarget + " to " + w, e);
1060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 mInputMethodTarget = w;
1062 if (w.mAppToken != null) {
1063 setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
1064 } else {
1065 setInputMethodAnimLayerAdjustment(0);
1066 }
1067 }
1068 return i+1;
1069 }
1070 if (willMove) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08001071 if (DEBUG_INPUT_METHOD) {
1072 RuntimeException e = null;
1073 if (!HIDE_STACK_CRAWLS) {
1074 e = new RuntimeException();
1075 e.fillInStackTrace();
1076 }
1077 Slog.w(TAG, "Moving IM target from "
1078 + mInputMethodTarget + " to null", e);
1079 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 mInputMethodTarget = null;
1081 setInputMethodAnimLayerAdjustment(0);
1082 }
1083 return -1;
1084 }
Romain Guy06882f82009-06-10 13:36:04 -07001085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 void addInputMethodWindowToListLocked(WindowState win) {
1087 int pos = findDesiredInputMethodWindowIndexLocked(true);
1088 if (pos >= 0) {
1089 win.mTargetAppToken = mInputMethodTarget.mAppToken;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001090 if (DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001091 TAG, "Adding input method window " + win + " at " + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 mWindows.add(pos, win);
1093 moveInputMethodDialogsLocked(pos+1);
1094 return;
1095 }
1096 win.mTargetAppToken = null;
1097 addWindowToListInOrderLocked(win, true);
1098 moveInputMethodDialogsLocked(pos);
1099 }
Romain Guy06882f82009-06-10 13:36:04 -07001100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 void setInputMethodAnimLayerAdjustment(int adj) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001102 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 mInputMethodAnimLayerAdjustment = adj;
1104 WindowState imw = mInputMethodWindow;
1105 if (imw != null) {
1106 imw.mAnimLayer = imw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001107 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 + " anim layer: " + imw.mAnimLayer);
1109 int wi = imw.mChildWindows.size();
1110 while (wi > 0) {
1111 wi--;
1112 WindowState cw = (WindowState)imw.mChildWindows.get(wi);
1113 cw.mAnimLayer = cw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001114 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 + " anim layer: " + cw.mAnimLayer);
1116 }
1117 }
1118 int di = mInputMethodDialogs.size();
1119 while (di > 0) {
1120 di --;
1121 imw = mInputMethodDialogs.get(di);
1122 imw.mAnimLayer = imw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001123 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 + " anim layer: " + imw.mAnimLayer);
1125 }
1126 }
Romain Guy06882f82009-06-10 13:36:04 -07001127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1129 int wpos = mWindows.indexOf(win);
1130 if (wpos >= 0) {
1131 if (wpos < interestingPos) interestingPos--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001132 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 mWindows.remove(wpos);
1134 int NC = win.mChildWindows.size();
1135 while (NC > 0) {
1136 NC--;
1137 WindowState cw = (WindowState)win.mChildWindows.get(NC);
1138 int cpos = mWindows.indexOf(cw);
1139 if (cpos >= 0) {
1140 if (cpos < interestingPos) interestingPos--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001141 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001142 + cpos + ": " + cw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143 mWindows.remove(cpos);
1144 }
1145 }
1146 }
1147 return interestingPos;
1148 }
Romain Guy06882f82009-06-10 13:36:04 -07001149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 private void reAddWindowToListInOrderLocked(WindowState win) {
1151 addWindowToListInOrderLocked(win, false);
1152 // This is a hack to get all of the child windows added as well
1153 // at the right position. Child windows should be rare and
1154 // this case should be rare, so it shouldn't be that big a deal.
1155 int wpos = mWindows.indexOf(win);
1156 if (wpos >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001157 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001158 + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 mWindows.remove(wpos);
1160 reAddWindowLocked(wpos, win);
1161 }
1162 }
Romain Guy06882f82009-06-10 13:36:04 -07001163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 void logWindowList(String prefix) {
1165 int N = mWindows.size();
1166 while (N > 0) {
1167 N--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001168 Slog.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 }
1170 }
Romain Guy06882f82009-06-10 13:36:04 -07001171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 void moveInputMethodDialogsLocked(int pos) {
1173 ArrayList<WindowState> dialogs = mInputMethodDialogs;
Romain Guy06882f82009-06-10 13:36:04 -07001174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 final int N = dialogs.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001176 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 for (int i=0; i<N; i++) {
1178 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1179 }
1180 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001181 Slog.v(TAG, "Window list w/pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 logWindowList(" ");
1183 }
Romain Guy06882f82009-06-10 13:36:04 -07001184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 if (pos >= 0) {
1186 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1187 if (pos < mWindows.size()) {
1188 WindowState wp = (WindowState)mWindows.get(pos);
1189 if (wp == mInputMethodWindow) {
1190 pos++;
1191 }
1192 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001193 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001194 for (int i=0; i<N; i++) {
1195 WindowState win = dialogs.get(i);
1196 win.mTargetAppToken = targetAppToken;
1197 pos = reAddWindowLocked(pos, win);
1198 }
1199 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001200 Slog.v(TAG, "Final window list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 logWindowList(" ");
1202 }
1203 return;
1204 }
1205 for (int i=0; i<N; i++) {
1206 WindowState win = dialogs.get(i);
1207 win.mTargetAppToken = null;
1208 reAddWindowToListInOrderLocked(win);
1209 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001210 Slog.v(TAG, "No IM target, final list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 logWindowList(" ");
1212 }
1213 }
1214 }
Romain Guy06882f82009-06-10 13:36:04 -07001215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1217 final WindowState imWin = mInputMethodWindow;
1218 final int DN = mInputMethodDialogs.size();
1219 if (imWin == null && DN == 0) {
1220 return false;
1221 }
Romain Guy06882f82009-06-10 13:36:04 -07001222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1224 if (imPos >= 0) {
1225 // In this case, the input method windows are to be placed
1226 // immediately above the window they are targeting.
Romain Guy06882f82009-06-10 13:36:04 -07001227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 // First check to see if the input method windows are already
1229 // located here, and contiguous.
1230 final int N = mWindows.size();
1231 WindowState firstImWin = imPos < N
1232 ? (WindowState)mWindows.get(imPos) : null;
Romain Guy06882f82009-06-10 13:36:04 -07001233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 // Figure out the actual input method window that should be
1235 // at the bottom of their stack.
1236 WindowState baseImWin = imWin != null
1237 ? imWin : mInputMethodDialogs.get(0);
1238 if (baseImWin.mChildWindows.size() > 0) {
1239 WindowState cw = (WindowState)baseImWin.mChildWindows.get(0);
1240 if (cw.mSubLayer < 0) baseImWin = cw;
1241 }
Romain Guy06882f82009-06-10 13:36:04 -07001242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 if (firstImWin == baseImWin) {
1244 // The windows haven't moved... but are they still contiguous?
1245 // First find the top IM window.
1246 int pos = imPos+1;
1247 while (pos < N) {
1248 if (!((WindowState)mWindows.get(pos)).mIsImWindow) {
1249 break;
1250 }
1251 pos++;
1252 }
1253 pos++;
1254 // Now there should be no more input method windows above.
1255 while (pos < N) {
1256 if (((WindowState)mWindows.get(pos)).mIsImWindow) {
1257 break;
1258 }
1259 pos++;
1260 }
1261 if (pos >= N) {
1262 // All is good!
1263 return false;
1264 }
1265 }
Romain Guy06882f82009-06-10 13:36:04 -07001266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 if (imWin != null) {
1268 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001269 Slog.v(TAG, "Moving IM from " + imPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 logWindowList(" ");
1271 }
1272 imPos = tmpRemoveWindowLocked(imPos, imWin);
1273 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001274 Slog.v(TAG, "List after moving with new pos " + imPos + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 logWindowList(" ");
1276 }
1277 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1278 reAddWindowLocked(imPos, imWin);
1279 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001280 Slog.v(TAG, "List after moving IM to " + imPos + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 logWindowList(" ");
1282 }
1283 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1284 } else {
1285 moveInputMethodDialogsLocked(imPos);
1286 }
Romain Guy06882f82009-06-10 13:36:04 -07001287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288 } else {
1289 // In this case, the input method windows go in a fixed layer,
1290 // because they aren't currently associated with a focus window.
Romain Guy06882f82009-06-10 13:36:04 -07001291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 if (imWin != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001293 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294 tmpRemoveWindowLocked(0, imWin);
1295 imWin.mTargetAppToken = null;
1296 reAddWindowToListInOrderLocked(imWin);
1297 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001298 Slog.v(TAG, "List with no IM target:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 logWindowList(" ");
1300 }
1301 if (DN > 0) moveInputMethodDialogsLocked(-1);;
1302 } else {
1303 moveInputMethodDialogsLocked(-1);;
1304 }
Romain Guy06882f82009-06-10 13:36:04 -07001305
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306 }
Romain Guy06882f82009-06-10 13:36:04 -07001307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001308 if (needAssignLayers) {
1309 assignLayersLocked();
1310 }
Romain Guy06882f82009-06-10 13:36:04 -07001311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001312 return true;
1313 }
Romain Guy06882f82009-06-10 13:36:04 -07001314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001315 void adjustInputMethodDialogsLocked() {
1316 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
1317 }
Romain Guy06882f82009-06-10 13:36:04 -07001318
Dianne Hackborn25994b42009-09-04 14:21:19 -07001319 final boolean isWallpaperVisible(WindowState wallpaperTarget) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001320 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target obscured="
Dianne Hackborn25994b42009-09-04 14:21:19 -07001321 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1322 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1323 ? wallpaperTarget.mAppToken.animation : null)
1324 + " upper=" + mUpperWallpaperTarget
1325 + " lower=" + mLowerWallpaperTarget);
1326 return (wallpaperTarget != null
1327 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1328 && wallpaperTarget.mAppToken.animation != null)))
1329 || mUpperWallpaperTarget != null
1330 || mLowerWallpaperTarget != null;
1331 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001332
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001333 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1334 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001335
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001336 int adjustWallpaperWindowsLocked() {
1337 int changed = 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001338
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001339 final int dw = mDisplay.getWidth();
1340 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001341
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001342 // First find top-most window that has asked to be on top of the
1343 // wallpaper; all wallpapers go behind it.
1344 final ArrayList localmWindows = mWindows;
1345 int N = localmWindows.size();
1346 WindowState w = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001347 WindowState foundW = null;
1348 int foundI = 0;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001349 WindowState topCurW = null;
1350 int topCurI = 0;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001351 int i = N;
1352 while (i > 0) {
1353 i--;
1354 w = (WindowState)localmWindows.get(i);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001355 if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
1356 if (topCurW == null) {
1357 topCurW = w;
1358 topCurI = i;
1359 }
1360 continue;
1361 }
1362 topCurW = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001363 if (w.mAppToken != null) {
1364 // If this window's app token is hidden and not animating,
1365 // it is of no interest to us.
1366 if (w.mAppToken.hidden && w.mAppToken.animation == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001367 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001368 "Skipping hidden or animating token: " + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001369 topCurW = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001370 continue;
1371 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001372 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001373 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": readyfordisplay="
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001374 + w.isReadyForDisplay() + " drawpending=" + w.mDrawPending
1375 + " commitdrawpending=" + w.mCommitDrawPending);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001376 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07001377 && (mWallpaperTarget == w
1378 || (!w.mDrawPending && !w.mCommitDrawPending))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001379 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001380 "Found wallpaper activity: #" + i + "=" + w);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001381 foundW = w;
1382 foundI = i;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001383 if (w == mWallpaperTarget && ((w.mAppToken != null
1384 && w.mAppToken.animation != null)
1385 || w.mAnimation != null)) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001386 // The current wallpaper target is animating, so we'll
1387 // look behind it for another possible target and figure
1388 // out what is going on below.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001389 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001390 + ": token animating, looking behind.");
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001391 continue;
1392 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001393 break;
1394 }
1395 }
1396
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001397 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001398 // If we are currently waiting for an app transition, and either
1399 // the current target or the next target are involved with it,
1400 // then hold off on doing anything with the wallpaper.
1401 // Note that we are checking here for just whether the target
1402 // is part of an app token... which is potentially overly aggressive
1403 // (the app token may not be involved in the transition), but good
1404 // enough (we'll just wait until whatever transition is pending
1405 // executes).
1406 if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001407 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001408 "Wallpaper not changing: waiting for app anim in current target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001409 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001410 }
1411 if (foundW != null && foundW.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001412 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001413 "Wallpaper not changing: waiting for app anim in found target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001414 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001415 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001416 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001417
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001418 if (mWallpaperTarget != foundW) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001419 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001420 Slog.v(TAG, "New wallpaper target: " + foundW
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001421 + " oldTarget: " + mWallpaperTarget);
1422 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001423
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001424 mLowerWallpaperTarget = null;
1425 mUpperWallpaperTarget = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001426
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001427 WindowState oldW = mWallpaperTarget;
1428 mWallpaperTarget = foundW;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001429
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001430 // Now what is happening... if the current and new targets are
1431 // animating, then we are in our super special mode!
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001432 if (foundW != null && oldW != null) {
1433 boolean oldAnim = oldW.mAnimation != null
1434 || (oldW.mAppToken != null && oldW.mAppToken.animation != null);
1435 boolean foundAnim = foundW.mAnimation != null
1436 || (foundW.mAppToken != null && foundW.mAppToken.animation != null);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001437 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001438 Slog.v(TAG, "New animation: " + foundAnim
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001439 + " old animation: " + oldAnim);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001440 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001441 if (foundAnim && oldAnim) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001442 int oldI = localmWindows.indexOf(oldW);
1443 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001444 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001445 }
1446 if (oldI >= 0) {
1447 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001448 Slog.v(TAG, "Animating wallpapers: old#" + oldI
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001449 + "=" + oldW + "; new#" + foundI
1450 + "=" + foundW);
1451 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001452
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001453 // Set the new target correctly.
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001454 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001455 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001456 Slog.v(TAG, "Old wallpaper still the target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001457 }
1458 mWallpaperTarget = oldW;
1459 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001460
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001461 // Now set the upper and lower wallpaper targets
1462 // correctly, and make sure that we are positioning
1463 // the wallpaper below the lower.
1464 if (foundI > oldI) {
1465 // The new target is on top of the old one.
1466 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001467 Slog.v(TAG, "Found target above old target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001468 }
1469 mUpperWallpaperTarget = foundW;
1470 mLowerWallpaperTarget = oldW;
1471 foundW = oldW;
1472 foundI = oldI;
1473 } else {
1474 // The new target is below the old one.
1475 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001476 Slog.v(TAG, "Found target below old target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001477 }
1478 mUpperWallpaperTarget = oldW;
1479 mLowerWallpaperTarget = foundW;
1480 }
1481 }
1482 }
1483 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001484
Dianne Hackborn6b1cb352009-09-28 18:27:26 -07001485 } else if (mLowerWallpaperTarget != null) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001486 // Is it time to stop animating?
Dianne Hackborn6b1cb352009-09-28 18:27:26 -07001487 boolean lowerAnimating = mLowerWallpaperTarget.mAnimation != null
1488 || (mLowerWallpaperTarget.mAppToken != null
1489 && mLowerWallpaperTarget.mAppToken.animation != null);
1490 boolean upperAnimating = mUpperWallpaperTarget.mAnimation != null
1491 || (mUpperWallpaperTarget.mAppToken != null
1492 && mUpperWallpaperTarget.mAppToken.animation != null);
1493 if (!lowerAnimating || !upperAnimating) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001494 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001495 Slog.v(TAG, "No longer animating wallpaper targets!");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001496 }
1497 mLowerWallpaperTarget = null;
1498 mUpperWallpaperTarget = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001499 }
1500 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001501
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001502 boolean visible = foundW != null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001503 if (visible) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001504 // The window is visible to the compositor... but is it visible
1505 // to the user? That is what the wallpaper cares about.
Dianne Hackborn25994b42009-09-04 14:21:19 -07001506 visible = isWallpaperVisible(foundW);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001507 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001508
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001509 // If the wallpaper target is animating, we may need to copy
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001510 // its layer adjustment. Only do this if we are not transfering
1511 // between two wallpaper targets.
1512 mWallpaperAnimLayerAdjustment =
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001513 (mLowerWallpaperTarget == null && foundW.mAppToken != null)
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001514 ? foundW.mAppToken.animLayerAdjustment : 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001515
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001516 final int maxLayer = mPolicy.getMaxWallpaperLayer()
1517 * TYPE_LAYER_MULTIPLIER
1518 + TYPE_LAYER_OFFSET;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001519
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001520 // Now w is the window we are supposed to be behind... but we
1521 // need to be sure to also be behind any of its attached windows,
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001522 // AND any starting window associated with it, AND below the
1523 // maximum layer the policy allows for wallpapers.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001524 while (foundI > 0) {
1525 WindowState wb = (WindowState)localmWindows.get(foundI-1);
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001526 if (wb.mBaseLayer < maxLayer &&
1527 wb.mAttachedWindow != foundW &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001528 (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001529 wb.mToken != foundW.mToken)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001530 // This window is not related to the previous one in any
1531 // interesting way, so stop here.
1532 break;
1533 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001534 foundW = wb;
1535 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001536 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07001537 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001538 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001539 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001540
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001541 if (foundW == null && topCurW != null) {
1542 // There is no wallpaper target, so it goes at the bottom.
1543 // We will assume it is the same place as last time, if known.
1544 foundW = topCurW;
1545 foundI = topCurI+1;
1546 } else {
1547 // Okay i is the position immediately above the wallpaper. Look at
1548 // what is below it for later.
1549 foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
1550 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001551
Dianne Hackborn284ac932009-08-28 10:34:25 -07001552 if (visible) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001553 if (mWallpaperTarget.mWallpaperX >= 0) {
1554 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001555 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001556 }
1557 if (mWallpaperTarget.mWallpaperY >= 0) {
1558 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001559 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001560 }
Dianne Hackborn284ac932009-08-28 10:34:25 -07001561 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001562
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001563 // Start stepping backwards from here, ensuring that our wallpaper windows
1564 // are correctly placed.
1565 int curTokenIndex = mWallpaperTokens.size();
1566 while (curTokenIndex > 0) {
1567 curTokenIndex--;
1568 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001569 if (token.hidden == visible) {
1570 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1571 token.hidden = !visible;
1572 // Need to do a layout to ensure the wallpaper now has the
1573 // correct size.
1574 mLayoutNeeded = true;
1575 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001576
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001577 int curWallpaperIndex = token.windows.size();
1578 while (curWallpaperIndex > 0) {
1579 curWallpaperIndex--;
1580 WindowState wallpaper = token.windows.get(curWallpaperIndex);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001581
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001582 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001583 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001584 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001585
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001586 // First, make sure the client has the current visibility
1587 // state.
1588 if (wallpaper.mWallpaperVisible != visible) {
1589 wallpaper.mWallpaperVisible = visible;
1590 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001591 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001592 "Setting visibility of wallpaper " + wallpaper
1593 + ": " + visible);
1594 wallpaper.mClient.dispatchAppVisibility(visible);
1595 } catch (RemoteException e) {
1596 }
1597 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001598
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001599 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001600 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001601 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001602
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001603 // First, if this window is at the current index, then all
1604 // is well.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001605 if (wallpaper == foundW) {
1606 foundI--;
1607 foundW = foundI > 0
1608 ? (WindowState)localmWindows.get(foundI-1) : null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001609 continue;
1610 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001611
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001612 // The window didn't match... the current wallpaper window,
1613 // wherever it is, is in the wrong place, so make sure it is
1614 // not in the list.
1615 int oldIndex = localmWindows.indexOf(wallpaper);
1616 if (oldIndex >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001617 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001618 + oldIndex + ": " + wallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001619 localmWindows.remove(oldIndex);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001620 if (oldIndex < foundI) {
1621 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001622 }
1623 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001624
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001625 // Now stick it in.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001626 if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001627 "Moving wallpaper " + wallpaper
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001628 + " from " + oldIndex + " to " + foundI);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001629
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001630 localmWindows.add(foundI, wallpaper);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001631 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001632 }
1633 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001634
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001635 return changed;
1636 }
1637
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001638 void setWallpaperAnimLayerAdjustmentLocked(int adj) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001639 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001640 "Setting wallpaper layer adj to " + adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001641 mWallpaperAnimLayerAdjustment = adj;
1642 int curTokenIndex = mWallpaperTokens.size();
1643 while (curTokenIndex > 0) {
1644 curTokenIndex--;
1645 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1646 int curWallpaperIndex = token.windows.size();
1647 while (curWallpaperIndex > 0) {
1648 curWallpaperIndex--;
1649 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1650 wallpaper.mAnimLayer = wallpaper.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001651 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001652 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001653 }
1654 }
1655 }
1656
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001657 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1658 boolean sync) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001659 boolean changed = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001660 boolean rawChanged = false;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001661 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001662 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001663 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1664 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1665 changed = wallpaperWin.mXOffset != offset;
1666 if (changed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001667 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001668 + wallpaperWin + " x: " + offset);
1669 wallpaperWin.mXOffset = offset;
1670 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001671 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001672 wallpaperWin.mWallpaperX = wpx;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001673 wallpaperWin.mWallpaperXStep = wpxs;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001674 rawChanged = true;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001675 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001676
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001677 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001678 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001679 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1680 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
1681 if (wallpaperWin.mYOffset != offset) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001682 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001683 + wallpaperWin + " y: " + offset);
1684 changed = true;
1685 wallpaperWin.mYOffset = offset;
1686 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001687 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001688 wallpaperWin.mWallpaperY = wpy;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001689 wallpaperWin.mWallpaperYStep = wpys;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001690 rawChanged = true;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001691 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001692
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001693 if (rawChanged) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001694 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001695 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001696 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1697 + " y=" + wallpaperWin.mWallpaperY);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001698 if (sync) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001699 mWaitingOnWallpaper = wallpaperWin;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001700 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001701 wallpaperWin.mClient.dispatchWallpaperOffsets(
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001702 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
1703 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001704 if (sync) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001705 if (mWaitingOnWallpaper != null) {
1706 long start = SystemClock.uptimeMillis();
1707 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
1708 < start) {
1709 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001710 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn75804932009-10-20 20:15:20 -07001711 "Waiting for offset complete...");
1712 mWindowMap.wait(WALLPAPER_TIMEOUT);
1713 } catch (InterruptedException e) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001714 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001715 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
Dianne Hackborn75804932009-10-20 20:15:20 -07001716 if ((start+WALLPAPER_TIMEOUT)
1717 < SystemClock.uptimeMillis()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001718 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
Dianne Hackborn75804932009-10-20 20:15:20 -07001719 + wallpaperWin);
1720 mLastWallpaperTimeoutTime = start;
1721 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001722 }
Dianne Hackborn75804932009-10-20 20:15:20 -07001723 mWaitingOnWallpaper = null;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001724 }
1725 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001726 } catch (RemoteException e) {
1727 }
1728 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001729
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001730 return changed;
1731 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001732
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001733 void wallpaperOffsetsComplete(IBinder window) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001734 synchronized (mWindowMap) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001735 if (mWaitingOnWallpaper != null &&
1736 mWaitingOnWallpaper.mClient.asBinder() == window) {
1737 mWaitingOnWallpaper = null;
Dianne Hackborn75804932009-10-20 20:15:20 -07001738 mWindowMap.notifyAll();
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001739 }
1740 }
1741 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001742
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001743 boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001744 final int dw = mDisplay.getWidth();
1745 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001746
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001747 boolean changed = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001748
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001749 WindowState target = mWallpaperTarget;
1750 if (target != null) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001751 if (target.mWallpaperX >= 0) {
1752 mLastWallpaperX = target.mWallpaperX;
1753 } else if (changingTarget.mWallpaperX >= 0) {
1754 mLastWallpaperX = changingTarget.mWallpaperX;
1755 }
1756 if (target.mWallpaperY >= 0) {
1757 mLastWallpaperY = target.mWallpaperY;
1758 } else if (changingTarget.mWallpaperY >= 0) {
1759 mLastWallpaperY = changingTarget.mWallpaperY;
1760 }
1761 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001762
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001763 int curTokenIndex = mWallpaperTokens.size();
1764 while (curTokenIndex > 0) {
1765 curTokenIndex--;
1766 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1767 int curWallpaperIndex = token.windows.size();
1768 while (curWallpaperIndex > 0) {
1769 curWallpaperIndex--;
1770 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1771 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
1772 wallpaper.computeShownFrameLocked();
1773 changed = true;
1774 // We only want to be synchronous with one wallpaper.
1775 sync = false;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001776 }
1777 }
1778 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001779
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001780 return changed;
1781 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001782
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001783 void updateWallpaperVisibilityLocked() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07001784 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001785 final int dw = mDisplay.getWidth();
1786 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001787
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001788 int curTokenIndex = mWallpaperTokens.size();
1789 while (curTokenIndex > 0) {
1790 curTokenIndex--;
1791 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001792 if (token.hidden == visible) {
1793 token.hidden = !visible;
1794 // Need to do a layout to ensure the wallpaper now has the
1795 // correct size.
1796 mLayoutNeeded = true;
1797 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001798
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001799 int curWallpaperIndex = token.windows.size();
1800 while (curWallpaperIndex > 0) {
1801 curWallpaperIndex--;
1802 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1803 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001804 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001805 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001806
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001807 if (wallpaper.mWallpaperVisible != visible) {
1808 wallpaper.mWallpaperVisible = visible;
1809 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001810 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07001811 "Updating visibility of wallpaper " + wallpaper
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001812 + ": " + visible);
1813 wallpaper.mClient.dispatchAppVisibility(visible);
1814 } catch (RemoteException e) {
1815 }
1816 }
1817 }
1818 }
1819 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001820
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001821 void sendPointerToWallpaperLocked(WindowState srcWin,
1822 MotionEvent pointer, long eventTime) {
1823 int curTokenIndex = mWallpaperTokens.size();
1824 while (curTokenIndex > 0) {
1825 curTokenIndex--;
1826 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1827 int curWallpaperIndex = token.windows.size();
1828 while (curWallpaperIndex > 0) {
1829 curWallpaperIndex--;
1830 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1831 if ((wallpaper.mAttrs.flags &
1832 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
1833 continue;
1834 }
1835 try {
1836 MotionEvent ev = MotionEvent.obtainNoHistory(pointer);
Dianne Hackborn6adba242009-11-10 11:10:09 -08001837 if (srcWin != null) {
1838 ev.offsetLocation(srcWin.mFrame.left-wallpaper.mFrame.left,
1839 srcWin.mFrame.top-wallpaper.mFrame.top);
1840 } else {
1841 ev.offsetLocation(-wallpaper.mFrame.left, -wallpaper.mFrame.top);
1842 }
1843 switch (pointer.getAction()) {
1844 case MotionEvent.ACTION_DOWN:
1845 mSendingPointersToWallpaper = true;
1846 break;
1847 case MotionEvent.ACTION_UP:
1848 mSendingPointersToWallpaper = false;
1849 break;
1850 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001851 wallpaper.mClient.dispatchPointer(ev, eventTime, false);
1852 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001853 Slog.w(TAG, "Failure sending pointer to wallpaper", e);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001854 }
1855 }
1856 }
1857 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001858
Dianne Hackborn90d2db32010-02-11 22:19:06 -08001859 void dispatchPointerElsewhereLocked(WindowState srcWin, WindowState relWin,
1860 MotionEvent pointer, long eventTime, boolean skipped) {
1861 if (relWin != null) {
1862 mPolicy.dispatchedPointerEventLw(pointer, relWin.mFrame.left, relWin.mFrame.top);
1863 } else {
1864 mPolicy.dispatchedPointerEventLw(pointer, 0, 0);
1865 }
1866
1867 // If we sent an initial down to the wallpaper, then continue
1868 // sending events until the final up.
1869 if (mSendingPointersToWallpaper) {
1870 if (skipped) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001871 Slog.i(TAG, "Sending skipped pointer to wallpaper!");
Dianne Hackborn90d2db32010-02-11 22:19:06 -08001872 }
1873 sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1874
1875 // If we are on top of the wallpaper, then the wallpaper also
1876 // gets to see this movement.
1877 } else if (srcWin != null
1878 && pointer.getAction() == MotionEvent.ACTION_DOWN
1879 && mWallpaperTarget == srcWin
1880 && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
1881 sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1882 }
1883 }
1884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 public int addWindow(Session session, IWindow client,
1886 WindowManager.LayoutParams attrs, int viewVisibility,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001887 Rect outContentInsets, InputChannel outInputChannel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 int res = mPolicy.checkAddPermission(attrs);
1889 if (res != WindowManagerImpl.ADD_OKAY) {
1890 return res;
1891 }
Romain Guy06882f82009-06-10 13:36:04 -07001892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 boolean reportNewConfig = false;
1894 WindowState attachedWindow = null;
1895 WindowState win = null;
Romain Guy06882f82009-06-10 13:36:04 -07001896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001897 synchronized(mWindowMap) {
1898 // Instantiating a Display requires talking with the simulator,
1899 // so don't do it until we know the system is mostly up and
1900 // running.
1901 if (mDisplay == null) {
1902 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1903 mDisplay = wm.getDefaultDisplay();
Christopher Tateb696aee2010-04-02 19:08:30 -07001904 mInitialDisplayWidth = mDisplay.getWidth();
1905 mInitialDisplayHeight = mDisplay.getHeight();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001906 if (ENABLE_NATIVE_INPUT_DISPATCH) {
1907 mInputManager.setDisplaySize(0,
1908 mInitialDisplayWidth, mInitialDisplayHeight);
1909 } else {
1910 mQueue.setDisplay(mDisplay);
1911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 reportNewConfig = true;
1913 }
Romain Guy06882f82009-06-10 13:36:04 -07001914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 if (mWindowMap.containsKey(client.asBinder())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001916 Slog.w(TAG, "Window " + client + " is already added");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 return WindowManagerImpl.ADD_DUPLICATE_ADD;
1918 }
1919
1920 if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001921 attachedWindow = windowForClientLocked(null, attrs.token, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 if (attachedWindow == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001923 Slog.w(TAG, "Attempted to add window with token that is not a window: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 + attrs.token + ". Aborting.");
1925 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1926 }
1927 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1928 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001929 Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 + attrs.token + ". Aborting.");
1931 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1932 }
1933 }
1934
1935 boolean addToken = false;
1936 WindowToken token = mTokenMap.get(attrs.token);
1937 if (token == null) {
1938 if (attrs.type >= FIRST_APPLICATION_WINDOW
1939 && attrs.type <= LAST_APPLICATION_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001940 Slog.w(TAG, "Attempted to add application window with unknown token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941 + attrs.token + ". Aborting.");
1942 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1943 }
1944 if (attrs.type == TYPE_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001945 Slog.w(TAG, "Attempted to add input method window with unknown token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 + attrs.token + ". Aborting.");
1947 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1948 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001949 if (attrs.type == TYPE_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001950 Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001951 + attrs.token + ". Aborting.");
1952 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1953 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001954 token = new WindowToken(attrs.token, -1, false);
1955 addToken = true;
1956 } else if (attrs.type >= FIRST_APPLICATION_WINDOW
1957 && attrs.type <= LAST_APPLICATION_WINDOW) {
1958 AppWindowToken atoken = token.appWindowToken;
1959 if (atoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001960 Slog.w(TAG, "Attempted to add window with non-application token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001961 + token + ". Aborting.");
1962 return WindowManagerImpl.ADD_NOT_APP_TOKEN;
1963 } else if (atoken.removed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001964 Slog.w(TAG, "Attempted to add window with exiting application token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 + token + ". Aborting.");
1966 return WindowManagerImpl.ADD_APP_EXITING;
1967 }
1968 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1969 // No need for this guy!
Joe Onorato8a9b2202010-02-26 18:56:32 -08001970 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001971 TAG, "**** NO NEED TO START: " + attrs.getTitle());
1972 return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
1973 }
1974 } else if (attrs.type == TYPE_INPUT_METHOD) {
1975 if (token.windowType != TYPE_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001976 Slog.w(TAG, "Attempted to add input method window with bad token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001977 + attrs.token + ". Aborting.");
1978 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1979 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001980 } else if (attrs.type == TYPE_WALLPAPER) {
1981 if (token.windowType != TYPE_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001982 Slog.w(TAG, "Attempted to add wallpaper window with bad token "
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001983 + attrs.token + ". Aborting.");
1984 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1985 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001986 }
1987
1988 win = new WindowState(session, client, token,
1989 attachedWindow, attrs, viewVisibility);
1990 if (win.mDeathRecipient == null) {
1991 // Client has apparently died, so there is no reason to
1992 // continue.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001993 Slog.w(TAG, "Adding window client " + client.asBinder()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994 + " that is dead, aborting.");
1995 return WindowManagerImpl.ADD_APP_EXITING;
1996 }
1997
1998 mPolicy.adjustWindowParamsLw(win.mAttrs);
Romain Guy06882f82009-06-10 13:36:04 -07001999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 res = mPolicy.prepareAddWindowLw(win, attrs);
2001 if (res != WindowManagerImpl.ADD_OKAY) {
2002 return res;
2003 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002004
2005 if (ENABLE_NATIVE_INPUT_DISPATCH) {
2006 if (outInputChannel != null) {
2007 String name = win.makeInputChannelName();
2008 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
2009 win.mInputChannel = inputChannels[0];
2010 inputChannels[1].transferToBinderOutParameter(outInputChannel);
2011
2012 mInputManager.registerInputChannel(win.mInputChannel);
2013 }
2014 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015
2016 // From now on, no exceptions or errors allowed!
2017
2018 res = WindowManagerImpl.ADD_OKAY;
Romain Guy06882f82009-06-10 13:36:04 -07002019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002020 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002022 if (addToken) {
2023 mTokenMap.put(attrs.token, token);
2024 mTokenList.add(token);
2025 }
2026 win.attach();
2027 mWindowMap.put(client.asBinder(), win);
2028
2029 if (attrs.type == TYPE_APPLICATION_STARTING &&
2030 token.appWindowToken != null) {
2031 token.appWindowToken.startingWindow = win;
2032 }
2033
2034 boolean imMayMove = true;
Romain Guy06882f82009-06-10 13:36:04 -07002035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002036 if (attrs.type == TYPE_INPUT_METHOD) {
2037 mInputMethodWindow = win;
2038 addInputMethodWindowToListLocked(win);
2039 imMayMove = false;
2040 } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
2041 mInputMethodDialogs.add(win);
2042 addWindowToListInOrderLocked(win, true);
2043 adjustInputMethodDialogsLocked();
2044 imMayMove = false;
2045 } else {
2046 addWindowToListInOrderLocked(win, true);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002047 if (attrs.type == TYPE_WALLPAPER) {
2048 mLastWallpaperTimeoutTime = 0;
2049 adjustWallpaperWindowsLocked();
2050 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002051 adjustWallpaperWindowsLocked();
2052 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 }
Romain Guy06882f82009-06-10 13:36:04 -07002054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 win.mEnterAnimationPending = true;
Romain Guy06882f82009-06-10 13:36:04 -07002056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
Romain Guy06882f82009-06-10 13:36:04 -07002058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 if (mInTouchMode) {
2060 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
2061 }
2062 if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
2063 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
2064 }
Romain Guy06882f82009-06-10 13:36:04 -07002065
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002066 boolean focusChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002067 if (win.canReceiveKeys()) {
Jeff Brown349703e2010-06-22 01:27:15 -07002068 focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS);
2069 if (focusChanged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 imMayMove = false;
2071 }
2072 }
Romain Guy06882f82009-06-10 13:36:04 -07002073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002074 if (imMayMove) {
Romain Guy06882f82009-06-10 13:36:04 -07002075 moveInputMethodWindowsIfNeededLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076 }
Romain Guy06882f82009-06-10 13:36:04 -07002077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002078 assignLayersLocked();
2079 // Don't do layout here, the window must call
2080 // relayout to be displayed, so we'll do it there.
Romain Guy06882f82009-06-10 13:36:04 -07002081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 //dump();
2083
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002084 if (focusChanged) {
Jeff Brown349703e2010-06-22 01:27:15 -07002085 finishUpdateFocusedWindowAfterAssignLayersLocked();
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002086 }
Jeff Brown349703e2010-06-22 01:27:15 -07002087
Joe Onorato8a9b2202010-02-26 18:56:32 -08002088 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 TAG, "New client " + client.asBinder()
2090 + ": window=" + win);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002091
2092 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked()) {
2093 reportNewConfig = true;
2094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002095 }
2096
2097 // sendNewConfiguration() checks caller permissions so we must call it with
2098 // privilege. updateOrientationFromAppTokens() clears and resets the caller
2099 // identity anyway, so it's safe to just clear & restore around this whole
2100 // block.
2101 final long origId = Binder.clearCallingIdentity();
2102 if (reportNewConfig) {
2103 sendNewConfiguration();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002104 }
2105 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07002106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002107 return res;
2108 }
Romain Guy06882f82009-06-10 13:36:04 -07002109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 public void removeWindow(Session session, IWindow client) {
2111 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002112 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002113 if (win == null) {
2114 return;
2115 }
2116 removeWindowLocked(session, win);
2117 }
2118 }
Romain Guy06882f82009-06-10 13:36:04 -07002119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002120 public void removeWindowLocked(Session session, WindowState win) {
2121
Joe Onorato8a9b2202010-02-26 18:56:32 -08002122 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 TAG, "Remove " + win + " client="
2124 + Integer.toHexString(System.identityHashCode(
2125 win.mClient.asBinder()))
2126 + ", surface=" + win.mSurface);
2127
2128 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002129
Joe Onorato8a9b2202010-02-26 18:56:32 -08002130 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002131 TAG, "Remove " + win + ": mSurface=" + win.mSurface
2132 + " mExiting=" + win.mExiting
2133 + " isAnimating=" + win.isAnimating()
2134 + " app-animation="
2135 + (win.mAppToken != null ? win.mAppToken.animation : null)
2136 + " inPendingTransaction="
2137 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2138 + " mDisplayFrozen=" + mDisplayFrozen);
2139 // Visibility of the removed window. Will be used later to update orientation later on.
2140 boolean wasVisible = false;
2141 // First, see if we need to run an animation. If we do, we have
2142 // to hold off on removing the window until the animation is done.
2143 // If the display is frozen, just remove immediately, since the
2144 // animation wouldn't be seen.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002145 if (win.mSurface != null && !mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 // If we are not currently running the exit animation, we
2147 // need to see about starting one.
2148 if (wasVisible=win.isWinVisibleLw()) {
Romain Guy06882f82009-06-10 13:36:04 -07002149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002150 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2151 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2152 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2153 }
2154 // Try starting an animation.
2155 if (applyAnimationLocked(win, transit, false)) {
2156 win.mExiting = true;
2157 }
2158 }
2159 if (win.mExiting || win.isAnimating()) {
2160 // The exit animation is running... wait for it!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002161 //Slog.i(TAG, "*** Running exit animation...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 win.mExiting = true;
2163 win.mRemoveOnExit = true;
2164 mLayoutNeeded = true;
2165 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
2166 performLayoutAndPlaceSurfacesLocked();
2167 if (win.mAppToken != null) {
2168 win.mAppToken.updateReportedVisibilityLocked();
2169 }
2170 //dump();
2171 Binder.restoreCallingIdentity(origId);
2172 return;
2173 }
2174 }
2175
2176 removeWindowInnerLocked(session, win);
2177 // Removing a visible window will effect the computed orientation
2178 // So just update orientation if needed.
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002179 if (wasVisible && computeForcedAppOrientationLocked()
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002180 != mForcedAppOrientation
2181 && updateOrientationFromAppTokensLocked()) {
2182 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 }
2184 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2185 Binder.restoreCallingIdentity(origId);
2186 }
Romain Guy06882f82009-06-10 13:36:04 -07002187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 private void removeWindowInnerLocked(Session session, WindowState win) {
Jeff Brown349703e2010-06-22 01:27:15 -07002189 if (ENABLE_NATIVE_INPUT_DISPATCH) {
2190 mInputMonitor.windowIsBeingRemovedLw(win);
2191 } else {
2192 mKeyWaiter.finishedKey(session, win.mClient, true,
2193 KeyWaiter.RETURN_NOTHING);
2194 mKeyWaiter.releasePendingPointerLocked(win.mSession);
2195 mKeyWaiter.releasePendingTrackballLocked(win.mSession);
2196 }
Romain Guy06882f82009-06-10 13:36:04 -07002197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 win.mRemoved = true;
Romain Guy06882f82009-06-10 13:36:04 -07002199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002200 if (mInputMethodTarget == win) {
2201 moveInputMethodWindowsIfNeededLocked(false);
2202 }
Romain Guy06882f82009-06-10 13:36:04 -07002203
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002204 if (false) {
2205 RuntimeException e = new RuntimeException("here");
2206 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002207 Slog.w(TAG, "Removing window " + win, e);
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002208 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002210 mPolicy.removeWindowLw(win);
2211 win.removeLocked();
2212
2213 mWindowMap.remove(win.mClient.asBinder());
2214 mWindows.remove(win);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002215 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002216
2217 if (mInputMethodWindow == win) {
2218 mInputMethodWindow = null;
2219 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2220 mInputMethodDialogs.remove(win);
2221 }
Romain Guy06882f82009-06-10 13:36:04 -07002222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 final WindowToken token = win.mToken;
2224 final AppWindowToken atoken = win.mAppToken;
2225 token.windows.remove(win);
2226 if (atoken != null) {
2227 atoken.allAppWindows.remove(win);
2228 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002229 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002230 TAG, "**** Removing window " + win + ": count="
2231 + token.windows.size());
2232 if (token.windows.size() == 0) {
2233 if (!token.explicit) {
2234 mTokenMap.remove(token.token);
2235 mTokenList.remove(token);
2236 } else if (atoken != null) {
2237 atoken.firstWindowDrawn = false;
2238 }
2239 }
2240
2241 if (atoken != null) {
2242 if (atoken.startingWindow == win) {
2243 atoken.startingWindow = null;
2244 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2245 // If this is the last window and we had requested a starting
2246 // transition window, well there is no point now.
2247 atoken.startingData = null;
2248 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2249 // If this is the last window except for a starting transition
2250 // window, we need to get rid of the starting transition.
2251 if (DEBUG_STARTING_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002252 Slog.v(TAG, "Schedule remove starting " + token
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 + ": no more real windows");
2254 }
2255 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
2256 mH.sendMessage(m);
2257 }
2258 }
Romain Guy06882f82009-06-10 13:36:04 -07002259
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002260 if (win.mAttrs.type == TYPE_WALLPAPER) {
2261 mLastWallpaperTimeoutTime = 0;
2262 adjustWallpaperWindowsLocked();
2263 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07002264 adjustWallpaperWindowsLocked();
2265 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 if (!mInLayout) {
2268 assignLayersLocked();
2269 mLayoutNeeded = true;
2270 performLayoutAndPlaceSurfacesLocked();
2271 if (win.mAppToken != null) {
2272 win.mAppToken.updateReportedVisibilityLocked();
2273 }
2274 }
2275 }
2276
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002277 private static void logSurface(WindowState w, String msg, RuntimeException where) {
2278 String str = " SURFACE " + Integer.toHexString(w.hashCode())
2279 + ": " + msg + " / " + w.mAttrs.getTitle();
2280 if (where != null) {
2281 Slog.i(TAG, str, where);
2282 } else {
2283 Slog.i(TAG, str);
2284 }
2285 }
2286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2288 long origId = Binder.clearCallingIdentity();
2289 try {
2290 synchronized (mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002291 WindowState w = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002292 if ((w != null) && (w.mSurface != null)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002293 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002294 Surface.openTransaction();
2295 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002296 if (SHOW_TRANSACTIONS) logSurface(w,
2297 "transparentRegionHint=" + region, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002298 w.mSurface.setTransparentRegionHint(region);
2299 } finally {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002300 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301 Surface.closeTransaction();
2302 }
2303 }
2304 }
2305 } finally {
2306 Binder.restoreCallingIdentity(origId);
2307 }
2308 }
2309
2310 void setInsetsWindow(Session session, IWindow client,
Romain Guy06882f82009-06-10 13:36:04 -07002311 int touchableInsets, Rect contentInsets,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002312 Rect visibleInsets) {
2313 long origId = Binder.clearCallingIdentity();
2314 try {
2315 synchronized (mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002316 WindowState w = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002317 if (w != null) {
2318 w.mGivenInsetsPending = false;
2319 w.mGivenContentInsets.set(contentInsets);
2320 w.mGivenVisibleInsets.set(visibleInsets);
2321 w.mTouchableInsets = touchableInsets;
2322 mLayoutNeeded = true;
2323 performLayoutAndPlaceSurfacesLocked();
2324 }
2325 }
2326 } finally {
2327 Binder.restoreCallingIdentity(origId);
2328 }
2329 }
Romain Guy06882f82009-06-10 13:36:04 -07002330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002331 public void getWindowDisplayFrame(Session session, IWindow client,
2332 Rect outDisplayFrame) {
2333 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002334 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002335 if (win == null) {
2336 outDisplayFrame.setEmpty();
2337 return;
2338 }
2339 outDisplayFrame.set(win.mDisplayFrame);
2340 }
2341 }
2342
Marco Nelissenbf6956b2009-11-09 15:21:13 -08002343 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2344 float xStep, float yStep) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002345 if (window.mWallpaperX != x || window.mWallpaperY != y) {
2346 window.mWallpaperX = x;
2347 window.mWallpaperY = y;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08002348 window.mWallpaperXStep = xStep;
2349 window.mWallpaperYStep = yStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07002350 if (updateWallpaperOffsetLocked(window, true)) {
2351 performLayoutAndPlaceSurfacesLocked();
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002352 }
2353 }
2354 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002355
Dianne Hackborn75804932009-10-20 20:15:20 -07002356 void wallpaperCommandComplete(IBinder window, Bundle result) {
2357 synchronized (mWindowMap) {
2358 if (mWaitingOnWallpaper != null &&
2359 mWaitingOnWallpaper.mClient.asBinder() == window) {
2360 mWaitingOnWallpaper = null;
2361 mWindowMap.notifyAll();
2362 }
2363 }
2364 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002365
Dianne Hackborn75804932009-10-20 20:15:20 -07002366 public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2367 String action, int x, int y, int z, Bundle extras, boolean sync) {
2368 if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2369 || window == mUpperWallpaperTarget) {
2370 boolean doWait = sync;
2371 int curTokenIndex = mWallpaperTokens.size();
2372 while (curTokenIndex > 0) {
2373 curTokenIndex--;
2374 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2375 int curWallpaperIndex = token.windows.size();
2376 while (curWallpaperIndex > 0) {
2377 curWallpaperIndex--;
2378 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2379 try {
2380 wallpaper.mClient.dispatchWallpaperCommand(action,
2381 x, y, z, extras, sync);
2382 // We only want to be synchronous with one wallpaper.
2383 sync = false;
2384 } catch (RemoteException e) {
2385 }
2386 }
2387 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002388
Dianne Hackborn75804932009-10-20 20:15:20 -07002389 if (doWait) {
2390 // XXX Need to wait for result.
2391 }
2392 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002393
Dianne Hackborn75804932009-10-20 20:15:20 -07002394 return null;
2395 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002396
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 public int relayoutWindow(Session session, IWindow client,
2398 WindowManager.LayoutParams attrs, int requestedWidth,
2399 int requestedHeight, int viewVisibility, boolean insetsPending,
2400 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07002401 Configuration outConfig, Surface outSurface) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 boolean displayed = false;
2403 boolean inTouchMode;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002404 boolean configChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002405 long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002407 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002408 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002409 if (win == null) {
2410 return 0;
2411 }
2412 win.mRequestedWidth = requestedWidth;
2413 win.mRequestedHeight = requestedHeight;
2414
2415 if (attrs != null) {
2416 mPolicy.adjustWindowParamsLw(attrs);
2417 }
Romain Guy06882f82009-06-10 13:36:04 -07002418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002419 int attrChanges = 0;
2420 int flagChanges = 0;
2421 if (attrs != null) {
2422 flagChanges = win.mAttrs.flags ^= attrs.flags;
2423 attrChanges = win.mAttrs.copyFrom(attrs);
2424 }
2425
Joe Onorato8a9b2202010-02-26 18:56:32 -08002426 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": " + win.mAttrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002427
2428 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2429 win.mAlpha = attrs.alpha;
2430 }
2431
2432 final boolean scaledWindow =
2433 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2434
2435 if (scaledWindow) {
2436 // requested{Width|Height} Surface's physical size
2437 // attrs.{width|height} Size on screen
2438 win.mHScale = (attrs.width != requestedWidth) ?
2439 (attrs.width / (float)requestedWidth) : 1.0f;
2440 win.mVScale = (attrs.height != requestedHeight) ?
2441 (attrs.height / (float)requestedHeight) : 1.0f;
Dianne Hackborn9b52a212009-12-11 14:51:35 -08002442 } else {
2443 win.mHScale = win.mVScale = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002444 }
2445
2446 boolean imMayMove = (flagChanges&(
2447 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
2448 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07002449
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002450 boolean focusMayChange = win.mViewVisibility != viewVisibility
2451 || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
2452 || (!win.mRelayoutCalled);
Romain Guy06882f82009-06-10 13:36:04 -07002453
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002454 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2455 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002457 win.mRelayoutCalled = true;
2458 final int oldVisibility = win.mViewVisibility;
2459 win.mViewVisibility = viewVisibility;
2460 if (viewVisibility == View.VISIBLE &&
2461 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2462 displayed = !win.isVisibleLw();
2463 if (win.mExiting) {
2464 win.mExiting = false;
2465 win.mAnimation = null;
2466 }
2467 if (win.mDestroying) {
2468 win.mDestroying = false;
2469 mDestroySurface.remove(win);
2470 }
2471 if (oldVisibility == View.GONE) {
2472 win.mEnterAnimationPending = true;
2473 }
Dianne Hackborn694f79b2010-03-17 19:44:59 -07002474 if (displayed) {
2475 if (win.mSurface != null && !win.mDrawPending
2476 && !win.mCommitDrawPending && !mDisplayFrozen
2477 && mPolicy.isScreenOn()) {
2478 applyEnterAnimationLocked(win);
2479 }
2480 if ((win.mAttrs.flags
2481 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2482 if (DEBUG_VISIBILITY) Slog.v(TAG,
2483 "Relayout window turning screen on: " + win);
2484 win.mTurnOnScreen = true;
2485 }
2486 int diff = 0;
2487 if (win.mConfiguration != mCurConfiguration
2488 && (win.mConfiguration == null
2489 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0)) {
2490 win.mConfiguration = mCurConfiguration;
2491 if (DEBUG_CONFIGURATION) {
2492 Slog.i(TAG, "Window " + win + " visible with new config: "
2493 + win.mConfiguration + " / 0x"
2494 + Integer.toHexString(diff));
2495 }
2496 outConfig.setTo(mCurConfiguration);
2497 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07002498 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002499 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2500 // To change the format, we need to re-build the surface.
2501 win.destroySurfaceLocked();
2502 displayed = true;
2503 }
2504 try {
2505 Surface surface = win.createSurfaceLocked();
2506 if (surface != null) {
2507 outSurface.copyFrom(surface);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002508 win.mReportDestroySurface = false;
2509 win.mSurfacePendingDestroy = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002510 if (SHOW_TRANSACTIONS) Slog.i(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002511 " OUT SURFACE " + outSurface + ": copied");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002512 } else {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002513 // For some reason there isn't a surface. Clear the
2514 // caller's object so they see the same state.
2515 outSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 }
2517 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002518 Slog.w(TAG, "Exception thrown when creating surface for client "
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002519 + client + " (" + win.mAttrs.getTitle() + ")",
2520 e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002521 Binder.restoreCallingIdentity(origId);
2522 return 0;
2523 }
2524 if (displayed) {
2525 focusMayChange = true;
2526 }
2527 if (win.mAttrs.type == TYPE_INPUT_METHOD
2528 && mInputMethodWindow == null) {
2529 mInputMethodWindow = win;
2530 imMayMove = true;
2531 }
Dianne Hackborn558947c2009-12-18 16:02:50 -08002532 if (win.mAttrs.type == TYPE_BASE_APPLICATION
2533 && win.mAppToken != null
2534 && win.mAppToken.startingWindow != null) {
2535 // Special handling of starting window over the base
2536 // window of the app: propagate lock screen flags to it,
2537 // to provide the correct semantics while starting.
2538 final int mask =
2539 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
Mike Lockwoodef731622010-01-27 17:51:34 -05002540 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
2541 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
Dianne Hackborn558947c2009-12-18 16:02:50 -08002542 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
2543 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
2544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002545 } else {
2546 win.mEnterAnimationPending = false;
2547 if (win.mSurface != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002548 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002549 + ": mExiting=" + win.mExiting
2550 + " mSurfacePendingDestroy=" + win.mSurfacePendingDestroy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002551 // If we are not currently running the exit animation, we
2552 // need to see about starting one.
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002553 if (!win.mExiting || win.mSurfacePendingDestroy) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002554 // Try starting an animation; if there isn't one, we
2555 // can destroy the surface right away.
2556 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2557 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2558 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2559 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002560 if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 applyAnimationLocked(win, transit, false)) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002562 focusMayChange = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002563 win.mExiting = true;
Jeff Brown349703e2010-06-22 01:27:15 -07002564 if (ENABLE_NATIVE_INPUT_DISPATCH) {
2565 mInputMonitor.windowIsBecomingInvisibleLw(win);
2566 } else {
2567 mKeyWaiter.finishedKey(session, client, true,
2568 KeyWaiter.RETURN_NOTHING);
2569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 } else if (win.isAnimating()) {
2571 // Currently in a hide animation... turn this into
2572 // an exit.
2573 win.mExiting = true;
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07002574 } else if (win == mWallpaperTarget) {
2575 // If the wallpaper is currently behind this
2576 // window, we need to change both of them inside
2577 // of a transaction to avoid artifacts.
2578 win.mExiting = true;
2579 win.mAnimating = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002580 } else {
2581 if (mInputMethodWindow == win) {
2582 mInputMethodWindow = null;
2583 }
2584 win.destroySurfaceLocked();
2585 }
2586 }
2587 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002588
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002589 if (win.mSurface == null || (win.getAttrs().flags
2590 & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0
2591 || win.mSurfacePendingDestroy) {
2592 // We are being called from a local process, which
2593 // means outSurface holds its current surface. Ensure the
2594 // surface object is cleared, but we don't want it actually
2595 // destroyed at this point.
2596 win.mSurfacePendingDestroy = false;
2597 outSurface.release();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002598 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002599 } else if (win.mSurface != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002600 if (DEBUG_VISIBILITY) Slog.i(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002601 "Keeping surface, will report destroy: " + win);
2602 win.mReportDestroySurface = true;
2603 outSurface.copyFrom(win.mSurface);
2604 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 }
2606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 if (focusMayChange) {
2608 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2609 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610 imMayMove = false;
2611 }
2612 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2613 }
Romain Guy06882f82009-06-10 13:36:04 -07002614
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002615 // updateFocusedWindowLocked() already assigned layers so we only need to
2616 // reassign them at this point if the IM window state gets shuffled
2617 boolean assignLayers = false;
Romain Guy06882f82009-06-10 13:36:04 -07002618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619 if (imMayMove) {
Dianne Hackborn8abd5f02009-11-20 18:09:03 -08002620 if (moveInputMethodWindowsIfNeededLocked(false) || displayed) {
2621 // Little hack here -- we -should- be able to rely on the
2622 // function to return true if the IME has moved and needs
2623 // its layer recomputed. However, if the IME was hidden
2624 // and isn't actually moved in the list, its layer may be
2625 // out of data so we make sure to recompute it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002626 assignLayers = true;
2627 }
2628 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002629 if (wallpaperMayMove) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002630 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002631 assignLayers = true;
2632 }
2633 }
Romain Guy06882f82009-06-10 13:36:04 -07002634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 mLayoutNeeded = true;
2636 win.mGivenInsetsPending = insetsPending;
2637 if (assignLayers) {
2638 assignLayersLocked();
2639 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002640 configChanged = updateOrientationFromAppTokensLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 performLayoutAndPlaceSurfacesLocked();
Dianne Hackborn284ac932009-08-28 10:34:25 -07002642 if (displayed && win.mIsWallpaper) {
2643 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002644 mDisplay.getHeight(), false);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002646 if (win.mAppToken != null) {
2647 win.mAppToken.updateReportedVisibilityLocked();
2648 }
2649 outFrame.set(win.mFrame);
2650 outContentInsets.set(win.mContentInsets);
2651 outVisibleInsets.set(win.mVisibleInsets);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002652 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002653 TAG, "Relayout given client " + client.asBinder()
Romain Guy06882f82009-06-10 13:36:04 -07002654 + ", requestedWidth=" + requestedWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 + ", requestedHeight=" + requestedHeight
2656 + ", viewVisibility=" + viewVisibility
2657 + "\nRelayout returning frame=" + outFrame
2658 + ", surface=" + outSurface);
2659
Joe Onorato8a9b2202010-02-26 18:56:32 -08002660 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2662
2663 inTouchMode = mInTouchMode;
2664 }
2665
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002666 if (configChanged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002667 sendNewConfiguration();
2668 }
Romain Guy06882f82009-06-10 13:36:04 -07002669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002670 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07002671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
2673 | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
2674 }
2675
2676 public void finishDrawingWindow(Session session, IWindow client) {
2677 final long origId = Binder.clearCallingIdentity();
2678 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002679 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002680 if (win != null && win.finishDrawingLocked()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07002681 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2682 adjustWallpaperWindowsLocked();
2683 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 mLayoutNeeded = true;
2685 performLayoutAndPlaceSurfacesLocked();
2686 }
2687 }
2688 Binder.restoreCallingIdentity(origId);
2689 }
2690
2691 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002692 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693 + (lp != null ? lp.packageName : null)
2694 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
2695 if (lp != null && lp.windowAnimations != 0) {
2696 // If this is a system resource, don't try to load it from the
2697 // application resources. It is nice to avoid loading application
2698 // resources if we can.
2699 String packageName = lp.packageName != null ? lp.packageName : "android";
2700 int resId = lp.windowAnimations;
2701 if ((resId&0xFF000000) == 0x01000000) {
2702 packageName = "android";
2703 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002704 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 + packageName);
2706 return AttributeCache.instance().get(packageName, resId,
2707 com.android.internal.R.styleable.WindowAnimation);
2708 }
2709 return null;
2710 }
Romain Guy06882f82009-06-10 13:36:04 -07002711
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002712 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002713 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002714 + packageName + " resId=0x" + Integer.toHexString(resId));
2715 if (packageName != null) {
2716 if ((resId&0xFF000000) == 0x01000000) {
2717 packageName = "android";
2718 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002719 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002720 + packageName);
2721 return AttributeCache.instance().get(packageName, resId,
2722 com.android.internal.R.styleable.WindowAnimation);
2723 }
2724 return null;
2725 }
2726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 private void applyEnterAnimationLocked(WindowState win) {
2728 int transit = WindowManagerPolicy.TRANSIT_SHOW;
2729 if (win.mEnterAnimationPending) {
2730 win.mEnterAnimationPending = false;
2731 transit = WindowManagerPolicy.TRANSIT_ENTER;
2732 }
2733
2734 applyAnimationLocked(win, transit, true);
2735 }
2736
2737 private boolean applyAnimationLocked(WindowState win,
2738 int transit, boolean isEntrance) {
2739 if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
2740 // If we are trying to apply an animation, but already running
2741 // an animation of the same type, then just leave that one alone.
2742 return true;
2743 }
Romain Guy06882f82009-06-10 13:36:04 -07002744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 // Only apply an animation if the display isn't frozen. If it is
2746 // frozen, there is no reason to animate and it can cause strange
2747 // artifacts when we unfreeze the display if some different animation
2748 // is running.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002749 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002750 int anim = mPolicy.selectAnimationLw(win, transit);
2751 int attr = -1;
2752 Animation a = null;
2753 if (anim != 0) {
2754 a = AnimationUtils.loadAnimation(mContext, anim);
2755 } else {
2756 switch (transit) {
2757 case WindowManagerPolicy.TRANSIT_ENTER:
2758 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
2759 break;
2760 case WindowManagerPolicy.TRANSIT_EXIT:
2761 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
2762 break;
2763 case WindowManagerPolicy.TRANSIT_SHOW:
2764 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
2765 break;
2766 case WindowManagerPolicy.TRANSIT_HIDE:
2767 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
2768 break;
2769 }
2770 if (attr >= 0) {
2771 a = loadAnimation(win.mAttrs, attr);
2772 }
2773 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002774 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: win=" + win
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002775 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
2776 + " mAnimation=" + win.mAnimation
2777 + " isEntrance=" + isEntrance);
2778 if (a != null) {
2779 if (DEBUG_ANIM) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002780 RuntimeException e = null;
2781 if (!HIDE_STACK_CRAWLS) {
2782 e = new RuntimeException();
2783 e.fillInStackTrace();
2784 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002785 Slog.v(TAG, "Loaded animation " + a + " for " + win, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002786 }
2787 win.setAnimation(a);
2788 win.mAnimationIsEntrance = isEntrance;
2789 }
2790 } else {
2791 win.clearAnimation();
2792 }
2793
2794 return win.mAnimation != null;
2795 }
2796
2797 private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
2798 int anim = 0;
2799 Context context = mContext;
2800 if (animAttr >= 0) {
2801 AttributeCache.Entry ent = getCachedAnimations(lp);
2802 if (ent != null) {
2803 context = ent.context;
2804 anim = ent.array.getResourceId(animAttr, 0);
2805 }
2806 }
2807 if (anim != 0) {
2808 return AnimationUtils.loadAnimation(context, anim);
2809 }
2810 return null;
2811 }
Romain Guy06882f82009-06-10 13:36:04 -07002812
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002813 private Animation loadAnimation(String packageName, int resId) {
2814 int anim = 0;
2815 Context context = mContext;
2816 if (resId >= 0) {
2817 AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
2818 if (ent != null) {
2819 context = ent.context;
2820 anim = resId;
2821 }
2822 }
2823 if (anim != 0) {
2824 return AnimationUtils.loadAnimation(context, anim);
2825 }
2826 return null;
2827 }
2828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002829 private boolean applyAnimationLocked(AppWindowToken wtoken,
2830 WindowManager.LayoutParams lp, int transit, boolean enter) {
2831 // Only apply an animation if the display isn't frozen. If it is
2832 // frozen, there is no reason to animate and it can cause strange
2833 // artifacts when we unfreeze the display if some different animation
2834 // is running.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002835 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002836 Animation a;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07002837 if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002838 a = new FadeInOutAnimation(enter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002839 if (DEBUG_ANIM) Slog.v(TAG,
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002840 "applying FadeInOutAnimation for a window in compatibility mode");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002841 } else if (mNextAppTransitionPackage != null) {
2842 a = loadAnimation(mNextAppTransitionPackage, enter ?
2843 mNextAppTransitionEnter : mNextAppTransitionExit);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002844 } else {
2845 int animAttr = 0;
2846 switch (transit) {
2847 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
2848 animAttr = enter
2849 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
2850 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
2851 break;
2852 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
2853 animAttr = enter
2854 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
2855 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
2856 break;
2857 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
2858 animAttr = enter
2859 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
2860 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
2861 break;
2862 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
2863 animAttr = enter
2864 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
2865 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
2866 break;
2867 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
2868 animAttr = enter
2869 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
2870 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
2871 break;
2872 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
2873 animAttr = enter
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07002874 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002875 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
2876 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002877 case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002878 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002879 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation
2880 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002881 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002882 case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002883 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002884 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation
2885 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
2886 break;
2887 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN:
2888 animAttr = enter
2889 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation
2890 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
2891 break;
2892 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE:
2893 animAttr = enter
2894 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation
2895 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002896 break;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002897 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002898 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002899 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002900 + " anim=" + a
2901 + " animAttr=0x" + Integer.toHexString(animAttr)
2902 + " transit=" + transit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002903 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002904 if (a != null) {
2905 if (DEBUG_ANIM) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002906 RuntimeException e = null;
2907 if (!HIDE_STACK_CRAWLS) {
2908 e = new RuntimeException();
2909 e.fillInStackTrace();
2910 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002911 Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 }
2913 wtoken.setAnimation(a);
2914 }
2915 } else {
2916 wtoken.clearAnimation();
2917 }
2918
2919 return wtoken.animation != null;
2920 }
2921
2922 // -------------------------------------------------------------
2923 // Application Window Tokens
2924 // -------------------------------------------------------------
2925
2926 public void validateAppTokens(List tokens) {
2927 int v = tokens.size()-1;
2928 int m = mAppTokens.size()-1;
2929 while (v >= 0 && m >= 0) {
2930 AppWindowToken wtoken = mAppTokens.get(m);
2931 if (wtoken.removed) {
2932 m--;
2933 continue;
2934 }
2935 if (tokens.get(v) != wtoken.token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002936 Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937 + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
2938 }
2939 v--;
2940 m--;
2941 }
2942 while (v >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002943 Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002944 v--;
2945 }
2946 while (m >= 0) {
2947 AppWindowToken wtoken = mAppTokens.get(m);
2948 if (!wtoken.removed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002949 Slog.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 }
2951 m--;
2952 }
2953 }
2954
2955 boolean checkCallingPermission(String permission, String func) {
2956 // Quick check: if the calling permission is me, it's all okay.
2957 if (Binder.getCallingPid() == Process.myPid()) {
2958 return true;
2959 }
Romain Guy06882f82009-06-10 13:36:04 -07002960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002961 if (mContext.checkCallingPermission(permission)
2962 == PackageManager.PERMISSION_GRANTED) {
2963 return true;
2964 }
2965 String msg = "Permission Denial: " + func + " from pid="
2966 + Binder.getCallingPid()
2967 + ", uid=" + Binder.getCallingUid()
2968 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002969 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002970 return false;
2971 }
Romain Guy06882f82009-06-10 13:36:04 -07002972
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 AppWindowToken findAppWindowToken(IBinder token) {
2974 WindowToken wtoken = mTokenMap.get(token);
2975 if (wtoken == null) {
2976 return null;
2977 }
2978 return wtoken.appWindowToken;
2979 }
Romain Guy06882f82009-06-10 13:36:04 -07002980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002981 public void addWindowToken(IBinder token, int type) {
2982 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2983 "addWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002984 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002985 }
Romain Guy06882f82009-06-10 13:36:04 -07002986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 synchronized(mWindowMap) {
2988 WindowToken wtoken = mTokenMap.get(token);
2989 if (wtoken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002990 Slog.w(TAG, "Attempted to add existing input method token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 return;
2992 }
2993 wtoken = new WindowToken(token, type, true);
2994 mTokenMap.put(token, wtoken);
2995 mTokenList.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002996 if (type == TYPE_WALLPAPER) {
2997 mWallpaperTokens.add(wtoken);
2998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002999 }
3000 }
Romain Guy06882f82009-06-10 13:36:04 -07003001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003002 public void removeWindowToken(IBinder token) {
3003 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3004 "removeWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003005 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003006 }
3007
3008 final long origId = Binder.clearCallingIdentity();
3009 synchronized(mWindowMap) {
3010 WindowToken wtoken = mTokenMap.remove(token);
3011 mTokenList.remove(wtoken);
3012 if (wtoken != null) {
3013 boolean delayed = false;
3014 if (!wtoken.hidden) {
3015 wtoken.hidden = true;
Romain Guy06882f82009-06-10 13:36:04 -07003016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003017 final int N = wtoken.windows.size();
3018 boolean changed = false;
Romain Guy06882f82009-06-10 13:36:04 -07003019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003020 for (int i=0; i<N; i++) {
3021 WindowState win = wtoken.windows.get(i);
3022
3023 if (win.isAnimating()) {
3024 delayed = true;
3025 }
Romain Guy06882f82009-06-10 13:36:04 -07003026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 if (win.isVisibleNow()) {
3028 applyAnimationLocked(win,
3029 WindowManagerPolicy.TRANSIT_EXIT, false);
Jeff Brown349703e2010-06-22 01:27:15 -07003030 if (ENABLE_NATIVE_INPUT_DISPATCH) {
3031 mInputMonitor.windowIsBeingRemovedLw(win);
3032 } else {
3033 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
3034 KeyWaiter.RETURN_NOTHING);
3035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003036 changed = true;
3037 }
3038 }
3039
3040 if (changed) {
3041 mLayoutNeeded = true;
3042 performLayoutAndPlaceSurfacesLocked();
3043 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3044 }
Romain Guy06882f82009-06-10 13:36:04 -07003045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003046 if (delayed) {
3047 mExitingTokens.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07003048 } else if (wtoken.windowType == TYPE_WALLPAPER) {
3049 mWallpaperTokens.remove(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003050 }
3051 }
Romain Guy06882f82009-06-10 13:36:04 -07003052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003054 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 }
3056 }
3057 Binder.restoreCallingIdentity(origId);
3058 }
3059
3060 public void addAppToken(int addPos, IApplicationToken token,
3061 int groupId, int requestedOrientation, boolean fullscreen) {
3062 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3063 "addAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003064 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 }
Jeff Brown349703e2010-06-22 01:27:15 -07003066
3067 // Get the dispatching timeout here while we are not holding any locks so that it
3068 // can be cached by the AppWindowToken. The timeout value is used later by the
3069 // input dispatcher in code that does hold locks. If we did not cache the value
3070 // here we would run the chance of introducing a deadlock between the window manager
3071 // (which holds locks while updating the input dispatcher state) and the activity manager
3072 // (which holds locks while querying the application token).
3073 long inputDispatchingTimeoutNanos;
3074 try {
3075 inputDispatchingTimeoutNanos = token.getKeyDispatchingTimeout() * 1000000L;
3076 } catch (RemoteException ex) {
3077 Slog.w(TAG, "Could not get dispatching timeout.", ex);
3078 inputDispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
3079 }
Romain Guy06882f82009-06-10 13:36:04 -07003080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003081 synchronized(mWindowMap) {
3082 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3083 if (wtoken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003084 Slog.w(TAG, "Attempted to add existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003085 return;
3086 }
3087 wtoken = new AppWindowToken(token);
Jeff Brown349703e2010-06-22 01:27:15 -07003088 wtoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 wtoken.groupId = groupId;
3090 wtoken.appFullscreen = fullscreen;
3091 wtoken.requestedOrientation = requestedOrientation;
3092 mAppTokens.add(addPos, wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003093 if (localLOGV) Slog.v(TAG, "Adding new app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003094 mTokenMap.put(token.asBinder(), wtoken);
3095 mTokenList.add(wtoken);
Romain Guy06882f82009-06-10 13:36:04 -07003096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003097 // Application tokens start out hidden.
3098 wtoken.hidden = true;
3099 wtoken.hiddenRequested = true;
Romain Guy06882f82009-06-10 13:36:04 -07003100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 //dump();
3102 }
3103 }
Romain Guy06882f82009-06-10 13:36:04 -07003104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003105 public void setAppGroupId(IBinder token, int groupId) {
3106 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3107 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003108 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003109 }
3110
3111 synchronized(mWindowMap) {
3112 AppWindowToken wtoken = findAppWindowToken(token);
3113 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003114 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 return;
3116 }
3117 wtoken.groupId = groupId;
3118 }
3119 }
Romain Guy06882f82009-06-10 13:36:04 -07003120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003121 public int getOrientationFromWindowsLocked() {
3122 int pos = mWindows.size() - 1;
3123 while (pos >= 0) {
3124 WindowState wtoken = (WindowState) mWindows.get(pos);
3125 pos--;
3126 if (wtoken.mAppToken != null) {
3127 // We hit an application window. so the orientation will be determined by the
3128 // app window. No point in continuing further.
3129 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3130 }
Christopher Tateb696aee2010-04-02 19:08:30 -07003131 if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003132 continue;
3133 }
3134 int req = wtoken.mAttrs.screenOrientation;
3135 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3136 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3137 continue;
3138 } else {
3139 return req;
3140 }
3141 }
3142 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3143 }
Romain Guy06882f82009-06-10 13:36:04 -07003144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 public int getOrientationFromAppTokensLocked() {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003146 int pos = mAppTokens.size() - 1;
3147 int curGroup = 0;
3148 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3149 boolean findingBehind = false;
3150 boolean haveGroup = false;
3151 boolean lastFullscreen = false;
3152 while (pos >= 0) {
3153 AppWindowToken wtoken = mAppTokens.get(pos);
3154 pos--;
3155 // if we're about to tear down this window and not seek for
3156 // the behind activity, don't use it for orientation
3157 if (!findingBehind
3158 && (!wtoken.hidden && wtoken.hiddenRequested)) {
3159 continue;
3160 }
3161
3162 if (!haveGroup) {
3163 // We ignore any hidden applications on the top.
3164 if (wtoken.hiddenRequested || wtoken.willBeHidden) {
The Android Open Source Project10592532009-03-18 17:39:46 -07003165 continue;
3166 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003167 haveGroup = true;
3168 curGroup = wtoken.groupId;
3169 lastOrientation = wtoken.requestedOrientation;
3170 } else if (curGroup != wtoken.groupId) {
3171 // If we have hit a new application group, and the bottom
3172 // of the previous group didn't explicitly say to use
3173 // the orientation behind it, and the last app was
3174 // full screen, then we'll stick with the
3175 // user's orientation.
3176 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3177 && lastFullscreen) {
3178 return lastOrientation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003180 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003181 int or = wtoken.requestedOrientation;
3182 // If this application is fullscreen, and didn't explicitly say
3183 // to use the orientation behind it, then just take whatever
3184 // orientation it has and ignores whatever is under it.
3185 lastFullscreen = wtoken.appFullscreen;
3186 if (lastFullscreen
3187 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3188 return or;
3189 }
3190 // If this application has requested an explicit orientation,
3191 // then use it.
3192 if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
3193 or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
3194 or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
3195 or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
3196 or == ActivityInfo.SCREEN_ORIENTATION_USER) {
3197 return or;
3198 }
3199 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3200 }
3201 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003202 }
Romain Guy06882f82009-06-10 13:36:04 -07003203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003204 public Configuration updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003205 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003206 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3207 "updateOrientationFromAppTokens()")) {
3208 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3209 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003210
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003211 Configuration config = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003212 long ident = Binder.clearCallingIdentity();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003213
3214 synchronized(mWindowMap) {
3215 if (updateOrientationFromAppTokensLocked()) {
3216 if (freezeThisOneIfNeeded != null) {
3217 AppWindowToken wtoken = findAppWindowToken(
3218 freezeThisOneIfNeeded);
3219 if (wtoken != null) {
3220 startAppFreezingScreenLocked(wtoken,
3221 ActivityInfo.CONFIG_ORIENTATION);
3222 }
3223 }
3224 config = computeNewConfigurationLocked();
3225
3226 } else if (currentConfig != null) {
3227 // No obvious action we need to take, but if our current
3228 // state mismatches the activity maanager's, update it
3229 mTempConfiguration.setToDefaults();
3230 if (computeNewConfigurationLocked(mTempConfiguration)) {
3231 if (currentConfig.diff(mTempConfiguration) != 0) {
3232 mWaitingForConfig = true;
3233 mLayoutNeeded = true;
3234 startFreezingDisplayLocked();
3235 config = new Configuration(mTempConfiguration);
3236 }
3237 }
3238 }
3239 }
3240
Dianne Hackborncfaef692009-06-15 14:24:44 -07003241 Binder.restoreCallingIdentity(ident);
3242 return config;
3243 }
3244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003245 /*
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003246 * Determine the new desired orientation of the display, returning
3247 * a non-null new Configuration if it has changed from the current
3248 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
3249 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3250 * SCREEN. This will typically be done for you if you call
3251 * sendNewConfiguration().
3252 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003253 * The orientation is computed from non-application windows first. If none of
3254 * the non-application windows specify orientation, the orientation is computed from
Romain Guy06882f82009-06-10 13:36:04 -07003255 * application tokens.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3257 * android.os.IBinder)
3258 */
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003259 boolean updateOrientationFromAppTokensLocked() {
Christopher Tateb696aee2010-04-02 19:08:30 -07003260 if (mDisplayFrozen) {
3261 // If the display is frozen, some activities may be in the middle
3262 // of restarting, and thus have removed their old window. If the
3263 // window has the flag to hide the lock screen, then the lock screen
3264 // can re-appear and inflict its own orientation on us. Keep the
3265 // orientation stable until this all settles down.
3266 return false;
3267 }
3268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 boolean changed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 long ident = Binder.clearCallingIdentity();
3271 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003272 int req = computeForcedAppOrientationLocked();
Romain Guy06882f82009-06-10 13:36:04 -07003273
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003274 if (req != mForcedAppOrientation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003275 mForcedAppOrientation = req;
3276 //send a message to Policy indicating orientation change to take
3277 //action like disabling/enabling sensors etc.,
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003278 mPolicy.setCurrentOrientationLw(req);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003279 if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
3280 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)) {
3281 changed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282 }
3283 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003284
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003285 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003286 } finally {
3287 Binder.restoreCallingIdentity(ident);
3288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 }
Romain Guy06882f82009-06-10 13:36:04 -07003290
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003291 int computeForcedAppOrientationLocked() {
3292 int req = getOrientationFromWindowsLocked();
3293 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3294 req = getOrientationFromAppTokensLocked();
3295 }
3296 return req;
3297 }
Romain Guy06882f82009-06-10 13:36:04 -07003298
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003299 public void setNewConfiguration(Configuration config) {
3300 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3301 "setNewConfiguration()")) {
3302 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3303 }
3304
3305 synchronized(mWindowMap) {
3306 mCurConfiguration = new Configuration(config);
3307 mWaitingForConfig = false;
3308 performLayoutAndPlaceSurfacesLocked();
3309 }
3310 }
3311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3313 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3314 "setAppOrientation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003315 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003316 }
Romain Guy06882f82009-06-10 13:36:04 -07003317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003318 synchronized(mWindowMap) {
3319 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3320 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003321 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003322 return;
3323 }
Romain Guy06882f82009-06-10 13:36:04 -07003324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003325 wtoken.requestedOrientation = requestedOrientation;
3326 }
3327 }
Romain Guy06882f82009-06-10 13:36:04 -07003328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003329 public int getAppOrientation(IApplicationToken token) {
3330 synchronized(mWindowMap) {
3331 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3332 if (wtoken == null) {
3333 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3334 }
Romain Guy06882f82009-06-10 13:36:04 -07003335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003336 return wtoken.requestedOrientation;
3337 }
3338 }
Romain Guy06882f82009-06-10 13:36:04 -07003339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003340 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3341 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3342 "setFocusedApp()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003343 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003344 }
3345
3346 synchronized(mWindowMap) {
3347 boolean changed = false;
3348 if (token == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003349 if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003350 changed = mFocusedApp != null;
3351 mFocusedApp = null;
Jeff Brown349703e2010-06-22 01:27:15 -07003352 if (ENABLE_NATIVE_INPUT_DISPATCH) {
3353 if (changed) {
3354 mInputMonitor.setFocusedAppLw(null);
3355 }
3356 } else {
3357 mKeyWaiter.tickle();
3358 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 } else {
3360 AppWindowToken newFocus = findAppWindowToken(token);
3361 if (newFocus == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003362 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 return;
3364 }
3365 changed = mFocusedApp != newFocus;
3366 mFocusedApp = newFocus;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003367 if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp);
Jeff Brown349703e2010-06-22 01:27:15 -07003368 if (ENABLE_NATIVE_INPUT_DISPATCH) {
3369 if (changed) {
3370 mInputMonitor.setFocusedAppLw(newFocus);
3371 }
3372 } else {
3373 mKeyWaiter.tickle();
3374 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003375 }
3376
3377 if (moveFocusNow && changed) {
3378 final long origId = Binder.clearCallingIdentity();
3379 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3380 Binder.restoreCallingIdentity(origId);
3381 }
3382 }
3383 }
3384
3385 public void prepareAppTransition(int transit) {
3386 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3387 "prepareAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003388 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 }
Romain Guy06882f82009-06-10 13:36:04 -07003390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003392 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 TAG, "Prepare app transition: transit=" + transit
3394 + " mNextAppTransition=" + mNextAppTransition);
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003395 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003396 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
3397 || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003398 mNextAppTransition = transit;
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07003399 } else if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
3400 && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) {
3401 // Opening a new task always supersedes a close for the anim.
3402 mNextAppTransition = transit;
3403 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
3404 && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) {
3405 // Opening a new activity always supersedes a close for the anim.
3406 mNextAppTransition = transit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003407 }
3408 mAppTransitionReady = false;
3409 mAppTransitionTimeout = false;
3410 mStartingIconInTransition = false;
3411 mSkipAppTransitionAnimation = false;
3412 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3413 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT),
3414 5000);
3415 }
3416 }
3417 }
3418
3419 public int getPendingAppTransition() {
3420 return mNextAppTransition;
3421 }
Romain Guy06882f82009-06-10 13:36:04 -07003422
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003423 public void overridePendingAppTransition(String packageName,
3424 int enterAnim, int exitAnim) {
Dianne Hackborn8b571a82009-09-25 16:09:43 -07003425 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003426 mNextAppTransitionPackage = packageName;
3427 mNextAppTransitionEnter = enterAnim;
3428 mNextAppTransitionExit = exitAnim;
3429 }
3430 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 public void executeAppTransition() {
3433 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3434 "executeAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003435 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003436 }
Romain Guy06882f82009-06-10 13:36:04 -07003437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003438 synchronized(mWindowMap) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003439 if (DEBUG_APP_TRANSITIONS) {
3440 RuntimeException e = new RuntimeException("here");
3441 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -08003442 Slog.w(TAG, "Execute app transition: mNextAppTransition="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003443 + mNextAppTransition, e);
3444 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003445 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003446 mAppTransitionReady = true;
3447 final long origId = Binder.clearCallingIdentity();
3448 performLayoutAndPlaceSurfacesLocked();
3449 Binder.restoreCallingIdentity(origId);
3450 }
3451 }
3452 }
3453
3454 public void setAppStartingWindow(IBinder token, String pkg,
3455 int theme, CharSequence nonLocalizedLabel, int labelRes, int icon,
3456 IBinder transferFrom, boolean createIfNeeded) {
3457 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3458 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003459 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003460 }
3461
3462 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003463 if (DEBUG_STARTING_WINDOW) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
3465 + " transferFrom=" + transferFrom);
Romain Guy06882f82009-06-10 13:36:04 -07003466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003467 AppWindowToken wtoken = findAppWindowToken(token);
3468 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003469 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 return;
3471 }
3472
3473 // If the display is frozen, we won't do anything until the
3474 // actual window is displayed so there is no reason to put in
3475 // the starting window.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08003476 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003477 return;
3478 }
Romain Guy06882f82009-06-10 13:36:04 -07003479
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003480 if (wtoken.startingData != null) {
3481 return;
3482 }
Romain Guy06882f82009-06-10 13:36:04 -07003483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003484 if (transferFrom != null) {
3485 AppWindowToken ttoken = findAppWindowToken(transferFrom);
3486 if (ttoken != null) {
3487 WindowState startingWindow = ttoken.startingWindow;
3488 if (startingWindow != null) {
3489 if (mStartingIconInTransition) {
3490 // In this case, the starting icon has already
3491 // been displayed, so start letting windows get
3492 // shown immediately without any more transitions.
3493 mSkipAppTransitionAnimation = true;
3494 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003495 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003496 "Moving existing starting from " + ttoken
3497 + " to " + wtoken);
3498 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07003499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003500 // Transfer the starting window over to the new
3501 // token.
3502 wtoken.startingData = ttoken.startingData;
3503 wtoken.startingView = ttoken.startingView;
3504 wtoken.startingWindow = startingWindow;
3505 ttoken.startingData = null;
3506 ttoken.startingView = null;
3507 ttoken.startingWindow = null;
3508 ttoken.startingMoved = true;
3509 startingWindow.mToken = wtoken;
Dianne Hackbornef49c572009-03-24 19:27:32 -07003510 startingWindow.mRootToken = wtoken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003511 startingWindow.mAppToken = wtoken;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003512 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003513 "Removing starting window: " + startingWindow);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003514 mWindows.remove(startingWindow);
3515 ttoken.windows.remove(startingWindow);
3516 ttoken.allAppWindows.remove(startingWindow);
3517 addWindowToListInOrderLocked(startingWindow, true);
Romain Guy06882f82009-06-10 13:36:04 -07003518
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003519 // Propagate other interesting state between the
3520 // tokens. If the old token is displayed, we should
3521 // immediately force the new one to be displayed. If
3522 // it is animating, we need to move that animation to
3523 // the new one.
3524 if (ttoken.allDrawn) {
3525 wtoken.allDrawn = true;
3526 }
3527 if (ttoken.firstWindowDrawn) {
3528 wtoken.firstWindowDrawn = true;
3529 }
3530 if (!ttoken.hidden) {
3531 wtoken.hidden = false;
3532 wtoken.hiddenRequested = false;
3533 wtoken.willBeHidden = false;
3534 }
3535 if (wtoken.clientHidden != ttoken.clientHidden) {
3536 wtoken.clientHidden = ttoken.clientHidden;
3537 wtoken.sendAppVisibilityToClients();
3538 }
3539 if (ttoken.animation != null) {
3540 wtoken.animation = ttoken.animation;
3541 wtoken.animating = ttoken.animating;
3542 wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
3543 ttoken.animation = null;
3544 ttoken.animLayerAdjustment = 0;
3545 wtoken.updateLayers();
3546 ttoken.updateLayers();
3547 }
Romain Guy06882f82009-06-10 13:36:04 -07003548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003549 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003550 mLayoutNeeded = true;
3551 performLayoutAndPlaceSurfacesLocked();
3552 Binder.restoreCallingIdentity(origId);
3553 return;
3554 } else if (ttoken.startingData != null) {
3555 // The previous app was getting ready to show a
3556 // starting window, but hasn't yet done so. Steal it!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003557 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003558 "Moving pending starting from " + ttoken
3559 + " to " + wtoken);
3560 wtoken.startingData = ttoken.startingData;
3561 ttoken.startingData = null;
3562 ttoken.startingMoved = true;
3563 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3564 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3565 // want to process the message ASAP, before any other queued
3566 // messages.
3567 mH.sendMessageAtFrontOfQueue(m);
3568 return;
3569 }
3570 }
3571 }
3572
3573 // There is no existing starting window, and the caller doesn't
3574 // want us to create one, so that's it!
3575 if (!createIfNeeded) {
3576 return;
3577 }
Romain Guy06882f82009-06-10 13:36:04 -07003578
Dianne Hackborn284ac932009-08-28 10:34:25 -07003579 // If this is a translucent or wallpaper window, then don't
3580 // show a starting window -- the current effect (a full-screen
3581 // opaque starting window that fades away to the real contents
3582 // when it is ready) does not work for this.
3583 if (theme != 0) {
3584 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
3585 com.android.internal.R.styleable.Window);
3586 if (ent.array.getBoolean(
3587 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
3588 return;
3589 }
3590 if (ent.array.getBoolean(
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07003591 com.android.internal.R.styleable.Window_windowIsFloating, false)) {
3592 return;
3593 }
3594 if (ent.array.getBoolean(
Dianne Hackborn284ac932009-08-28 10:34:25 -07003595 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
3596 return;
3597 }
3598 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003600 mStartingIconInTransition = true;
3601 wtoken.startingData = new StartingData(
3602 pkg, theme, nonLocalizedLabel,
3603 labelRes, icon);
3604 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3605 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3606 // want to process the message ASAP, before any other queued
3607 // messages.
3608 mH.sendMessageAtFrontOfQueue(m);
3609 }
3610 }
3611
3612 public void setAppWillBeHidden(IBinder token) {
3613 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3614 "setAppWillBeHidden()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003615 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003616 }
3617
3618 AppWindowToken wtoken;
3619
3620 synchronized(mWindowMap) {
3621 wtoken = findAppWindowToken(token);
3622 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003623 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003624 return;
3625 }
3626 wtoken.willBeHidden = true;
3627 }
3628 }
Romain Guy06882f82009-06-10 13:36:04 -07003629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
3631 boolean visible, int transit, boolean performLayout) {
3632 boolean delayed = false;
3633
3634 if (wtoken.clientHidden == visible) {
3635 wtoken.clientHidden = !visible;
3636 wtoken.sendAppVisibilityToClients();
3637 }
Romain Guy06882f82009-06-10 13:36:04 -07003638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003639 wtoken.willBeHidden = false;
3640 if (wtoken.hidden == visible) {
3641 final int N = wtoken.allAppWindows.size();
3642 boolean changed = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003643 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003644 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
3645 + " performLayout=" + performLayout);
Romain Guy06882f82009-06-10 13:36:04 -07003646
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003647 boolean runningAppAnimation = false;
Romain Guy06882f82009-06-10 13:36:04 -07003648
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003649 if (transit != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 if (wtoken.animation == sDummyAnimation) {
3651 wtoken.animation = null;
3652 }
3653 applyAnimationLocked(wtoken, lp, transit, visible);
3654 changed = true;
3655 if (wtoken.animation != null) {
3656 delayed = runningAppAnimation = true;
3657 }
3658 }
Romain Guy06882f82009-06-10 13:36:04 -07003659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003660 for (int i=0; i<N; i++) {
3661 WindowState win = wtoken.allAppWindows.get(i);
3662 if (win == wtoken.startingWindow) {
3663 continue;
3664 }
3665
3666 if (win.isAnimating()) {
3667 delayed = true;
3668 }
Romain Guy06882f82009-06-10 13:36:04 -07003669
Joe Onorato8a9b2202010-02-26 18:56:32 -08003670 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003671 //win.dump(" ");
3672 if (visible) {
3673 if (!win.isVisibleNow()) {
3674 if (!runningAppAnimation) {
3675 applyAnimationLocked(win,
3676 WindowManagerPolicy.TRANSIT_ENTER, true);
3677 }
3678 changed = true;
3679 }
3680 } else if (win.isVisibleNow()) {
3681 if (!runningAppAnimation) {
3682 applyAnimationLocked(win,
3683 WindowManagerPolicy.TRANSIT_EXIT, false);
3684 }
Jeff Brown349703e2010-06-22 01:27:15 -07003685 if (ENABLE_NATIVE_INPUT_DISPATCH) {
3686 mInputMonitor.windowIsBecomingInvisibleLw(win);
3687 } else {
3688 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
3689 KeyWaiter.RETURN_NOTHING);
3690 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 changed = true;
3692 }
3693 }
3694
3695 wtoken.hidden = wtoken.hiddenRequested = !visible;
3696 if (!visible) {
3697 unsetAppFreezingScreenLocked(wtoken, true, true);
3698 } else {
3699 // If we are being set visible, and the starting window is
3700 // not yet displayed, then make sure it doesn't get displayed.
3701 WindowState swin = wtoken.startingWindow;
3702 if (swin != null && (swin.mDrawPending
3703 || swin.mCommitDrawPending)) {
3704 swin.mPolicyVisibility = false;
3705 swin.mPolicyVisibilityAfterAnim = false;
3706 }
3707 }
Romain Guy06882f82009-06-10 13:36:04 -07003708
Joe Onorato8a9b2202010-02-26 18:56:32 -08003709 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003710 + ": hidden=" + wtoken.hidden + " hiddenRequested="
3711 + wtoken.hiddenRequested);
Romain Guy06882f82009-06-10 13:36:04 -07003712
Dianne Hackborn9b52a212009-12-11 14:51:35 -08003713 if (changed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003714 mLayoutNeeded = true;
Dianne Hackborn9b52a212009-12-11 14:51:35 -08003715 if (performLayout) {
3716 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
3717 performLayoutAndPlaceSurfacesLocked();
3718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003719 }
3720 }
3721
3722 if (wtoken.animation != null) {
3723 delayed = true;
3724 }
Romain Guy06882f82009-06-10 13:36:04 -07003725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003726 return delayed;
3727 }
3728
3729 public void setAppVisibility(IBinder token, boolean visible) {
3730 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3731 "setAppVisibility()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003732 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003733 }
3734
3735 AppWindowToken wtoken;
3736
3737 synchronized(mWindowMap) {
3738 wtoken = findAppWindowToken(token);
3739 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003740 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003741 return;
3742 }
3743
3744 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08003745 RuntimeException e = null;
3746 if (!HIDE_STACK_CRAWLS) {
3747 e = new RuntimeException();
3748 e.fillInStackTrace();
3749 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003750 Slog.v(TAG, "setAppVisibility(" + token + ", " + visible
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 + "): mNextAppTransition=" + mNextAppTransition
3752 + " hidden=" + wtoken.hidden
3753 + " hiddenRequested=" + wtoken.hiddenRequested, e);
3754 }
Romain Guy06882f82009-06-10 13:36:04 -07003755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003756 // If we are preparing an app transition, then delay changing
3757 // the visibility of this token until we execute that transition.
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003758 if (!mDisplayFrozen && mPolicy.isScreenOn()
3759 && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 // Already in requested state, don't do anything more.
3761 if (wtoken.hiddenRequested != visible) {
3762 return;
3763 }
3764 wtoken.hiddenRequested = !visible;
Romain Guy06882f82009-06-10 13:36:04 -07003765
Joe Onorato8a9b2202010-02-26 18:56:32 -08003766 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003767 TAG, "Setting dummy animation on: " + wtoken);
3768 wtoken.setDummyAnimation();
3769 mOpeningApps.remove(wtoken);
3770 mClosingApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003771 wtoken.waitingToShow = wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 wtoken.inPendingTransaction = true;
3773 if (visible) {
3774 mOpeningApps.add(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003775 wtoken.startingDisplayed = false;
3776 wtoken.startingMoved = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003777
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003778 // If the token is currently hidden (should be the
3779 // common case), then we need to set up to wait for
3780 // its windows to be ready.
3781 if (wtoken.hidden) {
3782 wtoken.allDrawn = false;
3783 wtoken.waitingToShow = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003784
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003785 if (wtoken.clientHidden) {
3786 // In the case where we are making an app visible
3787 // but holding off for a transition, we still need
3788 // to tell the client to make its windows visible so
3789 // they get drawn. Otherwise, we will wait on
3790 // performing the transition until all windows have
3791 // been drawn, they never will be, and we are sad.
3792 wtoken.clientHidden = false;
3793 wtoken.sendAppVisibilityToClients();
3794 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003795 }
3796 } else {
3797 mClosingApps.add(wtoken);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003798
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003799 // If the token is currently visible (should be the
3800 // common case), then set up to wait for it to be hidden.
3801 if (!wtoken.hidden) {
3802 wtoken.waitingToHide = true;
3803 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 }
3805 return;
3806 }
Romain Guy06882f82009-06-10 13:36:04 -07003807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003809 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 wtoken.updateReportedVisibilityLocked();
3811 Binder.restoreCallingIdentity(origId);
3812 }
3813 }
3814
3815 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
3816 boolean unfreezeSurfaceNow, boolean force) {
3817 if (wtoken.freezingScreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003818 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003819 + " force=" + force);
3820 final int N = wtoken.allAppWindows.size();
3821 boolean unfrozeWindows = false;
3822 for (int i=0; i<N; i++) {
3823 WindowState w = wtoken.allAppWindows.get(i);
3824 if (w.mAppFreezing) {
3825 w.mAppFreezing = false;
3826 if (w.mSurface != null && !w.mOrientationChanging) {
3827 w.mOrientationChanging = true;
3828 }
3829 unfrozeWindows = true;
3830 }
3831 }
3832 if (force || unfrozeWindows) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003833 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003834 wtoken.freezingScreen = false;
3835 mAppsFreezingScreen--;
3836 }
3837 if (unfreezeSurfaceNow) {
3838 if (unfrozeWindows) {
3839 mLayoutNeeded = true;
3840 performLayoutAndPlaceSurfacesLocked();
3841 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003842 stopFreezingDisplayLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003843 }
3844 }
3845 }
Romain Guy06882f82009-06-10 13:36:04 -07003846
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003847 public void startAppFreezingScreenLocked(AppWindowToken wtoken,
3848 int configChanges) {
3849 if (DEBUG_ORIENTATION) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08003850 RuntimeException e = null;
3851 if (!HIDE_STACK_CRAWLS) {
3852 e = new RuntimeException();
3853 e.fillInStackTrace();
3854 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003855 Slog.i(TAG, "Set freezing of " + wtoken.appToken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 + ": hidden=" + wtoken.hidden + " freezing="
3857 + wtoken.freezingScreen, e);
3858 }
3859 if (!wtoken.hiddenRequested) {
3860 if (!wtoken.freezingScreen) {
3861 wtoken.freezingScreen = true;
3862 mAppsFreezingScreen++;
3863 if (mAppsFreezingScreen == 1) {
3864 startFreezingDisplayLocked();
3865 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
3866 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
3867 5000);
3868 }
3869 }
3870 final int N = wtoken.allAppWindows.size();
3871 for (int i=0; i<N; i++) {
3872 WindowState w = wtoken.allAppWindows.get(i);
3873 w.mAppFreezing = true;
3874 }
3875 }
3876 }
Romain Guy06882f82009-06-10 13:36:04 -07003877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003878 public void startAppFreezingScreen(IBinder token, int configChanges) {
3879 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3880 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003881 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 }
3883
3884 synchronized(mWindowMap) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003885 if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOn()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003886 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003887 return;
3888 }
Romain Guy06882f82009-06-10 13:36:04 -07003889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 AppWindowToken wtoken = findAppWindowToken(token);
3891 if (wtoken == null || wtoken.appToken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003892 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 return;
3894 }
3895 final long origId = Binder.clearCallingIdentity();
3896 startAppFreezingScreenLocked(wtoken, configChanges);
3897 Binder.restoreCallingIdentity(origId);
3898 }
3899 }
Romain Guy06882f82009-06-10 13:36:04 -07003900
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003901 public void stopAppFreezingScreen(IBinder token, boolean force) {
3902 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3903 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003904 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003905 }
3906
3907 synchronized(mWindowMap) {
3908 AppWindowToken wtoken = findAppWindowToken(token);
3909 if (wtoken == null || wtoken.appToken == null) {
3910 return;
3911 }
3912 final long origId = Binder.clearCallingIdentity();
Joe Onorato8a9b2202010-02-26 18:56:32 -08003913 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003914 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
3915 unsetAppFreezingScreenLocked(wtoken, true, force);
3916 Binder.restoreCallingIdentity(origId);
3917 }
3918 }
Romain Guy06882f82009-06-10 13:36:04 -07003919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003920 public void removeAppToken(IBinder token) {
3921 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3922 "removeAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003923 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 }
3925
3926 AppWindowToken wtoken = null;
3927 AppWindowToken startingToken = null;
3928 boolean delayed = false;
3929
3930 final long origId = Binder.clearCallingIdentity();
3931 synchronized(mWindowMap) {
3932 WindowToken basewtoken = mTokenMap.remove(token);
3933 mTokenList.remove(basewtoken);
3934 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003935 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003936 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003937 wtoken.inPendingTransaction = false;
3938 mOpeningApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003939 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 if (mClosingApps.contains(wtoken)) {
3941 delayed = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003942 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003943 mClosingApps.add(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003944 wtoken.waitingToHide = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003945 delayed = true;
3946 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003947 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003948 TAG, "Removing app " + wtoken + " delayed=" + delayed
3949 + " animation=" + wtoken.animation
3950 + " animating=" + wtoken.animating);
3951 if (delayed) {
3952 // set the token aside because it has an active animation to be finished
3953 mExitingAppTokens.add(wtoken);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003954 } else {
3955 // Make sure there is no animation running on this token,
3956 // so any windows associated with it will be removed as
3957 // soon as their animations are complete
3958 wtoken.animation = null;
3959 wtoken.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 }
3961 mAppTokens.remove(wtoken);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003962 if (mLastEnterAnimToken == wtoken) {
3963 mLastEnterAnimToken = null;
3964 mLastEnterAnimParams = null;
3965 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003966 wtoken.removed = true;
3967 if (wtoken.startingData != null) {
3968 startingToken = wtoken;
3969 }
3970 unsetAppFreezingScreenLocked(wtoken, true, true);
3971 if (mFocusedApp == wtoken) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003972 if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003973 mFocusedApp = null;
3974 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
Jeff Brown349703e2010-06-22 01:27:15 -07003975 if (ENABLE_NATIVE_INPUT_DISPATCH) {
3976 mInputMonitor.setFocusedAppLw(null);
3977 } else {
3978 mKeyWaiter.tickle();
3979 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003980 }
3981 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003982 Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 }
Romain Guy06882f82009-06-10 13:36:04 -07003984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003985 if (!delayed && wtoken != null) {
3986 wtoken.updateReportedVisibilityLocked();
3987 }
3988 }
3989 Binder.restoreCallingIdentity(origId);
3990
3991 if (startingToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003992 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003993 + startingToken + ": app token removed");
3994 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
3995 mH.sendMessage(m);
3996 }
3997 }
3998
3999 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
4000 final int NW = token.windows.size();
4001 for (int i=0; i<NW; i++) {
4002 WindowState win = token.windows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004003 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 mWindows.remove(win);
4005 int j = win.mChildWindows.size();
4006 while (j > 0) {
4007 j--;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004008 WindowState cwin = (WindowState)win.mChildWindows.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004009 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004010 "Tmp removing child window " + cwin);
4011 mWindows.remove(cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004012 }
4013 }
4014 return NW > 0;
4015 }
4016
4017 void dumpAppTokensLocked() {
4018 for (int i=mAppTokens.size()-1; i>=0; i--) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004019 Slog.v(TAG, " #" + i + ": " + mAppTokens.get(i).token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004020 }
4021 }
Romain Guy06882f82009-06-10 13:36:04 -07004022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004023 void dumpWindowsLocked() {
4024 for (int i=mWindows.size()-1; i>=0; i--) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004025 Slog.v(TAG, " #" + i + ": " + mWindows.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004026 }
4027 }
Romain Guy06882f82009-06-10 13:36:04 -07004028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004029 private int findWindowOffsetLocked(int tokenPos) {
4030 final int NW = mWindows.size();
4031
4032 if (tokenPos >= mAppTokens.size()) {
4033 int i = NW;
4034 while (i > 0) {
4035 i--;
4036 WindowState win = (WindowState)mWindows.get(i);
4037 if (win.getAppToken() != null) {
4038 return i+1;
4039 }
4040 }
4041 }
4042
4043 while (tokenPos > 0) {
4044 // Find the first app token below the new position that has
4045 // a window displayed.
4046 final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004047 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004048 + tokenPos + " -- " + wtoken.token);
Dianne Hackborna8f60182009-09-01 19:01:50 -07004049 if (wtoken.sendingToBottom) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004050 if (DEBUG_REORDER) Slog.v(TAG,
Dianne Hackborna8f60182009-09-01 19:01:50 -07004051 "Skipping token -- currently sending to bottom");
4052 tokenPos--;
4053 continue;
4054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055 int i = wtoken.windows.size();
4056 while (i > 0) {
4057 i--;
4058 WindowState win = wtoken.windows.get(i);
4059 int j = win.mChildWindows.size();
4060 while (j > 0) {
4061 j--;
4062 WindowState cwin = (WindowState)win.mChildWindows.get(j);
Dianne Hackborna8f60182009-09-01 19:01:50 -07004063 if (cwin.mSubLayer >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004064 for (int pos=NW-1; pos>=0; pos--) {
4065 if (mWindows.get(pos) == cwin) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004066 if (DEBUG_REORDER) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004067 "Found child win @" + (pos+1));
4068 return pos+1;
4069 }
4070 }
4071 }
4072 }
4073 for (int pos=NW-1; pos>=0; pos--) {
4074 if (mWindows.get(pos) == win) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004075 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004076 return pos+1;
4077 }
4078 }
4079 }
4080 tokenPos--;
4081 }
4082
4083 return 0;
4084 }
4085
4086 private final int reAddWindowLocked(int index, WindowState win) {
4087 final int NCW = win.mChildWindows.size();
4088 boolean added = false;
4089 for (int j=0; j<NCW; j++) {
4090 WindowState cwin = (WindowState)win.mChildWindows.get(j);
4091 if (!added && cwin.mSubLayer >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004092 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004093 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004094 mWindows.add(index, win);
4095 index++;
4096 added = true;
4097 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004098 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004099 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004100 mWindows.add(index, cwin);
4101 index++;
4102 }
4103 if (!added) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004104 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004105 + index + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 mWindows.add(index, win);
4107 index++;
4108 }
4109 return index;
4110 }
Romain Guy06882f82009-06-10 13:36:04 -07004111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004112 private final int reAddAppWindowsLocked(int index, WindowToken token) {
4113 final int NW = token.windows.size();
4114 for (int i=0; i<NW; i++) {
4115 index = reAddWindowLocked(index, token.windows.get(i));
4116 }
4117 return index;
4118 }
4119
4120 public void moveAppToken(int index, IBinder token) {
4121 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4122 "moveAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004123 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004124 }
4125
4126 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004127 if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004128 if (DEBUG_REORDER) dumpAppTokensLocked();
4129 final AppWindowToken wtoken = findAppWindowToken(token);
4130 if (wtoken == null || !mAppTokens.remove(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004131 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004132 + token + " (" + wtoken + ")");
4133 return;
4134 }
4135 mAppTokens.add(index, wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004136 if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004137 if (DEBUG_REORDER) dumpAppTokensLocked();
Romain Guy06882f82009-06-10 13:36:04 -07004138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004139 final long origId = Binder.clearCallingIdentity();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004140 if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004141 if (DEBUG_REORDER) dumpWindowsLocked();
4142 if (tmpRemoveAppWindowsLocked(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004143 if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144 if (DEBUG_REORDER) dumpWindowsLocked();
4145 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004146 if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004147 if (DEBUG_REORDER) dumpWindowsLocked();
4148 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004149 mLayoutNeeded = true;
4150 performLayoutAndPlaceSurfacesLocked();
4151 }
4152 Binder.restoreCallingIdentity(origId);
4153 }
4154 }
4155
4156 private void removeAppTokensLocked(List<IBinder> tokens) {
4157 // XXX This should be done more efficiently!
4158 // (take advantage of the fact that both lists should be
4159 // ordered in the same way.)
4160 int N = tokens.size();
4161 for (int i=0; i<N; i++) {
4162 IBinder token = tokens.get(i);
4163 final AppWindowToken wtoken = findAppWindowToken(token);
4164 if (!mAppTokens.remove(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004165 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 + token + " (" + wtoken + ")");
4167 i--;
4168 N--;
4169 }
4170 }
4171 }
4172
Dianne Hackborna8f60182009-09-01 19:01:50 -07004173 private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos,
4174 boolean updateFocusAndLayout) {
4175 // First remove all of the windows from the list.
4176 tmpRemoveAppWindowsLocked(wtoken);
4177
4178 // Where to start adding?
4179 int pos = findWindowOffsetLocked(tokenPos);
4180
4181 // And now add them back at the correct place.
4182 pos = reAddAppWindowsLocked(pos, wtoken);
4183
4184 if (updateFocusAndLayout) {
4185 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4186 assignLayersLocked();
4187 }
4188 mLayoutNeeded = true;
4189 performLayoutAndPlaceSurfacesLocked();
4190 }
4191 }
4192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004193 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
4194 // First remove all of the windows from the list.
4195 final int N = tokens.size();
4196 int i;
4197 for (i=0; i<N; i++) {
4198 WindowToken token = mTokenMap.get(tokens.get(i));
4199 if (token != null) {
4200 tmpRemoveAppWindowsLocked(token);
4201 }
4202 }
4203
4204 // Where to start adding?
4205 int pos = findWindowOffsetLocked(tokenPos);
4206
4207 // And now add them back at the correct place.
4208 for (i=0; i<N; i++) {
4209 WindowToken token = mTokenMap.get(tokens.get(i));
4210 if (token != null) {
4211 pos = reAddAppWindowsLocked(pos, token);
4212 }
4213 }
4214
Dianne Hackborna8f60182009-09-01 19:01:50 -07004215 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4216 assignLayersLocked();
4217 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004218 mLayoutNeeded = true;
4219 performLayoutAndPlaceSurfacesLocked();
4220
4221 //dump();
4222 }
4223
4224 public void moveAppTokensToTop(List<IBinder> tokens) {
4225 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4226 "moveAppTokensToTop()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004227 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004228 }
4229
4230 final long origId = Binder.clearCallingIdentity();
4231 synchronized(mWindowMap) {
4232 removeAppTokensLocked(tokens);
4233 final int N = tokens.size();
4234 for (int i=0; i<N; i++) {
4235 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4236 if (wt != null) {
4237 mAppTokens.add(wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004238 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004239 mToTopApps.remove(wt);
4240 mToBottomApps.remove(wt);
4241 mToTopApps.add(wt);
4242 wt.sendingToBottom = false;
4243 wt.sendingToTop = true;
4244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 }
4246 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004247
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004248 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004249 moveAppWindowsLocked(tokens, mAppTokens.size());
4250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004251 }
4252 Binder.restoreCallingIdentity(origId);
4253 }
4254
4255 public void moveAppTokensToBottom(List<IBinder> tokens) {
4256 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4257 "moveAppTokensToBottom()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004258 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 }
4260
4261 final long origId = Binder.clearCallingIdentity();
4262 synchronized(mWindowMap) {
4263 removeAppTokensLocked(tokens);
4264 final int N = tokens.size();
4265 int pos = 0;
4266 for (int i=0; i<N; i++) {
4267 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4268 if (wt != null) {
4269 mAppTokens.add(pos, wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004270 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004271 mToTopApps.remove(wt);
4272 mToBottomApps.remove(wt);
4273 mToBottomApps.add(i, wt);
4274 wt.sendingToTop = false;
4275 wt.sendingToBottom = true;
4276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004277 pos++;
4278 }
4279 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004280
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004281 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004282 moveAppWindowsLocked(tokens, 0);
4283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004284 }
4285 Binder.restoreCallingIdentity(origId);
4286 }
4287
4288 // -------------------------------------------------------------
4289 // Misc IWindowSession methods
4290 // -------------------------------------------------------------
Romain Guy06882f82009-06-10 13:36:04 -07004291
Jim Miller284b62e2010-06-08 14:27:42 -07004292 private boolean shouldAllowDisableKeyguard()
Jim Millerd6b57052010-06-07 17:52:42 -07004293 {
Jim Miller284b62e2010-06-08 14:27:42 -07004294 // We fail safe and prevent disabling keyguard in the unlikely event this gets
4295 // called before DevicePolicyManagerService has started.
4296 if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
4297 DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
4298 Context.DEVICE_POLICY_SERVICE);
4299 if (dpm != null) {
4300 mAllowDisableKeyguard = dpm.getPasswordQuality(null)
4301 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
4302 ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
4303 }
Jim Millerd6b57052010-06-07 17:52:42 -07004304 }
Jim Miller284b62e2010-06-08 14:27:42 -07004305 return mAllowDisableKeyguard == ALLOW_DISABLE_YES;
Jim Millerd6b57052010-06-07 17:52:42 -07004306 }
4307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004308 public void disableKeyguard(IBinder token, String tag) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004309 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 != PackageManager.PERMISSION_GRANTED) {
4311 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4312 }
Jim Millerd6b57052010-06-07 17:52:42 -07004313
Jim Miller284b62e2010-06-08 14:27:42 -07004314 synchronized (mKeyguardTokenWatcher) {
4315 mKeyguardTokenWatcher.acquire(token, tag);
Mike Lockwooddd884682009-10-11 16:57:08 -04004316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 }
4318
4319 public void reenableKeyguard(IBinder token) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004320 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004321 != PackageManager.PERMISSION_GRANTED) {
4322 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4323 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004324
Jim Miller284b62e2010-06-08 14:27:42 -07004325 synchronized (mKeyguardTokenWatcher) {
4326 mKeyguardTokenWatcher.release(token);
Jim Millerd6b57052010-06-07 17:52:42 -07004327
Jim Miller284b62e2010-06-08 14:27:42 -07004328 if (!mKeyguardTokenWatcher.isAcquired()) {
4329 // If we are the last one to reenable the keyguard wait until
4330 // we have actually finished reenabling until returning.
4331 // It is possible that reenableKeyguard() can be called before
4332 // the previous disableKeyguard() is handled, in which case
4333 // neither mKeyguardTokenWatcher.acquired() or released() would
4334 // be called. In that case mKeyguardDisabled will be false here
4335 // and we have nothing to wait for.
4336 while (mKeyguardDisabled) {
4337 try {
4338 mKeyguardTokenWatcher.wait();
4339 } catch (InterruptedException e) {
4340 Thread.currentThread().interrupt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004341 }
4342 }
4343 }
4344 }
4345 }
4346
4347 /**
4348 * @see android.app.KeyguardManager#exitKeyguardSecurely
4349 */
4350 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004351 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004352 != PackageManager.PERMISSION_GRANTED) {
4353 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4354 }
4355 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
4356 public void onKeyguardExitResult(boolean success) {
4357 try {
4358 callback.onKeyguardExitResult(success);
4359 } catch (RemoteException e) {
4360 // Client has died, we don't care.
4361 }
4362 }
4363 });
4364 }
4365
4366 public boolean inKeyguardRestrictedInputMode() {
4367 return mPolicy.inKeyguardRestrictedKeyInputMode();
4368 }
Romain Guy06882f82009-06-10 13:36:04 -07004369
Dianne Hackbornffa42482009-09-23 22:20:11 -07004370 public void closeSystemDialogs(String reason) {
4371 synchronized(mWindowMap) {
4372 for (int i=mWindows.size()-1; i>=0; i--) {
4373 WindowState w = (WindowState)mWindows.get(i);
4374 if (w.mSurface != null) {
4375 try {
4376 w.mClient.closeSystemDialogs(reason);
4377 } catch (RemoteException e) {
4378 }
4379 }
4380 }
4381 }
4382 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 static float fixScale(float scale) {
4385 if (scale < 0) scale = 0;
4386 else if (scale > 20) scale = 20;
4387 return Math.abs(scale);
4388 }
Romain Guy06882f82009-06-10 13:36:04 -07004389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004390 public void setAnimationScale(int which, float scale) {
4391 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4392 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004393 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004394 }
4395
4396 if (scale < 0) scale = 0;
4397 else if (scale > 20) scale = 20;
4398 scale = Math.abs(scale);
4399 switch (which) {
4400 case 0: mWindowAnimationScale = fixScale(scale); break;
4401 case 1: mTransitionAnimationScale = fixScale(scale); break;
4402 }
Romain Guy06882f82009-06-10 13:36:04 -07004403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004404 // Persist setting
4405 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4406 }
Romain Guy06882f82009-06-10 13:36:04 -07004407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004408 public void setAnimationScales(float[] scales) {
4409 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4410 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004411 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 }
4413
4414 if (scales != null) {
4415 if (scales.length >= 1) {
4416 mWindowAnimationScale = fixScale(scales[0]);
4417 }
4418 if (scales.length >= 2) {
4419 mTransitionAnimationScale = fixScale(scales[1]);
4420 }
4421 }
Romain Guy06882f82009-06-10 13:36:04 -07004422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004423 // Persist setting
4424 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4425 }
Romain Guy06882f82009-06-10 13:36:04 -07004426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004427 public float getAnimationScale(int which) {
4428 switch (which) {
4429 case 0: return mWindowAnimationScale;
4430 case 1: return mTransitionAnimationScale;
4431 }
4432 return 0;
4433 }
Romain Guy06882f82009-06-10 13:36:04 -07004434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 public float[] getAnimationScales() {
4436 return new float[] { mWindowAnimationScale, mTransitionAnimationScale };
4437 }
Romain Guy06882f82009-06-10 13:36:04 -07004438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004439 public int getSwitchState(int sw) {
4440 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4441 "getSwitchState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004442 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004444 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4445 return mInputManager.getSwitchState(sw);
4446 } else {
4447 return KeyInputQueue.getSwitchState(sw);
4448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004449 }
Romain Guy06882f82009-06-10 13:36:04 -07004450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004451 public int getSwitchStateForDevice(int devid, int sw) {
4452 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4453 "getSwitchStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004454 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004456 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4457 return mInputManager.getSwitchState(devid, sw);
4458 } else {
4459 return KeyInputQueue.getSwitchState(devid, sw);
4460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004461 }
Romain Guy06882f82009-06-10 13:36:04 -07004462
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004463 public int getScancodeState(int sw) {
4464 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4465 "getScancodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004466 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004467 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004468 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4469 return mInputManager.getScancodeState(sw);
4470 } else {
4471 return mQueue.getScancodeState(sw);
4472 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 }
Romain Guy06882f82009-06-10 13:36:04 -07004474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 public int getScancodeStateForDevice(int devid, int sw) {
4476 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4477 "getScancodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004478 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004479 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004480 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4481 return mInputManager.getScancodeState(devid, sw);
4482 } else {
4483 return mQueue.getScancodeState(devid, sw);
4484 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004485 }
Romain Guy06882f82009-06-10 13:36:04 -07004486
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004487 public int getTrackballScancodeState(int sw) {
4488 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4489 "getTrackballScancodeState()")) {
4490 throw new SecurityException("Requires READ_INPUT_STATE permission");
4491 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004492 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4493 return mInputManager.getTrackballScancodeState(sw);
4494 } else {
4495 return mQueue.getTrackballScancodeState(sw);
4496 }
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004497 }
4498
4499 public int getDPadScancodeState(int sw) {
4500 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4501 "getDPadScancodeState()")) {
4502 throw new SecurityException("Requires READ_INPUT_STATE permission");
4503 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004504 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4505 return mInputManager.getDPadScancodeState(sw);
4506 } else {
4507 return mQueue.getDPadScancodeState(sw);
4508 }
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004509 }
4510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004511 public int getKeycodeState(int sw) {
4512 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4513 "getKeycodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004514 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004516 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4517 return mInputManager.getKeycodeState(sw);
4518 } else {
4519 return mQueue.getKeycodeState(sw);
4520 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 }
Romain Guy06882f82009-06-10 13:36:04 -07004522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004523 public int getKeycodeStateForDevice(int devid, int sw) {
4524 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4525 "getKeycodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004526 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004528 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4529 return mInputManager.getKeycodeState(devid, sw);
4530 } else {
4531 return mQueue.getKeycodeState(devid, sw);
4532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004533 }
Romain Guy06882f82009-06-10 13:36:04 -07004534
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004535 public int getTrackballKeycodeState(int sw) {
4536 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4537 "getTrackballKeycodeState()")) {
4538 throw new SecurityException("Requires READ_INPUT_STATE permission");
4539 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004540 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4541 return mInputManager.getTrackballKeycodeState(sw);
4542 } else {
4543 return mQueue.getTrackballKeycodeState(sw);
4544 }
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004545 }
4546
4547 public int getDPadKeycodeState(int sw) {
4548 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4549 "getDPadKeycodeState()")) {
4550 throw new SecurityException("Requires READ_INPUT_STATE permission");
4551 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004552 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4553 return mInputManager.getDPadKeycodeState(sw);
4554 } else {
4555 return mQueue.getDPadKeycodeState(sw);
4556 }
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004557 }
4558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004560 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4561 return mInputManager.hasKeys(keycodes, keyExists);
4562 } else {
4563 return KeyInputQueue.hasKeys(keycodes, keyExists);
4564 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565 }
Romain Guy06882f82009-06-10 13:36:04 -07004566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004567 public void enableScreenAfterBoot() {
4568 synchronized(mWindowMap) {
4569 if (mSystemBooted) {
4570 return;
4571 }
4572 mSystemBooted = true;
4573 }
Romain Guy06882f82009-06-10 13:36:04 -07004574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004575 performEnableScreen();
4576 }
Romain Guy06882f82009-06-10 13:36:04 -07004577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004578 public void enableScreenIfNeededLocked() {
4579 if (mDisplayEnabled) {
4580 return;
4581 }
4582 if (!mSystemBooted) {
4583 return;
4584 }
4585 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
4586 }
Romain Guy06882f82009-06-10 13:36:04 -07004587
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004588 public void performEnableScreen() {
4589 synchronized(mWindowMap) {
4590 if (mDisplayEnabled) {
4591 return;
4592 }
4593 if (!mSystemBooted) {
4594 return;
4595 }
Romain Guy06882f82009-06-10 13:36:04 -07004596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 // Don't enable the screen until all existing windows
4598 // have been drawn.
4599 final int N = mWindows.size();
4600 for (int i=0; i<N; i++) {
4601 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn5943c202010-04-12 21:36:49 -07004602 if (w.isVisibleLw() && !w.mObscured
4603 && (w.mOrientationChanging || !w.isDrawnLw())) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004604 return;
4605 }
4606 }
Romain Guy06882f82009-06-10 13:36:04 -07004607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004608 mDisplayEnabled = true;
4609 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004610 Slog.i(TAG, "ENABLING SCREEN!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004611 StringWriter sw = new StringWriter();
4612 PrintWriter pw = new PrintWriter(sw);
4613 this.dump(null, pw, null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004614 Slog.i(TAG, sw.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004615 }
4616 try {
4617 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
4618 if (surfaceFlinger != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004619 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004620 Parcel data = Parcel.obtain();
4621 data.writeInterfaceToken("android.ui.ISurfaceComposer");
4622 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
4623 data, null, 0);
4624 data.recycle();
4625 }
4626 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004627 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004628 }
4629 }
Romain Guy06882f82009-06-10 13:36:04 -07004630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004631 mPolicy.enableScreenAfterBoot();
Romain Guy06882f82009-06-10 13:36:04 -07004632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004633 // Make sure the last requested orientation has been applied.
Dianne Hackborn321ae682009-03-27 16:16:03 -07004634 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
4635 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004636 }
Romain Guy06882f82009-06-10 13:36:04 -07004637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638 public void setInTouchMode(boolean mode) {
4639 synchronized(mWindowMap) {
4640 mInTouchMode = mode;
4641 }
4642 }
4643
Romain Guy06882f82009-06-10 13:36:04 -07004644 public void setRotation(int rotation,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004645 boolean alwaysSendConfiguration, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004646 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004647 "setRotation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004648 throw new SecurityException("Requires SET_ORIENTATION permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004649 }
4650
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004651 setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004652 }
Romain Guy06882f82009-06-10 13:36:04 -07004653
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004654 public void setRotationUnchecked(int rotation,
4655 boolean alwaysSendConfiguration, int animFlags) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004656 if(DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004657 "alwaysSendConfiguration set to "+alwaysSendConfiguration);
Romain Guy06882f82009-06-10 13:36:04 -07004658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004659 long origId = Binder.clearCallingIdentity();
4660 boolean changed;
4661 synchronized(mWindowMap) {
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004662 changed = setRotationUncheckedLocked(rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004663 }
Romain Guy06882f82009-06-10 13:36:04 -07004664
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004665 if (changed || alwaysSendConfiguration) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004666 sendNewConfiguration();
4667 }
Romain Guy06882f82009-06-10 13:36:04 -07004668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004669 Binder.restoreCallingIdentity(origId);
4670 }
Romain Guy06882f82009-06-10 13:36:04 -07004671
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004672 /**
4673 * Apply a new rotation to the screen, respecting the requests of
4674 * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply
4675 * re-evaluate the desired rotation.
4676 *
4677 * Returns null if the rotation has been changed. In this case YOU
4678 * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
4679 */
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004680 public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004681 boolean changed;
4682 if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
4683 rotation = mRequestedRotation;
4684 } else {
4685 mRequestedRotation = rotation;
Dianne Hackborn321ae682009-03-27 16:16:03 -07004686 mLastRotationFlags = animFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004687 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004688 if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation);
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07004689 rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004690 mRotation, mDisplayEnabled);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004691 if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004692 changed = mDisplayEnabled && mRotation != rotation;
Romain Guy06882f82009-06-10 13:36:04 -07004693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004694 if (changed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004695 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004696 "Rotation changed to " + rotation
4697 + " from " + mRotation
4698 + " (forceApp=" + mForcedAppOrientation
4699 + ", req=" + mRequestedRotation + ")");
4700 mRotation = rotation;
4701 mWindowsFreezingScreen = true;
4702 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
4703 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
4704 2000);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004705 mWaitingForConfig = true;
4706 mLayoutNeeded = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004707 startFreezingDisplayLocked();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004708 Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004709 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4710 mInputManager.setDisplayOrientation(0, rotation);
4711 } else {
4712 mQueue.setOrientation(rotation);
4713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004714 if (mDisplayEnabled) {
Dianne Hackborn321ae682009-03-27 16:16:03 -07004715 Surface.setOrientation(0, rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004716 }
4717 for (int i=mWindows.size()-1; i>=0; i--) {
4718 WindowState w = (WindowState)mWindows.get(i);
4719 if (w.mSurface != null) {
4720 w.mOrientationChanging = true;
4721 }
4722 }
4723 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
4724 try {
4725 mRotationWatchers.get(i).onRotationChanged(rotation);
4726 } catch (RemoteException e) {
4727 }
4728 }
4729 } //end if changed
Romain Guy06882f82009-06-10 13:36:04 -07004730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004731 return changed;
4732 }
Romain Guy06882f82009-06-10 13:36:04 -07004733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 public int getRotation() {
4735 return mRotation;
4736 }
4737
4738 public int watchRotation(IRotationWatcher watcher) {
4739 final IBinder watcherBinder = watcher.asBinder();
4740 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4741 public void binderDied() {
4742 synchronized (mWindowMap) {
4743 for (int i=0; i<mRotationWatchers.size(); i++) {
4744 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004745 IRotationWatcher removed = mRotationWatchers.remove(i);
4746 if (removed != null) {
4747 removed.asBinder().unlinkToDeath(this, 0);
4748 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004749 i--;
4750 }
4751 }
4752 }
4753 }
4754 };
Romain Guy06882f82009-06-10 13:36:04 -07004755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004756 synchronized (mWindowMap) {
4757 try {
4758 watcher.asBinder().linkToDeath(dr, 0);
4759 mRotationWatchers.add(watcher);
4760 } catch (RemoteException e) {
4761 // Client died, no cleanup needed.
4762 }
Romain Guy06882f82009-06-10 13:36:04 -07004763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004764 return mRotation;
4765 }
4766 }
4767
4768 /**
4769 * Starts the view server on the specified port.
4770 *
4771 * @param port The port to listener to.
4772 *
4773 * @return True if the server was successfully started, false otherwise.
4774 *
4775 * @see com.android.server.ViewServer
4776 * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT
4777 */
4778 public boolean startViewServer(int port) {
Romain Guy06882f82009-06-10 13:36:04 -07004779 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004780 return false;
4781 }
4782
4783 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4784 return false;
4785 }
4786
4787 if (port < 1024) {
4788 return false;
4789 }
4790
4791 if (mViewServer != null) {
4792 if (!mViewServer.isRunning()) {
4793 try {
4794 return mViewServer.start();
4795 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004796 Slog.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004797 }
4798 }
4799 return false;
4800 }
4801
4802 try {
4803 mViewServer = new ViewServer(this, port);
4804 return mViewServer.start();
4805 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004806 Slog.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004807 }
4808 return false;
4809 }
4810
Romain Guy06882f82009-06-10 13:36:04 -07004811 private boolean isSystemSecure() {
4812 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4813 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4814 }
4815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004816 /**
4817 * Stops the view server if it exists.
4818 *
4819 * @return True if the server stopped, false if it wasn't started or
4820 * couldn't be stopped.
4821 *
4822 * @see com.android.server.ViewServer
4823 */
4824 public boolean stopViewServer() {
Romain Guy06882f82009-06-10 13:36:04 -07004825 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004826 return false;
4827 }
4828
4829 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4830 return false;
4831 }
4832
4833 if (mViewServer != null) {
4834 return mViewServer.stop();
4835 }
4836 return false;
4837 }
4838
4839 /**
4840 * Indicates whether the view server is running.
4841 *
4842 * @return True if the server is running, false otherwise.
4843 *
4844 * @see com.android.server.ViewServer
4845 */
4846 public boolean isViewServerRunning() {
Romain Guy06882f82009-06-10 13:36:04 -07004847 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004848 return false;
4849 }
4850
4851 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4852 return false;
4853 }
4854
4855 return mViewServer != null && mViewServer.isRunning();
4856 }
4857
4858 /**
4859 * Lists all availble windows in the system. The listing is written in the
4860 * specified Socket's output stream with the following syntax:
4861 * windowHashCodeInHexadecimal windowName
4862 * Each line of the ouput represents a different window.
4863 *
4864 * @param client The remote client to send the listing to.
4865 * @return False if an error occured, true otherwise.
4866 */
4867 boolean viewServerListWindows(Socket client) {
Romain Guy06882f82009-06-10 13:36:04 -07004868 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869 return false;
4870 }
4871
4872 boolean result = true;
4873
4874 Object[] windows;
4875 synchronized (mWindowMap) {
4876 windows = new Object[mWindows.size()];
4877 //noinspection unchecked
4878 windows = mWindows.toArray(windows);
4879 }
4880
4881 BufferedWriter out = null;
4882
4883 // Any uncaught exception will crash the system process
4884 try {
4885 OutputStream clientStream = client.getOutputStream();
4886 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4887
4888 final int count = windows.length;
4889 for (int i = 0; i < count; i++) {
4890 final WindowState w = (WindowState) windows[i];
4891 out.write(Integer.toHexString(System.identityHashCode(w)));
4892 out.write(' ');
4893 out.append(w.mAttrs.getTitle());
4894 out.write('\n');
4895 }
4896
4897 out.write("DONE.\n");
4898 out.flush();
4899 } catch (Exception e) {
4900 result = false;
4901 } finally {
4902 if (out != null) {
4903 try {
4904 out.close();
4905 } catch (IOException e) {
4906 result = false;
4907 }
4908 }
4909 }
4910
4911 return result;
4912 }
4913
4914 /**
4915 * Sends a command to a target window. The result of the command, if any, will be
4916 * written in the output stream of the specified socket.
4917 *
4918 * The parameters must follow this syntax:
4919 * windowHashcode extra
4920 *
4921 * Where XX is the length in characeters of the windowTitle.
4922 *
4923 * The first parameter is the target window. The window with the specified hashcode
4924 * will be the target. If no target can be found, nothing happens. The extra parameters
4925 * will be delivered to the target window and as parameters to the command itself.
4926 *
4927 * @param client The remote client to sent the result, if any, to.
4928 * @param command The command to execute.
4929 * @param parameters The command parameters.
4930 *
4931 * @return True if the command was successfully delivered, false otherwise. This does
4932 * not indicate whether the command itself was successful.
4933 */
4934 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
Romain Guy06882f82009-06-10 13:36:04 -07004935 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004936 return false;
4937 }
4938
4939 boolean success = true;
4940 Parcel data = null;
4941 Parcel reply = null;
4942
4943 // Any uncaught exception will crash the system process
4944 try {
4945 // Find the hashcode of the window
4946 int index = parameters.indexOf(' ');
4947 if (index == -1) {
4948 index = parameters.length();
4949 }
4950 final String code = parameters.substring(0, index);
Romain Guy236092a2009-12-14 15:31:48 -08004951 int hashCode = (int) Long.parseLong(code, 16);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004952
4953 // Extract the command's parameter after the window description
4954 if (index < parameters.length()) {
4955 parameters = parameters.substring(index + 1);
4956 } else {
4957 parameters = "";
4958 }
4959
4960 final WindowManagerService.WindowState window = findWindow(hashCode);
4961 if (window == null) {
4962 return false;
4963 }
4964
4965 data = Parcel.obtain();
4966 data.writeInterfaceToken("android.view.IWindow");
4967 data.writeString(command);
4968 data.writeString(parameters);
4969 data.writeInt(1);
4970 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4971
4972 reply = Parcel.obtain();
4973
4974 final IBinder binder = window.mClient.asBinder();
4975 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4976 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4977
4978 reply.readException();
4979
4980 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004981 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 success = false;
4983 } finally {
4984 if (data != null) {
4985 data.recycle();
4986 }
4987 if (reply != null) {
4988 reply.recycle();
4989 }
4990 }
4991
4992 return success;
4993 }
4994
4995 private WindowState findWindow(int hashCode) {
4996 if (hashCode == -1) {
4997 return getFocusedWindow();
4998 }
4999
5000 synchronized (mWindowMap) {
5001 final ArrayList windows = mWindows;
5002 final int count = windows.size();
5003
5004 for (int i = 0; i < count; i++) {
5005 WindowState w = (WindowState) windows.get(i);
5006 if (System.identityHashCode(w) == hashCode) {
5007 return w;
5008 }
5009 }
5010 }
5011
5012 return null;
5013 }
5014
5015 /*
5016 * Instruct the Activity Manager to fetch the current configuration and broadcast
5017 * that to config-changed listeners if appropriate.
5018 */
5019 void sendNewConfiguration() {
5020 try {
5021 mActivityManager.updateConfiguration(null);
5022 } catch (RemoteException e) {
5023 }
5024 }
Romain Guy06882f82009-06-10 13:36:04 -07005025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005026 public Configuration computeNewConfiguration() {
5027 synchronized (mWindowMap) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07005028 return computeNewConfigurationLocked();
5029 }
5030 }
Romain Guy06882f82009-06-10 13:36:04 -07005031
Dianne Hackbornc485a602009-03-24 22:39:49 -07005032 Configuration computeNewConfigurationLocked() {
5033 Configuration config = new Configuration();
5034 if (!computeNewConfigurationLocked(config)) {
5035 return null;
5036 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07005037 return config;
5038 }
Romain Guy06882f82009-06-10 13:36:04 -07005039
Dianne Hackbornc485a602009-03-24 22:39:49 -07005040 boolean computeNewConfigurationLocked(Configuration config) {
5041 if (mDisplay == null) {
5042 return false;
5043 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005044 if (ENABLE_NATIVE_INPUT_DISPATCH) {
5045 mInputManager.getInputConfiguration(config);
5046 } else {
5047 mQueue.getInputConfiguration(config);
5048 }
Christopher Tateb696aee2010-04-02 19:08:30 -07005049
5050 // Use the effective "visual" dimensions based on current rotation
5051 final boolean rotated = (mRotation == Surface.ROTATION_90
5052 || mRotation == Surface.ROTATION_270);
5053 final int dw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth;
5054 final int dh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight;
5055
Dianne Hackbornc485a602009-03-24 22:39:49 -07005056 int orientation = Configuration.ORIENTATION_SQUARE;
5057 if (dw < dh) {
5058 orientation = Configuration.ORIENTATION_PORTRAIT;
5059 } else if (dw > dh) {
5060 orientation = Configuration.ORIENTATION_LANDSCAPE;
5061 }
5062 config.orientation = orientation;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005063
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07005064 DisplayMetrics dm = new DisplayMetrics();
5065 mDisplay.getMetrics(dm);
5066 CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
5067
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005068 if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07005069 // Note we only do this once because at this point we don't
5070 // expect the screen to change in this way at runtime, and want
5071 // to avoid all of this computation for every config change.
Dianne Hackborn723738c2009-06-25 19:48:04 -07005072 int longSize = dw;
5073 int shortSize = dh;
5074 if (longSize < shortSize) {
5075 int tmp = longSize;
5076 longSize = shortSize;
5077 shortSize = tmp;
5078 }
5079 longSize = (int)(longSize/dm.density);
5080 shortSize = (int)(shortSize/dm.density);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07005081
Dianne Hackborn723738c2009-06-25 19:48:04 -07005082 // These semi-magic numbers define our compatibility modes for
5083 // applications with different screens. Don't change unless you
5084 // make sure to test lots and lots of apps!
5085 if (longSize < 470) {
5086 // This is shorter than an HVGA normal density screen (which
5087 // is 480 pixels on its long side).
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005088 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
5089 | Configuration.SCREENLAYOUT_LONG_NO;
Dianne Hackborn723738c2009-06-25 19:48:04 -07005090 } else {
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07005091 // What size is this screen screen?
5092 if (longSize >= 800 && shortSize >= 600) {
5093 // SVGA or larger screens at medium density are the point
5094 // at which we consider it to be an extra large screen.
5095 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE;
5096 } else if (longSize >= 640 && shortSize >= 480) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005097 // VGA or larger screens at medium density are the point
5098 // at which we consider it to be a large screen.
5099 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
5100 } else {
5101 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005102
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005103 // If this screen is wider than normal HVGA, or taller
5104 // than FWVGA, then for old apps we want to run in size
5105 // compatibility mode.
5106 if (shortSize > 321 || longSize > 570) {
5107 mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
5108 }
5109 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005110
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005111 // Is this a long screen?
5112 if (((longSize*3)/5) >= (shortSize-1)) {
5113 // Anything wider than WVGA (5:3) is considering to be long.
5114 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
5115 } else {
5116 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
5117 }
Dianne Hackborn723738c2009-06-25 19:48:04 -07005118 }
5119 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005120 config.screenLayout = mScreenLayout;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005121
Dianne Hackbornc485a602009-03-24 22:39:49 -07005122 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
5123 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
5124 mPolicy.adjustConfigurationLw(config);
5125 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005126 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07005127
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005128 // -------------------------------------------------------------
5129 // Input Events and Focus Management
5130 // -------------------------------------------------------------
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005131
Jeff Brown349703e2010-06-22 01:27:15 -07005132 InputMonitor mInputMonitor = new InputMonitor();
5133
5134 /* Tracks the progress of input dispatch and ensures that input dispatch state
5135 * is kept in sync with changes in window focus, visibility, registration, and
5136 * other relevant Window Manager state transitions. */
5137 final class InputMonitor {
5138 // Current window with input focus for keys and other non-touch events. May be null.
5139 private WindowState mInputFocus;
5140
5141 // When true, prevents input dispatch from proceeding until set to false again.
5142 private boolean mInputDispatchFrozen;
5143
5144 // When true, input dispatch proceeds normally. Otherwise all events are dropped.
5145 private boolean mInputDispatchEnabled = true;
5146
5147 // Temporary list of windows information to provide to the input dispatcher.
5148 private InputWindowList mTempInputWindows = new InputWindowList();
5149
5150 // Temporary input application object to provide to the input dispatcher.
5151 private InputApplication mTempInputApplication = new InputApplication();
5152
5153 /* Notifies the window manager about a broken input channel.
5154 *
5155 * Called by the InputManager.
5156 */
5157 public void notifyInputChannelBroken(InputChannel inputChannel) {
5158 synchronized (mWindowMap) {
5159 WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
5160 if (windowState == null) {
5161 return; // irrelevant
5162 }
5163
5164 Slog.i(TAG, "WINDOW DIED " + windowState);
5165 removeWindowLocked(windowState.mSession, windowState);
Jeff Brown7fbdc842010-06-17 20:52:56 -07005166 }
5167 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005168
Jeff Brown349703e2010-06-22 01:27:15 -07005169 /* Notifies the window manager about an input channel that is not responding.
5170 * The method can either cause dispatching to be aborted by returning -2 or
5171 * return a new timeout in nanoseconds.
5172 *
5173 * Called by the InputManager.
5174 */
5175 public long notifyInputChannelANR(InputChannel inputChannel) {
5176 AppWindowToken token;
5177 synchronized (mWindowMap) {
5178 WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
5179 if (windowState == null) {
5180 return -2; // irrelevant, abort dispatching (-2)
5181 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07005182
Jeff Brown349703e2010-06-22 01:27:15 -07005183 Slog.i(TAG, "Input event dispatching timed out sending to "
5184 + windowState.mAttrs.getTitle());
5185 token = windowState.mAppToken;
Jeff Brown7fbdc842010-06-17 20:52:56 -07005186 }
5187
Jeff Brown349703e2010-06-22 01:27:15 -07005188 return notifyANRInternal(token);
5189 }
5190
5191 /* Notifies the window manager about an input channel spontaneously recovering from ANR
5192 * by successfully delivering the event that originally timed out.
5193 *
5194 * Called by the InputManager.
5195 */
5196 public void notifyInputChannelRecoveredFromANR(InputChannel inputChannel) {
5197 // Nothing to do just now.
5198 // Just wait for the user to dismiss the ANR dialog.
5199 }
5200
5201 /* Notifies the window manager about an application that is not responding
5202 * in general rather than with respect to a particular input channel.
5203 * The method can either cause dispatching to be aborted by returning -2 or
5204 * return a new timeout in nanoseconds.
5205 *
5206 * Called by the InputManager.
5207 */
5208 public long notifyANR(Object token) {
5209 AppWindowToken appWindowToken = (AppWindowToken) token;
5210
5211 Slog.i(TAG, "Input event dispatching timed out sending to application "
5212 + appWindowToken.stringName);
5213 return notifyANRInternal(appWindowToken);
5214 }
5215
5216 private long notifyANRInternal(AppWindowToken token) {
5217 if (token != null && token.appToken != null) {
5218 try {
5219 // Notify the activity manager about the timeout and let it decide whether
5220 // to abort dispatching or keep waiting.
5221 boolean abort = token.appToken.keyDispatchingTimedOut();
5222 if (! abort) {
5223 // The activity manager declined to abort dispatching.
5224 // Wait a bit longer and timeout again later.
5225 return token.inputDispatchingTimeoutNanos;
Jeff Brown7fbdc842010-06-17 20:52:56 -07005226 }
Jeff Brown349703e2010-06-22 01:27:15 -07005227 } catch (RemoteException ex) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07005228 }
5229 }
Jeff Brown349703e2010-06-22 01:27:15 -07005230 return -2; // abort dispatching
Jeff Brown7fbdc842010-06-17 20:52:56 -07005231 }
5232
Jeff Brown349703e2010-06-22 01:27:15 -07005233 private WindowState getWindowStateForInputChannel(InputChannel inputChannel) {
5234 synchronized (mWindowMap) {
5235 return getWindowStateForInputChannelLocked(inputChannel);
5236 }
5237 }
5238
5239 private WindowState getWindowStateForInputChannelLocked(InputChannel inputChannel) {
5240 int windowCount = mWindows.size();
5241 for (int i = 0; i < windowCount; i++) {
5242 WindowState windowState = (WindowState) mWindows.get(i);
5243 if (windowState.mInputChannel == inputChannel) {
5244 return windowState;
5245 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07005246 }
5247
Jeff Brown349703e2010-06-22 01:27:15 -07005248 return null;
Jeff Brown7fbdc842010-06-17 20:52:56 -07005249 }
5250
Jeff Brown349703e2010-06-22 01:27:15 -07005251 /* Updates the cached window information provided to the input dispatcher. */
5252 public void updateInputWindowsLw() {
5253 // Populate the input window list with information about all of the windows that
5254 // could potentially receive input.
5255 // As an optimization, we could try to prune the list of windows but this turns
5256 // out to be difficult because only the native code knows for sure which window
5257 // currently has touch focus.
Jeff Brown7fbdc842010-06-17 20:52:56 -07005258 final ArrayList windows = mWindows;
5259 final int N = windows.size();
Jeff Brown349703e2010-06-22 01:27:15 -07005260 for (int i = N - 1; i >= 0; i--) {
5261 final WindowState child = (WindowState) windows.get(i);
5262 if (child.mInputChannel == null) {
5263 // Skip this window because it cannot possibly receive input.
Jeff Brown7fbdc842010-06-17 20:52:56 -07005264 continue;
5265 }
5266
Jeff Brown349703e2010-06-22 01:27:15 -07005267 final int flags = child.mAttrs.flags;
5268 final int type = child.mAttrs.type;
5269
5270 final boolean hasFocus = (child == mInputFocus);
5271 final boolean isVisible = child.isVisibleLw();
5272 final boolean hasWallpaper = (child == mWallpaperTarget)
5273 && (type != WindowManager.LayoutParams.TYPE_KEYGUARD);
5274
5275 // Add a window to our list of input windows.
5276 final InputWindow inputWindow = mTempInputWindows.add();
5277 inputWindow.inputChannel = child.mInputChannel;
5278 inputWindow.layoutParamsFlags = flags;
5279 inputWindow.layoutParamsType = type;
5280 inputWindow.dispatchingTimeoutNanos = child.getInputDispatchingTimeoutNanos();
5281 inputWindow.visible = isVisible;
5282 inputWindow.hasFocus = hasFocus;
5283 inputWindow.hasWallpaper = hasWallpaper;
5284 inputWindow.paused = child.mAppToken != null ? child.mAppToken.paused : false;
5285 inputWindow.ownerPid = child.mSession.mPid;
5286 inputWindow.ownerUid = child.mSession.mUid;
5287
5288 final Rect frame = child.mFrame;
5289 inputWindow.frameLeft = frame.left;
5290 inputWindow.frameTop = frame.top;
5291
5292 switch (child.mTouchableInsets) {
5293 default:
5294 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
5295 inputWindow.touchableAreaLeft = frame.left;
5296 inputWindow.touchableAreaTop = frame.top;
5297 inputWindow.touchableAreaRight = frame.right;
5298 inputWindow.touchableAreaBottom = frame.bottom;
5299 break;
5300
5301 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: {
5302 Rect inset = child.mGivenContentInsets;
5303 inputWindow.touchableAreaLeft = frame.left + inset.left;
5304 inputWindow.touchableAreaTop = frame.top + inset.top;
5305 inputWindow.touchableAreaRight = frame.right - inset.right;
5306 inputWindow.touchableAreaBottom = frame.bottom - inset.bottom;
5307 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005308 }
Jeff Brown349703e2010-06-22 01:27:15 -07005309
5310 case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: {
5311 Rect inset = child.mGivenVisibleInsets;
5312 inputWindow.touchableAreaLeft = frame.left + inset.left;
5313 inputWindow.touchableAreaTop = frame.top + inset.top;
5314 inputWindow.touchableAreaRight = frame.right - inset.right;
5315 inputWindow.touchableAreaBottom = frame.bottom - inset.bottom;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005316 break;
5317 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005318 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005319 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07005320
Jeff Brown349703e2010-06-22 01:27:15 -07005321 // Send windows to native code.
5322 mInputManager.setInputWindows(mTempInputWindows.toNullTerminatedArray());
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005323
Jeff Brown349703e2010-06-22 01:27:15 -07005324 // Clear the list in preparation for the next round.
5325 // Also avoids keeping InputChannel objects referenced unnecessarily.
5326 mTempInputWindows.clear();
5327 }
5328
5329 /* Notifies that an app switch key (BACK / HOME) has just been pressed.
5330 * This essentially starts a .5 second timeout for the application to process
5331 * subsequent input events while waiting for the app switch to occur. If it takes longer
5332 * than this, the pending events will be dropped.
5333 */
5334 public void notifyAppSwitchComing() {
5335 // TODO Not implemented yet. Should go in the native side.
5336 }
5337
5338 /* Provides an opportunity for the window manager policy to intercept early key
5339 * processing as soon as the key has been read from the device. */
5340 public int interceptKeyBeforeQueueing(int deviceId, int type, int scanCode,
5341 int keyCode, int policyFlags, int value, long whenNanos, boolean isScreenOn) {
5342 RawInputEvent event = new RawInputEvent();
5343 event.deviceId = deviceId;
5344 event.type = type;
5345 event.scancode = scanCode;
5346 event.keycode = keyCode;
5347 event.flags = policyFlags;
5348 event.value = value;
5349 event.when = whenNanos / 1000000;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005350
Jeff Brown349703e2010-06-22 01:27:15 -07005351 return mPolicy.interceptKeyTq(event, isScreenOn);
5352 }
5353
5354 /* Provides an opportunity for the window manager policy to process a key before
5355 * ordinary dispatch. */
5356 public boolean interceptKeyBeforeDispatching(InputChannel focus, int keyCode,
5357 int metaState, boolean down, int repeatCount, int policyFlags) {
5358 WindowState windowState = getWindowStateForInputChannel(focus);
5359 return mPolicy.interceptKeyTi(windowState, keyCode, metaState, down, repeatCount,
5360 policyFlags);
5361 }
5362
5363 /* Called when the current input focus changes.
5364 * Layer assignment is assumed to be complete by the time this is called.
5365 */
5366 public void setInputFocusLw(WindowState newWindow) {
5367 if (DEBUG_INPUT) {
5368 Slog.d(TAG, "Input focus has changed to " + newWindow);
5369 }
5370
5371 if (newWindow != mInputFocus) {
5372 if (newWindow != null && newWindow.canReceiveKeys()) {
5373 // If the new input focus is an error window or appears above the current
5374 // input focus, preempt any pending synchronous dispatch so that we can
5375 // start delivering events to the new input focus as soon as possible.
5376 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
5377 if (DEBUG_INPUT) {
5378 Slog.v(TAG, "New SYSTEM_ERROR window; resetting state");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005379 }
Jeff Brown349703e2010-06-22 01:27:15 -07005380 preemptInputDispatchLw();
5381 } else if (mInputFocus != null && newWindow.mLayer > mInputFocus.mLayer) {
5382 if (DEBUG_INPUT) {
5383 Slog.v(TAG, "Transferring focus to new window at higher layer: "
5384 + "old win layer=" + mInputFocus.mLayer
5385 + ", new win layer=" + newWindow.mLayer);
5386 }
5387 preemptInputDispatchLw();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005388 }
Jeff Brown349703e2010-06-22 01:27:15 -07005389
5390 // Displaying a window implicitly causes dispatching to be unpaused.
5391 // This is to protect against bugs if someone pauses dispatching but
5392 // forgets to resume.
5393 newWindow.mToken.paused = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005394 }
Jeff Brown349703e2010-06-22 01:27:15 -07005395
5396 mInputFocus = newWindow;
5397 updateInputWindowsLw();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005398 }
5399 }
5400
Jeff Brown349703e2010-06-22 01:27:15 -07005401 public void windowIsBecomingInvisibleLw(WindowState window) {
5402 // The window is becoming invisible. Preempt input dispatch in progress
5403 // so that the next window below can receive focus.
5404 if (window == mInputFocus) {
5405 mInputFocus = null;
5406 preemptInputDispatchLw();
5407 }
5408
5409 updateInputWindowsLw();
5410 }
5411
5412 /* Tells the dispatcher to stop waiting for its current synchronous event targets.
5413 * Essentially, just makes those dispatches asynchronous so a new dispatch cycle
5414 * can begin.
5415 */
5416 private void preemptInputDispatchLw() {
5417 mInputManager.preemptInputDispatch();
5418 }
5419
5420 public void setFocusedAppLw(AppWindowToken newApp) {
5421 // Focused app has changed.
5422 if (newApp == null) {
5423 mInputManager.setFocusedApplication(null);
5424 } else {
5425 mTempInputApplication.name = newApp.toString();
5426 mTempInputApplication.dispatchingTimeoutNanos =
5427 newApp.inputDispatchingTimeoutNanos;
5428 mTempInputApplication.token = newApp;
5429
5430 mInputManager.setFocusedApplication(mTempInputApplication);
5431 }
5432 }
5433
5434 public void windowIsBeingRemovedLw(WindowState window) {
5435 // Window is being removed.
5436 updateInputWindowsLw();
5437 }
5438
5439 public void pauseDispatchingLw(WindowToken window) {
5440 if (! window.paused) {
5441 if (DEBUG_INPUT) {
5442 Slog.v(TAG, "Pausing WindowToken " + window);
5443 }
5444
5445 window.paused = true;
5446 updateInputWindowsLw();
5447 }
5448 }
5449
5450 public void resumeDispatchingLw(WindowToken window) {
5451 if (window.paused) {
5452 if (DEBUG_INPUT) {
5453 Slog.v(TAG, "Resuming WindowToken " + window);
5454 }
5455
5456 window.paused = false;
5457 updateInputWindowsLw();
5458 }
5459 }
5460
5461 public void freezeInputDispatchingLw() {
5462 if (! mInputDispatchFrozen) {
5463 if (DEBUG_INPUT) {
5464 Slog.v(TAG, "Freezing input dispatching");
5465 }
5466
5467 mInputDispatchFrozen = true;
5468 updateInputDispatchModeLw();
5469 }
5470 }
5471
5472 public void thawInputDispatchingLw() {
5473 if (mInputDispatchFrozen) {
5474 if (DEBUG_INPUT) {
5475 Slog.v(TAG, "Thawing input dispatching");
5476 }
5477
5478 mInputDispatchFrozen = false;
5479 updateInputDispatchModeLw();
5480 }
5481 }
5482
5483 public void setEventDispatchingLw(boolean enabled) {
5484 if (mInputDispatchEnabled != enabled) {
5485 if (DEBUG_INPUT) {
5486 Slog.v(TAG, "Setting event dispatching to " + enabled);
5487 }
5488
5489 mInputDispatchEnabled = enabled;
5490 updateInputDispatchModeLw();
5491 }
5492 }
5493
5494 private void updateInputDispatchModeLw() {
5495 mInputManager.setInputDispatchMode(mInputDispatchEnabled, mInputDispatchFrozen);
5496 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005497 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498
5499 private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
Michael Chane96440f2009-05-06 10:27:36 -07005500 long curTime = SystemClock.uptimeMillis();
5501
Michael Chane10de972009-05-18 11:24:50 -07005502 if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
Michael Chane96440f2009-05-06 10:27:36 -07005503 if (mLastTouchEventType == eventType &&
5504 (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
5505 return;
5506 }
5507 mLastUserActivityCallTime = curTime;
5508 mLastTouchEventType = eventType;
5509 }
5510
5511 if (targetWin == null
5512 || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
5513 mPowerManager.userActivity(curTime, false, eventType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 }
5515 }
5516
5517 // tells if it's a cheek event or not -- this function is stateful
5518 private static final int EVENT_NONE = 0;
5519 private static final int EVENT_UNKNOWN = 0;
5520 private static final int EVENT_CHEEK = 0;
5521 private static final int EVENT_IGNORE_DURATION = 300; // ms
5522 private static final float CHEEK_THRESHOLD = 0.6f;
5523 private int mEventState = EVENT_NONE;
5524 private float mEventSize;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526 private int eventType(MotionEvent ev) {
5527 float size = ev.getSize();
5528 switch (ev.getAction()) {
5529 case MotionEvent.ACTION_DOWN:
5530 mEventSize = size;
5531 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT;
5532 case MotionEvent.ACTION_UP:
5533 if (size > mEventSize) mEventSize = size;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005534 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005535 case MotionEvent.ACTION_MOVE:
5536 final int N = ev.getHistorySize();
5537 if (size > mEventSize) mEventSize = size;
5538 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5539 for (int i=0; i<N; i++) {
5540 size = ev.getHistoricalSize(i);
5541 if (size > mEventSize) mEventSize = size;
5542 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5543 }
5544 if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) {
5545 return TOUCH_EVENT;
5546 } else {
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005547 return LONG_TOUCH_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548 }
5549 default:
5550 // not good
5551 return OTHER_EVENT;
5552 }
5553 }
Jeff Brown349703e2010-06-22 01:27:15 -07005554
5555 private boolean mFatTouch; // remove me together with dispatchPointer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005556
5557 /**
5558 * @return Returns true if event was dispatched, false if it was dropped for any reason
5559 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005560 private int dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005561 if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005562 "dispatchPointer " + ev);
5563
Michael Chan53071d62009-05-13 17:29:48 -07005564 if (MEASURE_LATENCY) {
5565 lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
5566 }
5567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005568 Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005569 ev, true, false, pid, uid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005570
Michael Chan53071d62009-05-13 17:29:48 -07005571 if (MEASURE_LATENCY) {
5572 lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
5573 }
5574
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005575 int action = ev.getAction();
Romain Guy06882f82009-06-10 13:36:04 -07005576
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005577 if (action == MotionEvent.ACTION_UP) {
5578 // let go of our target
5579 mKeyWaiter.mMotionTarget = null;
5580 mPowerManager.logPointerUpEvent();
5581 } else if (action == MotionEvent.ACTION_DOWN) {
5582 mPowerManager.logPointerDownEvent();
5583 }
5584
5585 if (targetObj == null) {
5586 // In this case we are either dropping the event, or have received
5587 // a move or up without a down. It is common to receive move
5588 // events in such a way, since this means the user is moving the
5589 // pointer without actually pressing down. All other cases should
5590 // be atypical, so let's log them.
Michael Chane96440f2009-05-06 10:27:36 -07005591 if (action != MotionEvent.ACTION_MOVE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005592 Slog.w(TAG, "No window to dispatch pointer action " + ev.getAction());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005593 }
Dianne Hackborn6adba242009-11-10 11:10:09 -08005594 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005595 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005597 if (qev != null) {
5598 mQueue.recycleEvent(qev);
5599 }
5600 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005601 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005602 }
5603 if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborn6adba242009-11-10 11:10:09 -08005604 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005605 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005606 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005607 if (qev != null) {
5608 mQueue.recycleEvent(qev);
5609 }
5610 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005611 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005612 }
Romain Guy06882f82009-06-10 13:36:04 -07005613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005614 WindowState target = (WindowState)targetObj;
Romain Guy06882f82009-06-10 13:36:04 -07005615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 final long eventTime = ev.getEventTime();
Michael Chan53071d62009-05-13 17:29:48 -07005617 final long eventTimeNano = ev.getEventTimeNano();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005618
Joe Onorato8a9b2202010-02-26 18:56:32 -08005619 //Slog.i(TAG, "Sending " + ev + " to " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620
5621 if (uid != 0 && uid != target.mSession.mUid) {
5622 if (mContext.checkPermission(
5623 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5624 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005625 Slog.w(TAG, "Permission denied: injecting pointer event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005626 + pid + " uid " + uid + " to window " + target
5627 + " owned by uid " + target.mSession.mUid);
5628 if (qev != null) {
5629 mQueue.recycleEvent(qev);
5630 }
5631 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005632 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005633 }
5634 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005635
Michael Chan53071d62009-05-13 17:29:48 -07005636 if (MEASURE_LATENCY) {
5637 lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano);
5638 }
5639
Romain Guy06882f82009-06-10 13:36:04 -07005640 if ((target.mAttrs.flags &
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005641 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
5642 //target wants to ignore fat touch events
5643 boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev);
5644 //explicit flag to return without processing event further
5645 boolean returnFlag = false;
5646 if((action == MotionEvent.ACTION_DOWN)) {
5647 mFatTouch = false;
5648 if(cheekPress) {
5649 mFatTouch = true;
5650 returnFlag = true;
5651 }
5652 } else {
5653 if(action == MotionEvent.ACTION_UP) {
5654 if(mFatTouch) {
5655 //earlier even was invalid doesnt matter if current up is cheekpress or not
5656 mFatTouch = false;
5657 returnFlag = true;
5658 } else if(cheekPress) {
5659 //cancel the earlier event
5660 ev.setAction(MotionEvent.ACTION_CANCEL);
5661 action = MotionEvent.ACTION_CANCEL;
5662 }
5663 } else if(action == MotionEvent.ACTION_MOVE) {
5664 if(mFatTouch) {
5665 //two cases here
5666 //an invalid down followed by 0 or moves(valid or invalid)
Romain Guy06882f82009-06-10 13:36:04 -07005667 //a valid down, invalid move, more moves. want to ignore till up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005668 returnFlag = true;
5669 } else if(cheekPress) {
5670 //valid down followed by invalid moves
5671 //an invalid move have to cancel earlier action
5672 ev.setAction(MotionEvent.ACTION_CANCEL);
5673 action = MotionEvent.ACTION_CANCEL;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005674 if (DEBUG_INPUT) Slog.v(TAG, "Sending cancel for invalid ACTION_MOVE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005675 //note that the subsequent invalid moves will not get here
5676 mFatTouch = true;
5677 }
5678 }
5679 } //else if action
5680 if(returnFlag) {
5681 //recycle que, ev
5682 if (qev != null) {
5683 mQueue.recycleEvent(qev);
5684 }
5685 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005686 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005687 }
5688 } //end if target
Michael Chane96440f2009-05-06 10:27:36 -07005689
Michael Chan9f028e62009-08-04 17:37:46 -07005690 // Enable this for testing the "right" value
5691 if (false && action == MotionEvent.ACTION_DOWN) {
Michael Chane96440f2009-05-06 10:27:36 -07005692 int max_events_per_sec = 35;
5693 try {
5694 max_events_per_sec = Integer.parseInt(SystemProperties
5695 .get("windowsmgr.max_events_per_sec"));
5696 if (max_events_per_sec < 1) {
5697 max_events_per_sec = 35;
5698 }
5699 } catch (NumberFormatException e) {
5700 }
5701 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
5702 }
5703
5704 /*
5705 * Throttle events to minimize CPU usage when there's a flood of events
5706 * e.g. constant contact with the screen
5707 */
5708 if (action == MotionEvent.ACTION_MOVE) {
5709 long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents;
5710 long now = SystemClock.uptimeMillis();
5711 if (now < nextEventTime) {
5712 try {
5713 Thread.sleep(nextEventTime - now);
5714 } catch (InterruptedException e) {
5715 }
5716 mLastTouchEventTime = nextEventTime;
5717 } else {
5718 mLastTouchEventTime = now;
5719 }
5720 }
5721
Michael Chan53071d62009-05-13 17:29:48 -07005722 if (MEASURE_LATENCY) {
5723 lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano);
5724 }
5725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005726 synchronized(mWindowMap) {
Dianne Hackborn6adba242009-11-10 11:10:09 -08005727 if (!target.isVisibleLw()) {
5728 // During this motion dispatch, the target window has become
5729 // invisible.
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005730 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), false);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005731 if (qev != null) {
5732 mQueue.recycleEvent(qev);
5733 }
5734 ev.recycle();
5735 return INJECT_SUCCEEDED;
5736 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005738 if (qev != null && action == MotionEvent.ACTION_MOVE) {
5739 mKeyWaiter.bindTargetWindowLocked(target,
5740 KeyWaiter.RETURN_PENDING_POINTER, qev);
5741 ev = null;
5742 } else {
5743 if (action == MotionEvent.ACTION_DOWN) {
5744 WindowState out = mKeyWaiter.mOutsideTouchTargets;
5745 if (out != null) {
5746 MotionEvent oev = MotionEvent.obtain(ev);
5747 oev.setAction(MotionEvent.ACTION_OUTSIDE);
5748 do {
5749 final Rect frame = out.mFrame;
5750 oev.offsetLocation(-(float)frame.left, -(float)frame.top);
5751 try {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005752 out.mClient.dispatchPointer(oev, eventTime, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005753 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005754 Slog.i(TAG, "WINDOW DIED during outside motion dispatch: " + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005755 }
5756 oev.offsetLocation((float)frame.left, (float)frame.top);
5757 out = out.mNextOutsideTouch;
5758 } while (out != null);
5759 mKeyWaiter.mOutsideTouchTargets = null;
5760 }
5761 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005762
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005763 dispatchPointerElsewhereLocked(target, null, ev, ev.getEventTime(), false);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005764
Dianne Hackborn6adba242009-11-10 11:10:09 -08005765 final Rect frame = target.mFrame;
5766 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
5767 mKeyWaiter.bindTargetWindowLocked(target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005768 }
5769 }
Romain Guy06882f82009-06-10 13:36:04 -07005770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005771 // finally offset the event to the target's coordinate system and
5772 // dispatch the event.
5773 try {
5774 if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005775 Slog.v(TAG, "Delivering pointer " + qev + " to " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005776 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005777
Michael Chan53071d62009-05-13 17:29:48 -07005778 if (MEASURE_LATENCY) {
5779 lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
5780 }
5781
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005782 target.mClient.dispatchPointer(ev, eventTime, true);
Michael Chan53071d62009-05-13 17:29:48 -07005783
5784 if (MEASURE_LATENCY) {
5785 lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
5786 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07005787 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005788 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005789 Slog.i(TAG, "WINDOW DIED during motion dispatch: " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005790 mKeyWaiter.mMotionTarget = null;
5791 try {
5792 removeWindow(target.mSession, target.mClient);
5793 } catch (java.util.NoSuchElementException ex) {
5794 // This will happen if the window has already been
5795 // removed.
5796 }
5797 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07005798 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005799 }
Romain Guy06882f82009-06-10 13:36:04 -07005800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005801 /**
5802 * @return Returns true if event was dispatched, false if it was dropped for any reason
5803 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005804 private int dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005805 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">");
Romain Guy06882f82009-06-10 13:36:04 -07005807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005808 Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005809 ev, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005810 if (focusObj == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005811 Slog.w(TAG, "No focus window, dropping trackball: " + ev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005812 if (qev != null) {
5813 mQueue.recycleEvent(qev);
5814 }
5815 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005816 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005817 }
5818 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5819 if (qev != null) {
5820 mQueue.recycleEvent(qev);
5821 }
5822 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005823 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005824 }
Romain Guy06882f82009-06-10 13:36:04 -07005825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005826 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07005827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 if (uid != 0 && uid != focus.mSession.mUid) {
5829 if (mContext.checkPermission(
5830 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5831 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005832 Slog.w(TAG, "Permission denied: injecting key event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005833 + pid + " uid " + uid + " to window " + focus
5834 + " owned by uid " + focus.mSession.mUid);
5835 if (qev != null) {
5836 mQueue.recycleEvent(qev);
5837 }
5838 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005839 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 }
5841 }
Romain Guy06882f82009-06-10 13:36:04 -07005842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 final long eventTime = ev.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07005844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005845 synchronized(mWindowMap) {
5846 if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) {
5847 mKeyWaiter.bindTargetWindowLocked(focus,
5848 KeyWaiter.RETURN_PENDING_TRACKBALL, qev);
5849 // We don't deliver movement events to the client, we hold
5850 // them and wait for them to call back.
5851 ev = null;
5852 } else {
5853 mKeyWaiter.bindTargetWindowLocked(focus);
5854 }
5855 }
Romain Guy06882f82009-06-10 13:36:04 -07005856
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005857 try {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005858 focus.mClient.dispatchTrackball(ev, eventTime, true);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005859 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005861 Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 try {
5863 removeWindow(focus.mSession, focus.mClient);
5864 } catch (java.util.NoSuchElementException ex) {
5865 // This will happen if the window has already been
5866 // removed.
5867 }
5868 }
Romain Guy06882f82009-06-10 13:36:04 -07005869
Dianne Hackborncfaef692009-06-15 14:24:44 -07005870 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005871 }
Romain Guy06882f82009-06-10 13:36:04 -07005872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005873 /**
5874 * @return Returns true if event was dispatched, false if it was dropped for any reason
5875 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005876 private int dispatchKey(KeyEvent event, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005877 if (DEBUG_INPUT) Slog.v(TAG, "Dispatch key: " + event);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878
5879 Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005880 null, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 if (focusObj == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005882 Slog.w(TAG, "No focus window, dropping: " + event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005883 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005884 }
5885 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005886 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005887 }
Romain Guy06882f82009-06-10 13:36:04 -07005888
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07005889 // Okay we have finished waiting for the last event to be processed.
5890 // First off, if this is a repeat event, check to see if there is
5891 // a corresponding up event in the queue. If there is, we will
5892 // just drop the repeat, because it makes no sense to repeat after
5893 // the user has released a key. (This is especially important for
5894 // long presses.)
5895 if (event.getRepeatCount() > 0 && mQueue.hasKeyUpEvent(event)) {
5896 return INJECT_SUCCEEDED;
5897 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005899 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07005900
Joe Onorato8a9b2202010-02-26 18:56:32 -08005901 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005902 TAG, "Dispatching to " + focus + ": " + event);
5903
5904 if (uid != 0 && uid != focus.mSession.mUid) {
5905 if (mContext.checkPermission(
5906 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5907 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005908 Slog.w(TAG, "Permission denied: injecting key event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005909 + pid + " uid " + uid + " to window " + focus
5910 + " owned by uid " + focus.mSession.mUid);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005911 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005912 }
5913 }
Romain Guy06882f82009-06-10 13:36:04 -07005914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 synchronized(mWindowMap) {
5916 mKeyWaiter.bindTargetWindowLocked(focus);
5917 }
5918
5919 // NOSHIP extra state logging
5920 mKeyWaiter.recordDispatchState(event, focus);
5921 // END NOSHIP
Romain Guy06882f82009-06-10 13:36:04 -07005922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005923 try {
5924 if (DEBUG_INPUT || DEBUG_FOCUS) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005925 Slog.v(TAG, "Delivering key " + event.getKeyCode()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005926 + " to " + focus);
5927 }
5928 focus.mClient.dispatchKey(event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005929 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005930 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005931 Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005932 try {
5933 removeWindow(focus.mSession, focus.mClient);
5934 } catch (java.util.NoSuchElementException ex) {
5935 // This will happen if the window has already been
5936 // removed.
5937 }
5938 }
Romain Guy06882f82009-06-10 13:36:04 -07005939
Dianne Hackborncfaef692009-06-15 14:24:44 -07005940 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 }
Romain Guy06882f82009-06-10 13:36:04 -07005942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943 public void pauseKeyDispatching(IBinder _token) {
5944 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5945 "pauseKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005946 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 }
5948
5949 synchronized (mWindowMap) {
5950 WindowToken token = mTokenMap.get(_token);
5951 if (token != null) {
Jeff Brown349703e2010-06-22 01:27:15 -07005952 if (ENABLE_NATIVE_INPUT_DISPATCH) {
5953 mInputMonitor.pauseDispatchingLw(token);
5954 } else {
5955 mKeyWaiter.pauseDispatchingLocked(token);
5956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957 }
5958 }
5959 }
5960
5961 public void resumeKeyDispatching(IBinder _token) {
5962 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5963 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005964 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005965 }
5966
5967 synchronized (mWindowMap) {
5968 WindowToken token = mTokenMap.get(_token);
5969 if (token != null) {
Jeff Brown349703e2010-06-22 01:27:15 -07005970 if (ENABLE_NATIVE_INPUT_DISPATCH) {
5971 mInputMonitor.resumeDispatchingLw(token);
5972 } else {
5973 mKeyWaiter.resumeDispatchingLocked(token);
5974 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975 }
5976 }
5977 }
5978
5979 public void setEventDispatching(boolean enabled) {
5980 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5981 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005982 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005983 }
5984
5985 synchronized (mWindowMap) {
Jeff Brown349703e2010-06-22 01:27:15 -07005986 if (ENABLE_NATIVE_INPUT_DISPATCH) {
5987 mInputMonitor.setEventDispatchingLw(enabled);
5988 } else {
5989 mKeyWaiter.setEventDispatchingLocked(enabled);
5990 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005991 }
5992 }
Romain Guy06882f82009-06-10 13:36:04 -07005993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005994 /**
5995 * Injects a keystroke event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005996 *
5997 * @param ev A motion event describing the keystroke action. (Be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005998 * {@link SystemClock#uptimeMillis()} as the timebase.)
5999 * @param sync If true, wait for the event to be completed before returning to the caller.
6000 * @return Returns true if event was dispatched, false if it was dropped for any reason
6001 */
6002 public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
6003 long downTime = ev.getDownTime();
6004 long eventTime = ev.getEventTime();
6005
6006 int action = ev.getAction();
6007 int code = ev.getKeyCode();
6008 int repeatCount = ev.getRepeatCount();
6009 int metaState = ev.getMetaState();
6010 int deviceId = ev.getDeviceId();
6011 int scancode = ev.getScanCode();
6012
6013 if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
6014 if (downTime == 0) downTime = eventTime;
6015
6016 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
The Android Open Source Project10592532009-03-18 17:39:46 -07006017 deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006018
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006019 final int pid = Binder.getCallingPid();
6020 final int uid = Binder.getCallingUid();
6021 final long ident = Binder.clearCallingIdentity();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006022
6023 final int result;
6024 if (ENABLE_NATIVE_INPUT_DISPATCH) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07006025 result = mInputManager.injectKeyEvent(newEvent, InputQueue.INPUT_EVENT_NATURE_KEY,
6026 pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006027 } else {
6028 result = dispatchKey(newEvent, pid, uid);
6029 if (sync) {
6030 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
6031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006033
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006034 Binder.restoreCallingIdentity(ident);
Jeff Brown7fbdc842010-06-17 20:52:56 -07006035 return reportInjectionResult(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006036 }
6037
6038 /**
6039 * Inject a pointer (touch) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07006040 *
6041 * @param ev A motion event describing the pointer (touch) action. (As noted in
6042 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006043 * {@link SystemClock#uptimeMillis()} as the timebase.)
6044 * @param sync If true, wait for the event to be completed before returning to the caller.
6045 * @return Returns true if event was dispatched, false if it was dropped for any reason
6046 */
6047 public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006048 final int pid = Binder.getCallingPid();
6049 final int uid = Binder.getCallingUid();
6050 final long ident = Binder.clearCallingIdentity();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006051
6052 final int result;
6053 if (ENABLE_NATIVE_INPUT_DISPATCH) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07006054 result = mInputManager.injectMotionEvent(ev, InputQueue.INPUT_EVENT_NATURE_TOUCH,
6055 pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006056 } else {
6057 result = dispatchPointer(null, ev, pid, uid);
6058 if (sync) {
6059 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
6060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006061 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006062
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006063 Binder.restoreCallingIdentity(ident);
Jeff Brown7fbdc842010-06-17 20:52:56 -07006064 return reportInjectionResult(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006065 }
Romain Guy06882f82009-06-10 13:36:04 -07006066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006067 /**
6068 * Inject a trackball (navigation device) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07006069 *
6070 * @param ev A motion event describing the trackball action. (As noted in
6071 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006072 * {@link SystemClock#uptimeMillis()} as the timebase.)
6073 * @param sync If true, wait for the event to be completed before returning to the caller.
6074 * @return Returns true if event was dispatched, false if it was dropped for any reason
6075 */
6076 public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006077 final int pid = Binder.getCallingPid();
6078 final int uid = Binder.getCallingUid();
6079 final long ident = Binder.clearCallingIdentity();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006080
6081 final int result;
6082 if (ENABLE_NATIVE_INPUT_DISPATCH) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07006083 result = mInputManager.injectMotionEvent(ev, InputQueue.INPUT_EVENT_NATURE_TRACKBALL,
6084 pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006085 } else {
6086 result = dispatchTrackball(null, ev, pid, uid);
6087 if (sync) {
6088 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
6089 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006091
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006092 Binder.restoreCallingIdentity(ident);
Jeff Brown7fbdc842010-06-17 20:52:56 -07006093 return reportInjectionResult(result);
6094 }
6095
6096 private boolean reportInjectionResult(int result) {
6097 if (ENABLE_NATIVE_INPUT_DISPATCH) {
6098 switch (result) {
6099 case InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED:
6100 Slog.w(TAG, "Input event injection permission denied.");
6101 throw new SecurityException(
6102 "Injecting to another application requires INJECT_EVENTS permission");
6103 case InputManager.INPUT_EVENT_INJECTION_SUCCEEDED:
6104 Slog.v(TAG, "Input event injection succeeded.");
6105 return true;
6106 case InputManager.INPUT_EVENT_INJECTION_TIMED_OUT:
6107 Slog.w(TAG, "Input event injection timed out.");
6108 return false;
6109 case InputManager.INPUT_EVENT_INJECTION_FAILED:
6110 default:
6111 Slog.w(TAG, "Input event injection failed.");
6112 return false;
6113 }
6114 } else {
6115 switch (result) {
6116 case INJECT_NO_PERMISSION:
6117 throw new SecurityException(
6118 "Injecting to another application requires INJECT_EVENTS permission");
6119 case INJECT_SUCCEEDED:
6120 return true;
6121 }
6122 return false;
Dianne Hackborncfaef692009-06-15 14:24:44 -07006123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006124 }
Romain Guy06882f82009-06-10 13:36:04 -07006125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006126 private WindowState getFocusedWindow() {
6127 synchronized (mWindowMap) {
6128 return getFocusedWindowLocked();
6129 }
6130 }
6131
6132 private WindowState getFocusedWindowLocked() {
6133 return mCurrentFocus;
6134 }
Romain Guy06882f82009-06-10 13:36:04 -07006135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006136 /**
6137 * This class holds the state for dispatching key events. This state
6138 * is protected by the KeyWaiter instance, NOT by the window lock. You
6139 * can be holding the main window lock while acquire the KeyWaiter lock,
6140 * but not the other way around.
6141 */
6142 final class KeyWaiter {
6143 // NOSHIP debugging
6144 public class DispatchState {
6145 private KeyEvent event;
6146 private WindowState focus;
6147 private long time;
6148 private WindowState lastWin;
6149 private IBinder lastBinder;
6150 private boolean finished;
6151 private boolean gotFirstWindow;
6152 private boolean eventDispatching;
6153 private long timeToSwitch;
6154 private boolean wasFrozen;
6155 private boolean focusPaused;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006156 private WindowState curFocus;
Romain Guy06882f82009-06-10 13:36:04 -07006157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006158 DispatchState(KeyEvent theEvent, WindowState theFocus) {
6159 focus = theFocus;
6160 event = theEvent;
6161 time = System.currentTimeMillis();
6162 // snapshot KeyWaiter state
6163 lastWin = mLastWin;
6164 lastBinder = mLastBinder;
6165 finished = mFinished;
6166 gotFirstWindow = mGotFirstWindow;
6167 eventDispatching = mEventDispatching;
6168 timeToSwitch = mTimeToSwitch;
6169 wasFrozen = mWasFrozen;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006170 curFocus = mCurrentFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006171 // cache the paused state at ctor time as well
6172 if (theFocus == null || theFocus.mToken == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006173 focusPaused = false;
6174 } else {
6175 focusPaused = theFocus.mToken.paused;
6176 }
6177 }
Romain Guy06882f82009-06-10 13:36:04 -07006178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006179 public String toString() {
6180 return "{{" + event + " to " + focus + " @ " + time
6181 + " lw=" + lastWin + " lb=" + lastBinder
6182 + " fin=" + finished + " gfw=" + gotFirstWindow
6183 + " ed=" + eventDispatching + " tts=" + timeToSwitch
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006184 + " wf=" + wasFrozen + " fp=" + focusPaused
Christopher Tate46d45252010-02-09 15:48:57 -08006185 + " mcf=" + curFocus + "}}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006186 }
6187 };
6188 private DispatchState mDispatchState = null;
6189 public void recordDispatchState(KeyEvent theEvent, WindowState theFocus) {
6190 mDispatchState = new DispatchState(theEvent, theFocus);
6191 }
6192 // END NOSHIP
6193
6194 public static final int RETURN_NOTHING = 0;
6195 public static final int RETURN_PENDING_POINTER = 1;
6196 public static final int RETURN_PENDING_TRACKBALL = 2;
Romain Guy06882f82009-06-10 13:36:04 -07006197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006198 final Object SKIP_TARGET_TOKEN = new Object();
6199 final Object CONSUMED_EVENT_TOKEN = new Object();
Romain Guy06882f82009-06-10 13:36:04 -07006200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006201 private WindowState mLastWin = null;
6202 private IBinder mLastBinder = null;
6203 private boolean mFinished = true;
6204 private boolean mGotFirstWindow = false;
6205 private boolean mEventDispatching = true;
6206 private long mTimeToSwitch = 0;
6207 /* package */ boolean mWasFrozen = false;
Romain Guy06882f82009-06-10 13:36:04 -07006208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006209 // Target of Motion events
6210 WindowState mMotionTarget;
Romain Guy06882f82009-06-10 13:36:04 -07006211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006212 // Windows above the target who would like to receive an "outside"
6213 // touch event for any down events outside of them.
6214 WindowState mOutsideTouchTargets;
6215
6216 /**
6217 * Wait for the last event dispatch to complete, then find the next
6218 * target that should receive the given event and wait for that one
6219 * to be ready to receive it.
6220 */
6221 Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev,
6222 MotionEvent nextMotion, boolean isPointerEvent,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006223 boolean failIfTimeout, int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006224 long startTime = SystemClock.uptimeMillis();
6225 long keyDispatchingTimeout = 5 * 1000;
6226 long waitedFor = 0;
6227
6228 while (true) {
6229 // Figure out which window we care about. It is either the
6230 // last window we are waiting to have process the event or,
6231 // if none, then the next window we think the event should go
6232 // to. Note: we retrieve mLastWin outside of the lock, so
6233 // it may change before we lock. Thus we must check it again.
6234 WindowState targetWin = mLastWin;
6235 boolean targetIsNew = targetWin == null;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006236 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006237 TAG, "waitForLastKey: mFinished=" + mFinished +
6238 ", mLastWin=" + mLastWin);
6239 if (targetIsNew) {
6240 Object target = findTargetWindow(nextKey, qev, nextMotion,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006241 isPointerEvent, callingPid, callingUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006242 if (target == SKIP_TARGET_TOKEN) {
6243 // The user has pressed a special key, and we are
6244 // dropping all pending events before it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006245 if (DEBUG_INPUT) Slog.v(TAG, "Skipping: " + nextKey
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006246 + " " + nextMotion);
6247 return null;
6248 }
6249 if (target == CONSUMED_EVENT_TOKEN) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006250 if (DEBUG_INPUT) Slog.v(TAG, "Consumed: " + nextKey
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006251 + " " + nextMotion);
6252 return target;
6253 }
6254 targetWin = (WindowState)target;
6255 }
Romain Guy06882f82009-06-10 13:36:04 -07006256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006257 AppWindowToken targetApp = null;
Romain Guy06882f82009-06-10 13:36:04 -07006258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006259 // Now: is it okay to send the next event to this window?
6260 synchronized (this) {
6261 // First: did we come here based on the last window not
6262 // being null, but it changed by the time we got here?
6263 // If so, try again.
6264 if (!targetIsNew && mLastWin == null) {
6265 continue;
6266 }
Romain Guy06882f82009-06-10 13:36:04 -07006267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006268 // We never dispatch events if not finished with the
6269 // last one, or the display is frozen.
6270 if (mFinished && !mDisplayFrozen) {
6271 // If event dispatching is disabled, then we
6272 // just consume the events.
6273 if (!mEventDispatching) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006274 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006275 "Skipping event; dispatching disabled: "
6276 + nextKey + " " + nextMotion);
6277 return null;
6278 }
6279 if (targetWin != null) {
6280 // If this is a new target, and that target is not
6281 // paused or unresponsive, then all looks good to
6282 // handle the event.
6283 if (targetIsNew && !targetWin.mToken.paused) {
6284 return targetWin;
6285 }
Romain Guy06882f82009-06-10 13:36:04 -07006286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006287 // If we didn't find a target window, and there is no
6288 // focused app window, then just eat the events.
6289 } else if (mFocusedApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006290 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006291 "Skipping event; no focused app: "
6292 + nextKey + " " + nextMotion);
6293 return null;
6294 }
6295 }
Romain Guy06882f82009-06-10 13:36:04 -07006296
Joe Onorato8a9b2202010-02-26 18:56:32 -08006297 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 TAG, "Waiting for last key in " + mLastBinder
6299 + " target=" + targetWin
6300 + " mFinished=" + mFinished
6301 + " mDisplayFrozen=" + mDisplayFrozen
6302 + " targetIsNew=" + targetIsNew
6303 + " paused="
6304 + (targetWin != null ? targetWin.mToken.paused : false)
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006305 + " mFocusedApp=" + mFocusedApp
6306 + " mCurrentFocus=" + mCurrentFocus);
Romain Guy06882f82009-06-10 13:36:04 -07006307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006308 targetApp = targetWin != null
6309 ? targetWin.mAppToken : mFocusedApp;
Romain Guy06882f82009-06-10 13:36:04 -07006310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006311 long curTimeout = keyDispatchingTimeout;
6312 if (mTimeToSwitch != 0) {
6313 long now = SystemClock.uptimeMillis();
6314 if (mTimeToSwitch <= now) {
6315 // If an app switch key has been pressed, and we have
6316 // waited too long for the current app to finish
6317 // processing keys, then wait no more!
Christopher Tate136b1f92010-02-11 17:51:24 -08006318 doFinishedKeyLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006319 continue;
6320 }
6321 long switchTimeout = mTimeToSwitch - now;
6322 if (curTimeout > switchTimeout) {
6323 curTimeout = switchTimeout;
6324 }
6325 }
Romain Guy06882f82009-06-10 13:36:04 -07006326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 try {
6328 // after that continue
6329 // processing keys, so we don't get stuck.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006330 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 TAG, "Waiting for key dispatch: " + curTimeout);
6332 wait(curTimeout);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006333 if (DEBUG_INPUT) Slog.v(TAG, "Finished waiting @"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 + SystemClock.uptimeMillis() + " startTime="
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006335 + startTime + " switchTime=" + mTimeToSwitch
6336 + " target=" + targetWin + " mLW=" + mLastWin
6337 + " mLB=" + mLastBinder + " fin=" + mFinished
6338 + " mCurrentFocus=" + mCurrentFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006339 } catch (InterruptedException e) {
6340 }
6341 }
6342
6343 // If we were frozen during configuration change, restart the
6344 // timeout checks from now; otherwise look at whether we timed
6345 // out before awakening.
6346 if (mWasFrozen) {
6347 waitedFor = 0;
6348 mWasFrozen = false;
6349 } else {
6350 waitedFor = SystemClock.uptimeMillis() - startTime;
6351 }
6352
6353 if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) {
6354 IApplicationToken at = null;
6355 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006356 Slog.w(TAG, "Key dispatching timed out sending to " +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006357 (targetWin != null ? targetWin.mAttrs.getTitle()
Ken Shirriff8200b202010-02-04 13:34:37 -08006358 : "<null>: no window ready for key dispatch"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006359 // NOSHIP debugging
Joe Onorato8a9b2202010-02-26 18:56:32 -08006360 Slog.w(TAG, "Previous dispatch state: " + mDispatchState);
6361 Slog.w(TAG, "Current dispatch state: " +
Ken Shirriff8200b202010-02-04 13:34:37 -08006362 new DispatchState(nextKey, targetWin));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 // END NOSHIP
6364 //dump();
6365 if (targetWin != null) {
6366 at = targetWin.getAppToken();
6367 } else if (targetApp != null) {
6368 at = targetApp.appToken;
6369 }
6370 }
6371
6372 boolean abort = true;
6373 if (at != null) {
6374 try {
6375 long timeout = at.getKeyDispatchingTimeout();
6376 if (timeout > waitedFor) {
6377 // we did not wait the proper amount of time for this application.
6378 // set the timeout to be the real timeout and wait again.
6379 keyDispatchingTimeout = timeout - waitedFor;
6380 continue;
6381 } else {
6382 abort = at.keyDispatchingTimedOut();
6383 }
6384 } catch (RemoteException ex) {
6385 }
6386 }
6387
6388 synchronized (this) {
6389 if (abort && (mLastWin == targetWin || targetWin == null)) {
6390 mFinished = true;
Romain Guy06882f82009-06-10 13:36:04 -07006391 if (mLastWin != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006392 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006393 "Window " + mLastWin +
6394 " timed out on key input");
6395 if (mLastWin.mToken.paused) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006396 Slog.w(TAG, "Un-pausing dispatching to this window");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006397 mLastWin.mToken.paused = false;
6398 }
6399 }
6400 if (mMotionTarget == targetWin) {
6401 mMotionTarget = null;
6402 }
6403 mLastWin = null;
6404 mLastBinder = null;
6405 if (failIfTimeout || targetWin == null) {
6406 return null;
6407 }
6408 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006409 Slog.w(TAG, "Continuing to wait for key to be dispatched");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006410 startTime = SystemClock.uptimeMillis();
6411 }
6412 }
6413 }
6414 }
6415 }
Romain Guy06882f82009-06-10 13:36:04 -07006416
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006417 Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006418 MotionEvent nextMotion, boolean isPointerEvent,
6419 int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006420 mOutsideTouchTargets = null;
Romain Guy06882f82009-06-10 13:36:04 -07006421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006422 if (nextKey != null) {
6423 // Find the target window for a normal key event.
6424 final int keycode = nextKey.getKeyCode();
6425 final int repeatCount = nextKey.getRepeatCount();
6426 final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP;
6427 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006429 if (!dispatch) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006430 if (callingUid == 0 ||
6431 mContext.checkPermission(
6432 android.Manifest.permission.INJECT_EVENTS,
6433 callingPid, callingUid)
6434 == PackageManager.PERMISSION_GRANTED) {
6435 mPolicy.interceptKeyTi(null, keycode,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07006436 nextKey.getMetaState(), down, repeatCount,
6437 nextKey.getFlags());
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006438 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006439 Slog.w(TAG, "Event timeout during app switch: dropping "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 + nextKey);
6441 return SKIP_TARGET_TOKEN;
6442 }
Romain Guy06882f82009-06-10 13:36:04 -07006443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006444 // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")");
Romain Guy06882f82009-06-10 13:36:04 -07006445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006446 WindowState focus = null;
6447 synchronized(mWindowMap) {
6448 focus = getFocusedWindowLocked();
6449 }
Romain Guy06882f82009-06-10 13:36:04 -07006450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006451 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
Romain Guy06882f82009-06-10 13:36:04 -07006452
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006453 if (callingUid == 0 ||
6454 (focus != null && callingUid == focus.mSession.mUid) ||
6455 mContext.checkPermission(
6456 android.Manifest.permission.INJECT_EVENTS,
6457 callingPid, callingUid)
6458 == PackageManager.PERMISSION_GRANTED) {
6459 if (mPolicy.interceptKeyTi(focus,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006460 keycode, nextKey.getMetaState(), down, repeatCount,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07006461 nextKey.getFlags())) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006462 return CONSUMED_EVENT_TOKEN;
6463 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006464 }
Romain Guy06882f82009-06-10 13:36:04 -07006465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006466 return focus;
Romain Guy06882f82009-06-10 13:36:04 -07006467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006468 } else if (!isPointerEvent) {
6469 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1);
6470 if (!dispatch) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006471 Slog.w(TAG, "Event timeout during app switch: dropping trackball "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006472 + nextMotion);
6473 return SKIP_TARGET_TOKEN;
6474 }
Romain Guy06882f82009-06-10 13:36:04 -07006475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006476 WindowState focus = null;
6477 synchronized(mWindowMap) {
6478 focus = getFocusedWindowLocked();
6479 }
Romain Guy06882f82009-06-10 13:36:04 -07006480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006481 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
6482 return focus;
6483 }
Romain Guy06882f82009-06-10 13:36:04 -07006484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006485 if (nextMotion == null) {
6486 return SKIP_TARGET_TOKEN;
6487 }
Romain Guy06882f82009-06-10 13:36:04 -07006488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006489 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(
6490 KeyEvent.KEYCODE_UNKNOWN);
6491 if (!dispatch) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006492 Slog.w(TAG, "Event timeout during app switch: dropping pointer "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 + nextMotion);
6494 return SKIP_TARGET_TOKEN;
6495 }
Romain Guy06882f82009-06-10 13:36:04 -07006496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006497 // Find the target window for a pointer event.
6498 int action = nextMotion.getAction();
6499 final float xf = nextMotion.getX();
6500 final float yf = nextMotion.getY();
6501 final long eventTime = nextMotion.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07006502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006503 final boolean screenWasOff = qev != null
6504 && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07006505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006506 WindowState target = null;
Romain Guy06882f82009-06-10 13:36:04 -07006507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006508 synchronized(mWindowMap) {
6509 synchronized (this) {
6510 if (action == MotionEvent.ACTION_DOWN) {
6511 if (mMotionTarget != null) {
6512 // this is weird, we got a pen down, but we thought it was
6513 // already down!
6514 // XXX: We should probably send an ACTION_UP to the current
6515 // target.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006516 Slog.w(TAG, "Pointer down received while already down in: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006517 + mMotionTarget);
6518 mMotionTarget = null;
6519 }
Romain Guy06882f82009-06-10 13:36:04 -07006520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006521 // ACTION_DOWN is special, because we need to lock next events to
6522 // the window we'll land onto.
6523 final int x = (int)xf;
6524 final int y = (int)yf;
Romain Guy06882f82009-06-10 13:36:04 -07006525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006526 final ArrayList windows = mWindows;
6527 final int N = windows.size();
6528 WindowState topErrWindow = null;
6529 final Rect tmpRect = mTempRect;
6530 for (int i=N-1; i>=0; i--) {
6531 WindowState child = (WindowState)windows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006532 //Slog.i(TAG, "Checking dispatch to: " + child);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006533 final int flags = child.mAttrs.flags;
6534 if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
6535 if (topErrWindow == null) {
6536 topErrWindow = child;
6537 }
6538 }
6539 if (!child.isVisibleLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006540 //Slog.i(TAG, "Not visible!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006541 continue;
6542 }
6543 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006544 //Slog.i(TAG, "Not touchable!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006545 if ((flags & WindowManager.LayoutParams
6546 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
6547 child.mNextOutsideTouch = mOutsideTouchTargets;
6548 mOutsideTouchTargets = child;
6549 }
6550 continue;
6551 }
6552 tmpRect.set(child.mFrame);
6553 if (child.mTouchableInsets == ViewTreeObserver
6554 .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
6555 // The touch is inside of the window if it is
6556 // inside the frame, AND the content part of that
6557 // frame that was given by the application.
6558 tmpRect.left += child.mGivenContentInsets.left;
6559 tmpRect.top += child.mGivenContentInsets.top;
6560 tmpRect.right -= child.mGivenContentInsets.right;
6561 tmpRect.bottom -= child.mGivenContentInsets.bottom;
6562 } else if (child.mTouchableInsets == ViewTreeObserver
6563 .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
6564 // The touch is inside of the window if it is
6565 // inside the frame, AND the visible part of that
6566 // frame that was given by the application.
6567 tmpRect.left += child.mGivenVisibleInsets.left;
6568 tmpRect.top += child.mGivenVisibleInsets.top;
6569 tmpRect.right -= child.mGivenVisibleInsets.right;
6570 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
6571 }
6572 final int touchFlags = flags &
6573 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6574 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
6575 if (tmpRect.contains(x, y) || touchFlags == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006576 //Slog.i(TAG, "Using this target!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006577 if (!screenWasOff || (flags &
6578 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
6579 mMotionTarget = child;
6580 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006581 //Slog.i(TAG, "Waking, skip!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006582 mMotionTarget = null;
6583 }
6584 break;
6585 }
Romain Guy06882f82009-06-10 13:36:04 -07006586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006587 if ((flags & WindowManager.LayoutParams
6588 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
6589 child.mNextOutsideTouch = mOutsideTouchTargets;
6590 mOutsideTouchTargets = child;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006591 //Slog.i(TAG, "Adding to outside target list: " + child);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006592 }
6593 }
6594
6595 // if there's an error window but it's not accepting
6596 // focus (typically because it is not yet visible) just
6597 // wait for it -- any other focused window may in fact
6598 // be in ANR state.
6599 if (topErrWindow != null && mMotionTarget != topErrWindow) {
6600 mMotionTarget = null;
6601 }
6602 }
Romain Guy06882f82009-06-10 13:36:04 -07006603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006604 target = mMotionTarget;
6605 }
6606 }
Romain Guy06882f82009-06-10 13:36:04 -07006607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006608 wakeupIfNeeded(target, eventType(nextMotion));
Romain Guy06882f82009-06-10 13:36:04 -07006609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006610 // Pointer events are a little different -- if there isn't a
6611 // target found for any event, then just drop it.
6612 return target != null ? target : SKIP_TARGET_TOKEN;
6613 }
Romain Guy06882f82009-06-10 13:36:04 -07006614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006615 boolean checkShouldDispatchKey(int keycode) {
6616 synchronized (this) {
6617 if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) {
6618 mTimeToSwitch = 0;
6619 return true;
6620 }
6621 if (mTimeToSwitch != 0
6622 && mTimeToSwitch < SystemClock.uptimeMillis()) {
6623 return false;
6624 }
6625 return true;
6626 }
6627 }
Romain Guy06882f82009-06-10 13:36:04 -07006628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006629 void bindTargetWindowLocked(WindowState win,
6630 int pendingWhat, QueuedEvent pendingMotion) {
6631 synchronized (this) {
6632 bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion);
6633 }
6634 }
Romain Guy06882f82009-06-10 13:36:04 -07006635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006636 void bindTargetWindowLocked(WindowState win) {
6637 synchronized (this) {
6638 bindTargetWindowLockedLocked(win, RETURN_NOTHING, null);
6639 }
6640 }
6641
6642 void bindTargetWindowLockedLocked(WindowState win,
6643 int pendingWhat, QueuedEvent pendingMotion) {
6644 mLastWin = win;
6645 mLastBinder = win.mClient.asBinder();
6646 mFinished = false;
6647 if (pendingMotion != null) {
6648 final Session s = win.mSession;
6649 if (pendingWhat == RETURN_PENDING_POINTER) {
6650 releasePendingPointerLocked(s);
6651 s.mPendingPointerMove = pendingMotion;
6652 s.mPendingPointerWindow = win;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006653 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006654 "bindTargetToWindow " + s.mPendingPointerMove);
6655 } else if (pendingWhat == RETURN_PENDING_TRACKBALL) {
6656 releasePendingTrackballLocked(s);
6657 s.mPendingTrackballMove = pendingMotion;
6658 s.mPendingTrackballWindow = win;
6659 }
6660 }
6661 }
Romain Guy06882f82009-06-10 13:36:04 -07006662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006663 void releasePendingPointerLocked(Session s) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006664 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006665 "releasePendingPointer " + s.mPendingPointerMove);
6666 if (s.mPendingPointerMove != null) {
6667 mQueue.recycleEvent(s.mPendingPointerMove);
6668 s.mPendingPointerMove = null;
6669 }
6670 }
Romain Guy06882f82009-06-10 13:36:04 -07006671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006672 void releasePendingTrackballLocked(Session s) {
6673 if (s.mPendingTrackballMove != null) {
6674 mQueue.recycleEvent(s.mPendingTrackballMove);
6675 s.mPendingTrackballMove = null;
6676 }
6677 }
Romain Guy06882f82009-06-10 13:36:04 -07006678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006679 MotionEvent finishedKey(Session session, IWindow client, boolean force,
6680 int returnWhat) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006681 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006682 TAG, "finishedKey: client=" + client + ", force=" + force);
6683
6684 if (client == null) {
6685 return null;
6686 }
6687
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006688 MotionEvent res = null;
6689 QueuedEvent qev = null;
6690 WindowState win = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006692 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006693 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006694 TAG, "finishedKey: client=" + client.asBinder()
6695 + ", force=" + force + ", last=" + mLastBinder
6696 + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
6697
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006698 if (returnWhat == RETURN_PENDING_POINTER) {
6699 qev = session.mPendingPointerMove;
6700 win = session.mPendingPointerWindow;
6701 session.mPendingPointerMove = null;
6702 session.mPendingPointerWindow = null;
6703 } else if (returnWhat == RETURN_PENDING_TRACKBALL) {
6704 qev = session.mPendingTrackballMove;
6705 win = session.mPendingTrackballWindow;
6706 session.mPendingTrackballMove = null;
6707 session.mPendingTrackballWindow = null;
6708 }
Romain Guy06882f82009-06-10 13:36:04 -07006709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006710 if (mLastBinder == client.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006711 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006712 TAG, "finishedKey: last paused="
6713 + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
6714 if (mLastWin != null && (!mLastWin.mToken.paused || force
6715 || !mEventDispatching)) {
Christopher Tate136b1f92010-02-11 17:51:24 -08006716 doFinishedKeyLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006717 } else {
6718 // Make sure to wake up anyone currently waiting to
6719 // dispatch a key, so they can re-evaluate their
6720 // current situation.
6721 mFinished = true;
6722 notifyAll();
6723 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006724 }
Romain Guy06882f82009-06-10 13:36:04 -07006725
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006726 if (qev != null) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006727 res = (MotionEvent)qev.event;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006728 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006729 "Returning pending motion: " + res);
6730 mQueue.recycleEvent(qev);
6731 if (win != null && returnWhat == RETURN_PENDING_POINTER) {
6732 res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
6733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006734 }
Christopher Tate2624fbc2009-12-11 12:11:31 -08006735 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006736
Christopher Tate2624fbc2009-12-11 12:11:31 -08006737 if (res != null && returnWhat == RETURN_PENDING_POINTER) {
6738 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08006739 dispatchPointerElsewhereLocked(win, win, res, res.getEventTime(), false);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006740 }
6741 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006742
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006743 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006744 }
6745
6746 void tickle() {
6747 synchronized (this) {
6748 notifyAll();
6749 }
6750 }
Romain Guy06882f82009-06-10 13:36:04 -07006751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006752 void handleNewWindowLocked(WindowState newWindow) {
6753 if (!newWindow.canReceiveKeys()) {
6754 return;
6755 }
6756 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006757 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006758 TAG, "New key dispatch window: win="
6759 + newWindow.mClient.asBinder()
6760 + ", last=" + mLastBinder
6761 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6762 + "), finished=" + mFinished + ", paused="
6763 + newWindow.mToken.paused);
6764
6765 // Displaying a window implicitly causes dispatching to
6766 // be unpaused. (This is to protect against bugs if someone
6767 // pauses dispatching but forgets to resume.)
6768 newWindow.mToken.paused = false;
6769
6770 mGotFirstWindow = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006771
6772 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006773 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 "New SYSTEM_ERROR window; resetting state");
6775 mLastWin = null;
6776 mLastBinder = null;
6777 mMotionTarget = null;
6778 mFinished = true;
6779 } else if (mLastWin != null) {
6780 // If the new window is above the window we are
6781 // waiting on, then stop waiting and let key dispatching
6782 // start on the new guy.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006783 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006784 TAG, "Last win layer=" + mLastWin.mLayer
6785 + ", new win layer=" + newWindow.mLayer);
6786 if (newWindow.mLayer >= mLastWin.mLayer) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006787 // The new window is above the old; finish pending input to the last
6788 // window and start directing it to the new one.
6789 mLastWin.mToken.paused = false;
Christopher Tate136b1f92010-02-11 17:51:24 -08006790 doFinishedKeyLocked(false); // does a notifyAll()
6791 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006792 }
6793 }
6794
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006795 // Now that we've put a new window state in place, make the event waiter
6796 // take notice and retarget its attentions.
6797 notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006798 }
6799 }
6800
6801 void pauseDispatchingLocked(WindowToken token) {
6802 synchronized (this)
6803 {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006804 if (DEBUG_INPUT) Slog.v(TAG, "Pausing WindowToken " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006805 token.paused = true;
6806
6807 /*
6808 if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) {
6809 mPaused = true;
6810 } else {
6811 if (mLastWin == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006812 Slog.i(TAG, "Key dispatching not paused: no last window.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006813 } else if (mFinished) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006814 Slog.i(TAG, "Key dispatching not paused: finished last key.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006815 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006816 Slog.i(TAG, "Key dispatching not paused: window in higher layer.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006817 }
6818 }
6819 */
6820 }
6821 }
6822
6823 void resumeDispatchingLocked(WindowToken token) {
6824 synchronized (this) {
6825 if (token.paused) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006826 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006827 TAG, "Resuming WindowToken " + token
6828 + ", last=" + mLastBinder
6829 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6830 + "), finished=" + mFinished + ", paused="
6831 + token.paused);
6832 token.paused = false;
6833 if (mLastWin != null && mLastWin.mToken == token && mFinished) {
Christopher Tate136b1f92010-02-11 17:51:24 -08006834 doFinishedKeyLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006835 } else {
6836 notifyAll();
6837 }
6838 }
6839 }
6840 }
6841
6842 void setEventDispatchingLocked(boolean enabled) {
6843 synchronized (this) {
6844 mEventDispatching = enabled;
6845 notifyAll();
6846 }
6847 }
Romain Guy06882f82009-06-10 13:36:04 -07006848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006849 void appSwitchComing() {
6850 synchronized (this) {
6851 // Don't wait for more than .5 seconds for app to finish
6852 // processing the pending events.
6853 long now = SystemClock.uptimeMillis() + 500;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006854 if (DEBUG_INPUT) Slog.v(TAG, "appSwitchComing: " + now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006855 if (mTimeToSwitch == 0 || now < mTimeToSwitch) {
6856 mTimeToSwitch = now;
6857 }
6858 notifyAll();
6859 }
6860 }
Romain Guy06882f82009-06-10 13:36:04 -07006861
Christopher Tate136b1f92010-02-11 17:51:24 -08006862 private final void doFinishedKeyLocked(boolean force) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006863 if (mLastWin != null) {
6864 releasePendingPointerLocked(mLastWin.mSession);
6865 releasePendingTrackballLocked(mLastWin.mSession);
6866 }
Romain Guy06882f82009-06-10 13:36:04 -07006867
Christopher Tate136b1f92010-02-11 17:51:24 -08006868 if (force || mLastWin == null || !mLastWin.mToken.paused
6869 || !mLastWin.isVisibleLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006870 // If the current window has been paused, we aren't -really-
6871 // finished... so let the waiters still wait.
6872 mLastWin = null;
6873 mLastBinder = null;
6874 }
6875 mFinished = true;
6876 notifyAll();
6877 }
6878 }
6879
6880 private class KeyQ extends KeyInputQueue
6881 implements KeyInputQueue.FilterCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006882 KeyQ() {
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07006883 super(mContext, WindowManagerService.this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006884 }
6885
6886 @Override
6887 boolean preprocessEvent(InputDevice device, RawInputEvent event) {
6888 if (mPolicy.preprocessInputEventTq(event)) {
6889 return true;
6890 }
Romain Guy06882f82009-06-10 13:36:04 -07006891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006892 switch (event.type) {
6893 case RawInputEvent.EV_KEY: {
6894 // XXX begin hack
6895 if (DEBUG) {
6896 if (event.keycode == KeyEvent.KEYCODE_G) {
6897 if (event.value != 0) {
6898 // G down
6899 mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
6900 }
6901 return false;
6902 }
6903 if (event.keycode == KeyEvent.KEYCODE_D) {
6904 if (event.value != 0) {
6905 //dump();
6906 }
6907 return false;
6908 }
6909 }
6910 // XXX end hack
Romain Guy06882f82009-06-10 13:36:04 -07006911
Charles Mendis322591c2009-10-29 11:06:59 -07006912 boolean screenIsOff = !mPowerManager.isScreenOn();
6913 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006914 int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
Romain Guy06882f82009-06-10 13:36:04 -07006915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006916 if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) {
6917 mPowerManager.goToSleep(event.when);
6918 }
6919
6920 if (screenIsOff) {
6921 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6922 }
6923 if (screenIsDim) {
6924 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6925 }
6926 if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
6927 mPowerManager.userActivity(event.when, false,
Michael Chane96440f2009-05-06 10:27:36 -07006928 LocalPowerManager.BUTTON_EVENT, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006929 }
Romain Guy06882f82009-06-10 13:36:04 -07006930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006931 if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
6932 if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) {
6933 filterQueue(this);
6934 mKeyWaiter.appSwitchComing();
6935 }
6936 return true;
6937 } else {
6938 return false;
6939 }
6940 }
Romain Guy06882f82009-06-10 13:36:04 -07006941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006942 case RawInputEvent.EV_REL: {
Charles Mendis322591c2009-10-29 11:06:59 -07006943 boolean screenIsOff = !mPowerManager.isScreenOn();
6944 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006945 if (screenIsOff) {
6946 if (!mPolicy.isWakeRelMovementTq(event.deviceId,
6947 device.classes, event)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006948 //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006949 return false;
6950 }
6951 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6952 }
6953 if (screenIsDim) {
6954 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6955 }
6956 return true;
6957 }
Romain Guy06882f82009-06-10 13:36:04 -07006958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006959 case RawInputEvent.EV_ABS: {
Charles Mendis322591c2009-10-29 11:06:59 -07006960 boolean screenIsOff = !mPowerManager.isScreenOn();
6961 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006962 if (screenIsOff) {
6963 if (!mPolicy.isWakeAbsMovementTq(event.deviceId,
6964 device.classes, event)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006965 //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006966 return false;
6967 }
6968 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6969 }
6970 if (screenIsDim) {
6971 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6972 }
6973 return true;
6974 }
Romain Guy06882f82009-06-10 13:36:04 -07006975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006976 default:
6977 return true;
6978 }
6979 }
6980
6981 public int filterEvent(QueuedEvent ev) {
6982 switch (ev.classType) {
6983 case RawInputEvent.CLASS_KEYBOARD:
6984 KeyEvent ke = (KeyEvent)ev.event;
6985 if (mPolicy.isMovementKeyTi(ke.getKeyCode())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006986 Slog.w(TAG, "Dropping movement key during app switch: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006987 + ke.getKeyCode() + ", action=" + ke.getAction());
6988 return FILTER_REMOVE;
6989 }
6990 return FILTER_ABORT;
6991 default:
6992 return FILTER_KEEP;
6993 }
6994 }
Michael Chan53071d62009-05-13 17:29:48 -07006995 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006996
6997 public boolean detectSafeMode() {
6998 mSafeMode = mPolicy.detectSafeMode();
6999 return mSafeMode;
7000 }
Romain Guy06882f82009-06-10 13:36:04 -07007001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007002 public void systemReady() {
7003 mPolicy.systemReady();
7004 }
Romain Guy06882f82009-06-10 13:36:04 -07007005
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007006 private final class InputDispatcherThread extends Thread {
7007 // Time to wait when there is nothing to do: 9999 seconds.
7008 static final int LONG_WAIT=9999*1000;
7009
7010 public InputDispatcherThread() {
7011 super("InputDispatcher");
7012 }
Romain Guy06882f82009-06-10 13:36:04 -07007013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014 @Override
7015 public void run() {
7016 while (true) {
7017 try {
7018 process();
7019 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007020 Slog.e(TAG, "Exception in input dispatcher", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007021 }
7022 }
7023 }
Romain Guy06882f82009-06-10 13:36:04 -07007024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007025 private void process() {
7026 android.os.Process.setThreadPriority(
7027 android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -07007028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007029 // The last key event we saw
7030 KeyEvent lastKey = null;
7031
7032 // Last keydown time for auto-repeating keys
7033 long lastKeyTime = SystemClock.uptimeMillis();
7034 long nextKeyTime = lastKeyTime+LONG_WAIT;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007035 long downTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007036
Romain Guy06882f82009-06-10 13:36:04 -07007037 // How many successive repeats we generated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007038 int keyRepeatCount = 0;
7039
7040 // Need to report that configuration has changed?
7041 boolean configChanged = false;
Romain Guy06882f82009-06-10 13:36:04 -07007042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007043 while (true) {
7044 long curTime = SystemClock.uptimeMillis();
7045
Joe Onorato8a9b2202010-02-26 18:56:32 -08007046 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007047 TAG, "Waiting for next key: now=" + curTime
7048 + ", repeat @ " + nextKeyTime);
7049
7050 // Retrieve next event, waiting only as long as the next
7051 // repeat timeout. If the configuration has changed, then
7052 // don't wait at all -- we'll report the change as soon as
7053 // we have processed all events.
7054 QueuedEvent ev = mQueue.getEvent(
7055 (int)((!configChanged && curTime < nextKeyTime)
7056 ? (nextKeyTime-curTime) : 0));
7057
Joe Onorato8a9b2202010-02-26 18:56:32 -08007058 if (DEBUG_INPUT && ev != null) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007059 TAG, "Event: type=" + ev.classType + " data=" + ev.event);
7060
Michael Chan53071d62009-05-13 17:29:48 -07007061 if (MEASURE_LATENCY) {
7062 lt.sample("2 got event ", System.nanoTime() - ev.whenNano);
7063 }
7064
Mike Lockwood3d0ea722009-10-21 22:58:29 -04007065 if (lastKey != null && !mPolicy.allowKeyRepeat()) {
7066 // cancel key repeat at the request of the policy.
7067 lastKey = null;
7068 downTime = 0;
7069 lastKeyTime = curTime;
7070 nextKeyTime = curTime + LONG_WAIT;
7071 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007072 try {
7073 if (ev != null) {
Michael Chan53071d62009-05-13 17:29:48 -07007074 curTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007075 int eventType;
7076 if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
7077 eventType = eventType((MotionEvent)ev.event);
7078 } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
7079 ev.classType == RawInputEvent.CLASS_TRACKBALL) {
7080 eventType = LocalPowerManager.BUTTON_EVENT;
7081 } else {
7082 eventType = LocalPowerManager.OTHER_EVENT;
7083 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07007084 try {
Michael Chan53071d62009-05-13 17:29:48 -07007085 if ((curTime - mLastBatteryStatsCallTime)
Michael Chane96440f2009-05-06 10:27:36 -07007086 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
Michael Chan53071d62009-05-13 17:29:48 -07007087 mLastBatteryStatsCallTime = curTime;
Michael Chane96440f2009-05-06 10:27:36 -07007088 mBatteryStats.noteInputEvent();
7089 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07007090 } catch (RemoteException e) {
7091 // Ignore
7092 }
Michael Chane10de972009-05-18 11:24:50 -07007093
Mike Lockwood5db42402009-11-30 14:51:51 -05007094 if (ev.classType == RawInputEvent.CLASS_CONFIGURATION_CHANGED) {
7095 // do not wake screen in this case
7096 } else if (eventType != TOUCH_EVENT
Michael Chane10de972009-05-18 11:24:50 -07007097 && eventType != LONG_TOUCH_EVENT
7098 && eventType != CHEEK_EVENT) {
7099 mPowerManager.userActivity(curTime, false,
7100 eventType, false);
7101 } else if (mLastTouchEventType != eventType
7102 || (curTime - mLastUserActivityCallTime)
7103 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
7104 mLastUserActivityCallTime = curTime;
7105 mLastTouchEventType = eventType;
7106 mPowerManager.userActivity(curTime, false,
7107 eventType, false);
7108 }
7109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007110 switch (ev.classType) {
7111 case RawInputEvent.CLASS_KEYBOARD:
7112 KeyEvent ke = (KeyEvent)ev.event;
7113 if (ke.isDown()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007114 lastKeyTime = curTime;
Kristian Dreher133bfdf2010-02-23 08:50:58 +01007115 if (lastKey != null &&
7116 ke.getKeyCode() == lastKey.getKeyCode()) {
7117 keyRepeatCount++;
7118 // Arbitrary long timeout to block
7119 // repeating here since we know that
7120 // the device driver takes care of it.
7121 nextKeyTime = lastKeyTime + LONG_WAIT;
The Android Open Source Project2a9ae012010-05-12 12:33:35 -07007122 if (DEBUG_INPUT) Slog.v(
Kristian Dreher133bfdf2010-02-23 08:50:58 +01007123 TAG, "Received repeated key down");
7124 } else {
7125 downTime = curTime;
7126 keyRepeatCount = 0;
7127 nextKeyTime = lastKeyTime
7128 + ViewConfiguration.getLongPressTimeout();
The Android Open Source Project2a9ae012010-05-12 12:33:35 -07007129 if (DEBUG_INPUT) Slog.v(
Kristian Dreher133bfdf2010-02-23 08:50:58 +01007130 TAG, "Received key down: first repeat @ "
7131 + nextKeyTime);
7132 }
7133 lastKey = ke;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007134 } else {
7135 lastKey = null;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007136 downTime = 0;
Kristian Dreher133bfdf2010-02-23 08:50:58 +01007137 keyRepeatCount = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007138 // Arbitrary long timeout.
7139 lastKeyTime = curTime;
7140 nextKeyTime = curTime + LONG_WAIT;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007141 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 TAG, "Received key up: ignore repeat @ "
7143 + nextKeyTime);
7144 }
Kristian Dreher133bfdf2010-02-23 08:50:58 +01007145 if (keyRepeatCount > 0) {
7146 dispatchKey(KeyEvent.changeTimeRepeat(ke,
7147 ke.getEventTime(), keyRepeatCount), 0, 0);
7148 } else {
7149 dispatchKey(ke, 0, 0);
7150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007151 mQueue.recycleEvent(ev);
7152 break;
7153 case RawInputEvent.CLASS_TOUCHSCREEN:
Joe Onorato8a9b2202010-02-26 18:56:32 -08007154 //Slog.i(TAG, "Read next event " + ev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007155 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
7156 break;
7157 case RawInputEvent.CLASS_TRACKBALL:
7158 dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
7159 break;
7160 case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
7161 configChanged = true;
7162 break;
7163 default:
7164 mQueue.recycleEvent(ev);
7165 break;
7166 }
Romain Guy06882f82009-06-10 13:36:04 -07007167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007168 } else if (configChanged) {
7169 configChanged = false;
7170 sendNewConfiguration();
Romain Guy06882f82009-06-10 13:36:04 -07007171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007172 } else if (lastKey != null) {
7173 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07007174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007175 // Timeout occurred while key was down. If it is at or
7176 // past the key repeat time, dispatch the repeat.
Joe Onorato8a9b2202010-02-26 18:56:32 -08007177 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007178 TAG, "Key timeout: repeat=" + nextKeyTime
7179 + ", now=" + curTime);
7180 if (curTime < nextKeyTime) {
7181 continue;
7182 }
Romain Guy06882f82009-06-10 13:36:04 -07007183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007184 lastKeyTime = nextKeyTime;
7185 nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY;
7186 keyRepeatCount++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007187 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007188 TAG, "Key repeat: count=" + keyRepeatCount
7189 + ", next @ " + nextKeyTime);
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007190 KeyEvent newEvent;
7191 if (downTime != 0 && (downTime
7192 + ViewConfiguration.getLongPressTimeout())
7193 <= curTime) {
7194 newEvent = KeyEvent.changeTimeRepeat(lastKey,
7195 curTime, keyRepeatCount,
7196 lastKey.getFlags() | KeyEvent.FLAG_LONG_PRESS);
7197 downTime = 0;
7198 } else {
7199 newEvent = KeyEvent.changeTimeRepeat(lastKey,
7200 curTime, keyRepeatCount);
7201 }
7202 dispatchKey(newEvent, 0, 0);
Romain Guy06882f82009-06-10 13:36:04 -07007203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007204 } else {
7205 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07007206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007207 lastKeyTime = curTime;
7208 nextKeyTime = curTime + LONG_WAIT;
7209 }
Romain Guy06882f82009-06-10 13:36:04 -07007210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007211 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007212 Slog.e(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007213 "Input thread received uncaught exception: " + e, e);
7214 }
7215 }
7216 }
7217 }
7218
7219 // -------------------------------------------------------------
7220 // Client Session State
7221 // -------------------------------------------------------------
7222
7223 private final class Session extends IWindowSession.Stub
7224 implements IBinder.DeathRecipient {
7225 final IInputMethodClient mClient;
7226 final IInputContext mInputContext;
7227 final int mUid;
7228 final int mPid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007229 final String mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007230 SurfaceSession mSurfaceSession;
7231 int mNumWindow = 0;
7232 boolean mClientDead = false;
Romain Guy06882f82009-06-10 13:36:04 -07007233
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007234 /**
7235 * Current pointer move event being dispatched to client window... must
7236 * hold key lock to access.
7237 */
7238 QueuedEvent mPendingPointerMove;
7239 WindowState mPendingPointerWindow;
Romain Guy06882f82009-06-10 13:36:04 -07007240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007241 /**
7242 * Current trackball move event being dispatched to client window... must
7243 * hold key lock to access.
7244 */
7245 QueuedEvent mPendingTrackballMove;
7246 WindowState mPendingTrackballWindow;
7247
7248 public Session(IInputMethodClient client, IInputContext inputContext) {
7249 mClient = client;
7250 mInputContext = inputContext;
7251 mUid = Binder.getCallingUid();
7252 mPid = Binder.getCallingPid();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007253 StringBuilder sb = new StringBuilder();
7254 sb.append("Session{");
7255 sb.append(Integer.toHexString(System.identityHashCode(this)));
7256 sb.append(" uid ");
7257 sb.append(mUid);
7258 sb.append("}");
7259 mStringName = sb.toString();
Romain Guy06882f82009-06-10 13:36:04 -07007260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007261 synchronized (mWindowMap) {
7262 if (mInputMethodManager == null && mHaveInputMethods) {
7263 IBinder b = ServiceManager.getService(
7264 Context.INPUT_METHOD_SERVICE);
7265 mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
7266 }
7267 }
7268 long ident = Binder.clearCallingIdentity();
7269 try {
7270 // Note: it is safe to call in to the input method manager
7271 // here because we are not holding our lock.
7272 if (mInputMethodManager != null) {
7273 mInputMethodManager.addClient(client, inputContext,
7274 mUid, mPid);
7275 } else {
7276 client.setUsingInputMethod(false);
7277 }
7278 client.asBinder().linkToDeath(this, 0);
7279 } catch (RemoteException e) {
7280 // The caller has died, so we can just forget about this.
7281 try {
7282 if (mInputMethodManager != null) {
7283 mInputMethodManager.removeClient(client);
7284 }
7285 } catch (RemoteException ee) {
7286 }
7287 } finally {
7288 Binder.restoreCallingIdentity(ident);
7289 }
7290 }
Romain Guy06882f82009-06-10 13:36:04 -07007291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007292 @Override
7293 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
7294 throws RemoteException {
7295 try {
7296 return super.onTransact(code, data, reply, flags);
7297 } catch (RuntimeException e) {
7298 // Log all 'real' exceptions thrown to the caller
7299 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007300 Slog.e(TAG, "Window Session Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007301 }
7302 throw e;
7303 }
7304 }
7305
7306 public void binderDied() {
7307 // Note: it is safe to call in to the input method manager
7308 // here because we are not holding our lock.
7309 try {
7310 if (mInputMethodManager != null) {
7311 mInputMethodManager.removeClient(mClient);
7312 }
7313 } catch (RemoteException e) {
7314 }
7315 synchronized(mWindowMap) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07007316 mClient.asBinder().unlinkToDeath(this, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007317 mClientDead = true;
7318 killSessionLocked();
7319 }
7320 }
7321
7322 public int add(IWindow window, WindowManager.LayoutParams attrs,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07007323 int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
7324 return addWindow(this, window, attrs, viewVisibility, outContentInsets,
7325 outInputChannel);
7326 }
7327
7328 public int addWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007329 int viewVisibility, Rect outContentInsets) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07007330 return addWindow(this, window, attrs, viewVisibility, outContentInsets, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007331 }
Romain Guy06882f82009-06-10 13:36:04 -07007332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007333 public void remove(IWindow window) {
7334 removeWindow(this, window);
7335 }
Romain Guy06882f82009-06-10 13:36:04 -07007336
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007337 public int relayout(IWindow window, WindowManager.LayoutParams attrs,
7338 int requestedWidth, int requestedHeight, int viewFlags,
7339 boolean insetsPending, Rect outFrame, Rect outContentInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07007340 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007341 return relayoutWindow(this, window, attrs,
7342 requestedWidth, requestedHeight, viewFlags, insetsPending,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07007343 outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007344 }
Romain Guy06882f82009-06-10 13:36:04 -07007345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007346 public void setTransparentRegion(IWindow window, Region region) {
7347 setTransparentRegionWindow(this, window, region);
7348 }
Romain Guy06882f82009-06-10 13:36:04 -07007349
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007350 public void setInsets(IWindow window, int touchableInsets,
7351 Rect contentInsets, Rect visibleInsets) {
7352 setInsetsWindow(this, window, touchableInsets, contentInsets,
7353 visibleInsets);
7354 }
Romain Guy06882f82009-06-10 13:36:04 -07007355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
7357 getWindowDisplayFrame(this, window, outDisplayFrame);
7358 }
Romain Guy06882f82009-06-10 13:36:04 -07007359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360 public void finishDrawing(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007361 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007362 TAG, "IWindow finishDrawing called for " + window);
7363 finishDrawingWindow(this, window);
7364 }
7365
7366 public void finishKey(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007367 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 TAG, "IWindow finishKey called for " + window);
Jeff Brown349703e2010-06-22 01:27:15 -07007369 if (ENABLE_NATIVE_INPUT_DISPATCH) {
7370 throw new IllegalStateException("Should not be called anymore.");
7371 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 mKeyWaiter.finishedKey(this, window, false,
7373 KeyWaiter.RETURN_NOTHING);
7374 }
7375
7376 public MotionEvent getPendingPointerMove(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007377 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007378 TAG, "IWindow getPendingMotionEvent called for " + window);
Jeff Brown349703e2010-06-22 01:27:15 -07007379 if (ENABLE_NATIVE_INPUT_DISPATCH) {
7380 throw new IllegalStateException("Should not be called anymore.");
7381 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007382 return mKeyWaiter.finishedKey(this, window, false,
7383 KeyWaiter.RETURN_PENDING_POINTER);
7384 }
Romain Guy06882f82009-06-10 13:36:04 -07007385
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007386 public MotionEvent getPendingTrackballMove(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007387 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 TAG, "IWindow getPendingMotionEvent called for " + window);
Jeff Brown349703e2010-06-22 01:27:15 -07007389 if (ENABLE_NATIVE_INPUT_DISPATCH) {
7390 throw new IllegalStateException("Should not be called anymore.");
7391 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007392 return mKeyWaiter.finishedKey(this, window, false,
7393 KeyWaiter.RETURN_PENDING_TRACKBALL);
7394 }
7395
7396 public void setInTouchMode(boolean mode) {
7397 synchronized(mWindowMap) {
7398 mInTouchMode = mode;
7399 }
7400 }
7401
7402 public boolean getInTouchMode() {
7403 synchronized(mWindowMap) {
7404 return mInTouchMode;
7405 }
7406 }
7407
7408 public boolean performHapticFeedback(IWindow window, int effectId,
7409 boolean always) {
7410 synchronized(mWindowMap) {
7411 long ident = Binder.clearCallingIdentity();
7412 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07007413 return mPolicy.performHapticFeedbackLw(
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007414 windowForClientLocked(this, window, true),
7415 effectId, always);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007416 } finally {
7417 Binder.restoreCallingIdentity(ident);
7418 }
7419 }
7420 }
Romain Guy06882f82009-06-10 13:36:04 -07007421
Marco Nelissenbf6956b2009-11-09 15:21:13 -08007422 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007423 synchronized(mWindowMap) {
7424 long ident = Binder.clearCallingIdentity();
7425 try {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007426 setWindowWallpaperPositionLocked(
7427 windowForClientLocked(this, window, true),
Marco Nelissenbf6956b2009-11-09 15:21:13 -08007428 x, y, xStep, yStep);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007429 } finally {
7430 Binder.restoreCallingIdentity(ident);
7431 }
7432 }
7433 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007434
Dianne Hackborn19382ac2009-09-11 21:13:37 -07007435 public void wallpaperOffsetsComplete(IBinder window) {
7436 WindowManagerService.this.wallpaperOffsetsComplete(window);
7437 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007438
Dianne Hackborn75804932009-10-20 20:15:20 -07007439 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
7440 int z, Bundle extras, boolean sync) {
7441 synchronized(mWindowMap) {
7442 long ident = Binder.clearCallingIdentity();
7443 try {
7444 return sendWindowWallpaperCommandLocked(
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007445 windowForClientLocked(this, window, true),
Dianne Hackborn75804932009-10-20 20:15:20 -07007446 action, x, y, z, extras, sync);
7447 } finally {
7448 Binder.restoreCallingIdentity(ident);
7449 }
7450 }
7451 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007452
Dianne Hackborn75804932009-10-20 20:15:20 -07007453 public void wallpaperCommandComplete(IBinder window, Bundle result) {
7454 WindowManagerService.this.wallpaperCommandComplete(window, result);
7455 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007457 void windowAddedLocked() {
7458 if (mSurfaceSession == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007459 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007460 TAG, "First window added to " + this + ", creating SurfaceSession");
7461 mSurfaceSession = new SurfaceSession();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007462 if (SHOW_TRANSACTIONS) Slog.i(
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007463 TAG, " NEW SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007464 mSessions.add(this);
7465 }
7466 mNumWindow++;
7467 }
7468
7469 void windowRemovedLocked() {
7470 mNumWindow--;
7471 killSessionLocked();
7472 }
Romain Guy06882f82009-06-10 13:36:04 -07007473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007474 void killSessionLocked() {
7475 if (mNumWindow <= 0 && mClientDead) {
7476 mSessions.remove(this);
7477 if (mSurfaceSession != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007478 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007479 TAG, "Last window removed from " + this
7480 + ", destroying " + mSurfaceSession);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007481 if (SHOW_TRANSACTIONS) Slog.i(
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007482 TAG, " KILL SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007483 try {
7484 mSurfaceSession.kill();
7485 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007486 Slog.w(TAG, "Exception thrown when killing surface session "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007487 + mSurfaceSession + " in session " + this
7488 + ": " + e.toString());
7489 }
7490 mSurfaceSession = null;
7491 }
7492 }
7493 }
Romain Guy06882f82009-06-10 13:36:04 -07007494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007495 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007496 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
7497 pw.print(" mClientDead="); pw.print(mClientDead);
7498 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
7499 if (mPendingPointerWindow != null || mPendingPointerMove != null) {
7500 pw.print(prefix);
7501 pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
7502 pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
7503 }
7504 if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
7505 pw.print(prefix);
7506 pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
7507 pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
7508 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007509 }
7510
7511 @Override
7512 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007513 return mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007514 }
7515 }
7516
7517 // -------------------------------------------------------------
7518 // Client Window State
7519 // -------------------------------------------------------------
7520
7521 private final class WindowState implements WindowManagerPolicy.WindowState {
7522 final Session mSession;
7523 final IWindow mClient;
7524 WindowToken mToken;
The Android Open Source Project10592532009-03-18 17:39:46 -07007525 WindowToken mRootToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007526 AppWindowToken mAppToken;
7527 AppWindowToken mTargetAppToken;
7528 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
7529 final DeathRecipient mDeathRecipient;
7530 final WindowState mAttachedWindow;
7531 final ArrayList mChildWindows = new ArrayList();
7532 final int mBaseLayer;
7533 final int mSubLayer;
7534 final boolean mLayoutAttached;
7535 final boolean mIsImWindow;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007536 final boolean mIsWallpaper;
7537 final boolean mIsFloatingLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007538 int mViewVisibility;
7539 boolean mPolicyVisibility = true;
7540 boolean mPolicyVisibilityAfterAnim = true;
7541 boolean mAppFreezing;
7542 Surface mSurface;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007543 boolean mReportDestroySurface;
7544 boolean mSurfacePendingDestroy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 boolean mAttachedHidden; // is our parent window hidden?
7546 boolean mLastHidden; // was this window last hidden?
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007547 boolean mWallpaperVisible; // for wallpaper, what was last vis report?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007548 int mRequestedWidth;
7549 int mRequestedHeight;
7550 int mLastRequestedWidth;
7551 int mLastRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007552 int mLayer;
7553 int mAnimLayer;
7554 int mLastLayer;
7555 boolean mHaveFrame;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007556 boolean mObscured;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07007557 boolean mTurnOnScreen;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007558
7559 WindowState mNextOutsideTouch;
Romain Guy06882f82009-06-10 13:36:04 -07007560
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007561 int mLayoutSeq = -1;
7562
7563 Configuration mConfiguration = null;
7564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007565 // Actual frame shown on-screen (may be modified by animation)
7566 final Rect mShownFrame = new Rect();
7567 final Rect mLastShownFrame = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569 /**
Dianne Hackbornac3587d2010-03-11 11:12:11 -08007570 * Set when we have changed the size of the surface, to know that
7571 * we must tell them application to resize (and thus redraw itself).
7572 */
7573 boolean mSurfaceResized;
7574
7575 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576 * Insets that determine the actually visible area
7577 */
7578 final Rect mVisibleInsets = new Rect();
7579 final Rect mLastVisibleInsets = new Rect();
7580 boolean mVisibleInsetsChanged;
7581
7582 /**
7583 * Insets that are covered by system windows
7584 */
7585 final Rect mContentInsets = new Rect();
7586 final Rect mLastContentInsets = new Rect();
7587 boolean mContentInsetsChanged;
7588
7589 /**
7590 * Set to true if we are waiting for this window to receive its
7591 * given internal insets before laying out other windows based on it.
7592 */
7593 boolean mGivenInsetsPending;
Romain Guy06882f82009-06-10 13:36:04 -07007594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007595 /**
7596 * These are the content insets that were given during layout for
7597 * this window, to be applied to windows behind it.
7598 */
7599 final Rect mGivenContentInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007601 /**
7602 * These are the visible insets that were given during layout for
7603 * this window, to be applied to windows behind it.
7604 */
7605 final Rect mGivenVisibleInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007607 /**
7608 * Flag indicating whether the touchable region should be adjusted by
7609 * the visible insets; if false the area outside the visible insets is
7610 * NOT touchable, so we must use those to adjust the frame during hit
7611 * tests.
7612 */
7613 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
Romain Guy06882f82009-06-10 13:36:04 -07007614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007615 // Current transformation being applied.
7616 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
7617 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
7618 float mHScale=1, mVScale=1;
7619 float mLastHScale=1, mLastVScale=1;
7620 final Matrix mTmpMatrix = new Matrix();
7621
7622 // "Real" frame that the application sees.
7623 final Rect mFrame = new Rect();
7624 final Rect mLastFrame = new Rect();
7625
7626 final Rect mContainingFrame = new Rect();
7627 final Rect mDisplayFrame = new Rect();
7628 final Rect mContentFrame = new Rect();
7629 final Rect mVisibleFrame = new Rect();
7630
7631 float mShownAlpha = 1;
7632 float mAlpha = 1;
7633 float mLastAlpha = 1;
7634
7635 // Set to true if, when the window gets displayed, it should perform
7636 // an enter animation.
7637 boolean mEnterAnimationPending;
7638
7639 // Currently running animation.
7640 boolean mAnimating;
7641 boolean mLocalAnimating;
7642 Animation mAnimation;
7643 boolean mAnimationIsEntrance;
7644 boolean mHasTransformation;
7645 boolean mHasLocalTransformation;
7646 final Transformation mTransformation = new Transformation();
7647
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007648 // If a window showing a wallpaper: the requested offset for the
7649 // wallpaper; if a wallpaper window: the currently applied offset.
7650 float mWallpaperX = -1;
7651 float mWallpaperY = -1;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08007652
7653 // If a window showing a wallpaper: what fraction of the offset
7654 // range corresponds to a full virtual screen.
7655 float mWallpaperXStep = -1;
7656 float mWallpaperYStep = -1;
7657
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007658 // Wallpaper windows: pixels offset based on above variables.
7659 int mXOffset;
7660 int mYOffset;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007662 // This is set after IWindowSession.relayout() has been called at
7663 // least once for the window. It allows us to detect the situation
7664 // where we don't yet have a surface, but should have one soon, so
7665 // we can give the window focus before waiting for the relayout.
7666 boolean mRelayoutCalled;
Romain Guy06882f82009-06-10 13:36:04 -07007667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007668 // This is set after the Surface has been created but before the
7669 // window has been drawn. During this time the surface is hidden.
7670 boolean mDrawPending;
7671
7672 // This is set after the window has finished drawing for the first
7673 // time but before its surface is shown. The surface will be
7674 // displayed when the next layout is run.
7675 boolean mCommitDrawPending;
7676
7677 // This is set during the time after the window's drawing has been
7678 // committed, and before its surface is actually shown. It is used
7679 // to delay showing the surface until all windows in a token are ready
7680 // to be shown.
7681 boolean mReadyToShow;
Romain Guy06882f82009-06-10 13:36:04 -07007682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683 // Set when the window has been shown in the screen the first time.
7684 boolean mHasDrawn;
7685
7686 // Currently running an exit animation?
7687 boolean mExiting;
7688
7689 // Currently on the mDestroySurface list?
7690 boolean mDestroying;
Romain Guy06882f82009-06-10 13:36:04 -07007691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007692 // Completely remove from window manager after exit animation?
7693 boolean mRemoveOnExit;
7694
7695 // Set when the orientation is changing and this window has not yet
7696 // been updated for the new orientation.
7697 boolean mOrientationChanging;
Romain Guy06882f82009-06-10 13:36:04 -07007698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007699 // Is this window now (or just being) removed?
7700 boolean mRemoved;
Romain Guy06882f82009-06-10 13:36:04 -07007701
Dianne Hackborn16064f92010-03-25 00:47:24 -07007702 // For debugging, this is the last information given to the surface flinger.
7703 boolean mSurfaceShown;
7704 int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
7705 int mSurfaceLayer;
7706 float mSurfaceAlpha;
7707
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07007708 // Input channel
7709 InputChannel mInputChannel;
7710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007711 WindowState(Session s, IWindow c, WindowToken token,
7712 WindowState attachedWindow, WindowManager.LayoutParams a,
7713 int viewVisibility) {
7714 mSession = s;
7715 mClient = c;
7716 mToken = token;
7717 mAttrs.copyFrom(a);
7718 mViewVisibility = viewVisibility;
7719 DeathRecipient deathRecipient = new DeathRecipient();
7720 mAlpha = a.alpha;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007721 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007722 TAG, "Window " + this + " client=" + c.asBinder()
7723 + " token=" + token + " (" + mAttrs.token + ")");
7724 try {
7725 c.asBinder().linkToDeath(deathRecipient, 0);
7726 } catch (RemoteException e) {
7727 mDeathRecipient = null;
7728 mAttachedWindow = null;
7729 mLayoutAttached = false;
7730 mIsImWindow = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007731 mIsWallpaper = false;
7732 mIsFloatingLayer = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733 mBaseLayer = 0;
7734 mSubLayer = 0;
7735 return;
7736 }
7737 mDeathRecipient = deathRecipient;
Romain Guy06882f82009-06-10 13:36:04 -07007738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007739 if ((mAttrs.type >= FIRST_SUB_WINDOW &&
7740 mAttrs.type <= LAST_SUB_WINDOW)) {
7741 // The multiplier here is to reserve space for multiple
7742 // windows in the same type layer.
7743 mBaseLayer = mPolicy.windowTypeToLayerLw(
7744 attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
7745 + TYPE_LAYER_OFFSET;
7746 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
7747 mAttachedWindow = attachedWindow;
7748 mAttachedWindow.mChildWindows.add(this);
7749 mLayoutAttached = mAttrs.type !=
7750 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
7751 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
7752 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007753 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
7754 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007755 } else {
7756 // The multiplier here is to reserve space for multiple
7757 // windows in the same type layer.
7758 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
7759 * TYPE_LAYER_MULTIPLIER
7760 + TYPE_LAYER_OFFSET;
7761 mSubLayer = 0;
7762 mAttachedWindow = null;
7763 mLayoutAttached = false;
7764 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
7765 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007766 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
7767 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007768 }
7769
7770 WindowState appWin = this;
7771 while (appWin.mAttachedWindow != null) {
7772 appWin = mAttachedWindow;
7773 }
7774 WindowToken appToken = appWin.mToken;
7775 while (appToken.appWindowToken == null) {
7776 WindowToken parent = mTokenMap.get(appToken.token);
7777 if (parent == null || appToken == parent) {
7778 break;
7779 }
7780 appToken = parent;
7781 }
The Android Open Source Project10592532009-03-18 17:39:46 -07007782 mRootToken = appToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007783 mAppToken = appToken.appWindowToken;
7784
7785 mSurface = null;
7786 mRequestedWidth = 0;
7787 mRequestedHeight = 0;
7788 mLastRequestedWidth = 0;
7789 mLastRequestedHeight = 0;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007790 mXOffset = 0;
7791 mYOffset = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007792 mLayer = 0;
7793 mAnimLayer = 0;
7794 mLastLayer = 0;
7795 }
7796
7797 void attach() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007798 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 TAG, "Attaching " + this + " token=" + mToken
7800 + ", list=" + mToken.windows);
7801 mSession.windowAddedLocked();
7802 }
7803
7804 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
7805 mHaveFrame = true;
7806
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007807 final Rect container = mContainingFrame;
7808 container.set(pf);
7809
7810 final Rect display = mDisplayFrame;
7811 display.set(df);
7812
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07007813 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007814 container.intersect(mCompatibleScreenFrame);
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007815 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
7816 display.intersect(mCompatibleScreenFrame);
7817 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007818 }
7819
7820 final int pw = container.right - container.left;
7821 final int ph = container.bottom - container.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007822
7823 int w,h;
7824 if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
7825 w = mAttrs.width < 0 ? pw : mAttrs.width;
7826 h = mAttrs.height< 0 ? ph : mAttrs.height;
7827 } else {
Romain Guy980a9382010-01-08 15:06:28 -08007828 w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
7829 h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007830 }
Romain Guy06882f82009-06-10 13:36:04 -07007831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007832 final Rect content = mContentFrame;
7833 content.set(cf);
Romain Guy06882f82009-06-10 13:36:04 -07007834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007835 final Rect visible = mVisibleFrame;
7836 visible.set(vf);
Romain Guy06882f82009-06-10 13:36:04 -07007837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 final Rect frame = mFrame;
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07007839 final int fw = frame.width();
7840 final int fh = frame.height();
Romain Guy06882f82009-06-10 13:36:04 -07007841
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007842 //System.out.println("In: w=" + w + " h=" + h + " container=" +
7843 // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
7844
7845 Gravity.apply(mAttrs.gravity, w, h, container,
7846 (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
7847 (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
7848
7849 //System.out.println("Out: " + mFrame);
7850
7851 // Now make sure the window fits in the overall display.
7852 Gravity.applyDisplay(mAttrs.gravity, df, frame);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007854 // Make sure the content and visible frames are inside of the
7855 // final window frame.
7856 if (content.left < frame.left) content.left = frame.left;
7857 if (content.top < frame.top) content.top = frame.top;
7858 if (content.right > frame.right) content.right = frame.right;
7859 if (content.bottom > frame.bottom) content.bottom = frame.bottom;
7860 if (visible.left < frame.left) visible.left = frame.left;
7861 if (visible.top < frame.top) visible.top = frame.top;
7862 if (visible.right > frame.right) visible.right = frame.right;
7863 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865 final Rect contentInsets = mContentInsets;
7866 contentInsets.left = content.left-frame.left;
7867 contentInsets.top = content.top-frame.top;
7868 contentInsets.right = frame.right-content.right;
7869 contentInsets.bottom = frame.bottom-content.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007871 final Rect visibleInsets = mVisibleInsets;
7872 visibleInsets.left = visible.left-frame.left;
7873 visibleInsets.top = visible.top-frame.top;
7874 visibleInsets.right = frame.right-visible.right;
7875 visibleInsets.bottom = frame.bottom-visible.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007876
Dianne Hackborn284ac932009-08-28 10:34:25 -07007877 if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
7878 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07007879 mDisplay.getHeight(), false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07007880 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 if (localLOGV) {
7883 //if ("com.google.android.youtube".equals(mAttrs.packageName)
7884 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007885 Slog.v(TAG, "Resolving (mRequestedWidth="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007886 + mRequestedWidth + ", mRequestedheight="
7887 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
7888 + "): frame=" + mFrame.toShortString()
7889 + " ci=" + contentInsets.toShortString()
7890 + " vi=" + visibleInsets.toShortString());
7891 //}
7892 }
7893 }
Romain Guy06882f82009-06-10 13:36:04 -07007894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007895 public Rect getFrameLw() {
7896 return mFrame;
7897 }
7898
7899 public Rect getShownFrameLw() {
7900 return mShownFrame;
7901 }
7902
7903 public Rect getDisplayFrameLw() {
7904 return mDisplayFrame;
7905 }
7906
7907 public Rect getContentFrameLw() {
7908 return mContentFrame;
7909 }
7910
7911 public Rect getVisibleFrameLw() {
7912 return mVisibleFrame;
7913 }
7914
7915 public boolean getGivenInsetsPendingLw() {
7916 return mGivenInsetsPending;
7917 }
7918
7919 public Rect getGivenContentInsetsLw() {
7920 return mGivenContentInsets;
7921 }
Romain Guy06882f82009-06-10 13:36:04 -07007922
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007923 public Rect getGivenVisibleInsetsLw() {
7924 return mGivenVisibleInsets;
7925 }
Romain Guy06882f82009-06-10 13:36:04 -07007926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007927 public WindowManager.LayoutParams getAttrs() {
7928 return mAttrs;
7929 }
7930
7931 public int getSurfaceLayer() {
7932 return mLayer;
7933 }
Romain Guy06882f82009-06-10 13:36:04 -07007934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 public IApplicationToken getAppToken() {
7936 return mAppToken != null ? mAppToken.appToken : null;
7937 }
Jeff Brown349703e2010-06-22 01:27:15 -07007938
7939 public long getInputDispatchingTimeoutNanos() {
7940 return mAppToken != null
7941 ? mAppToken.inputDispatchingTimeoutNanos
7942 : DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
7943 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007944
7945 public boolean hasAppShownWindows() {
7946 return mAppToken != null ? mAppToken.firstWindowDrawn : false;
7947 }
7948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007949 public void setAnimation(Animation anim) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007950 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007951 TAG, "Setting animation in " + this + ": " + anim);
7952 mAnimating = false;
7953 mLocalAnimating = false;
7954 mAnimation = anim;
7955 mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
7956 mAnimation.scaleCurrentDuration(mWindowAnimationScale);
7957 }
7958
7959 public void clearAnimation() {
7960 if (mAnimation != null) {
7961 mAnimating = true;
7962 mLocalAnimating = false;
7963 mAnimation = null;
7964 }
7965 }
Romain Guy06882f82009-06-10 13:36:04 -07007966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007967 Surface createSurfaceLocked() {
7968 if (mSurface == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007969 mReportDestroySurface = false;
7970 mSurfacePendingDestroy = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007971 mDrawPending = true;
7972 mCommitDrawPending = false;
7973 mReadyToShow = false;
7974 if (mAppToken != null) {
7975 mAppToken.allDrawn = false;
7976 }
7977
7978 int flags = 0;
Mathias Agopian317a6282009-08-13 17:29:02 -07007979 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 flags |= Surface.PUSH_BUFFERS;
7981 }
7982
7983 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
7984 flags |= Surface.SECURE;
7985 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007986 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007987 TAG, "Creating surface in session "
7988 + mSession.mSurfaceSession + " window " + this
7989 + " w=" + mFrame.width()
7990 + " h=" + mFrame.height() + " format="
7991 + mAttrs.format + " flags=" + flags);
7992
7993 int w = mFrame.width();
7994 int h = mFrame.height();
7995 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
7996 // for a scaled surface, we always want the requested
7997 // size.
7998 w = mRequestedWidth;
7999 h = mRequestedHeight;
8000 }
8001
Romain Guy9825ec62009-10-01 00:58:09 -07008002 // Something is wrong and SurfaceFlinger will not like this,
8003 // try to revert to sane values
8004 if (w <= 0) w = 1;
8005 if (h <= 0) h = 1;
8006
Dianne Hackborn16064f92010-03-25 00:47:24 -07008007 mSurfaceShown = false;
8008 mSurfaceLayer = 0;
8009 mSurfaceAlpha = 1;
8010 mSurfaceX = 0;
8011 mSurfaceY = 0;
8012 mSurfaceW = w;
8013 mSurfaceH = h;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008014 try {
8015 mSurface = new Surface(
Romain Guy06882f82009-06-10 13:36:04 -07008016 mSession.mSurfaceSession, mSession.mPid,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -08008017 mAttrs.getTitle().toString(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008018 0, w, h, mAttrs.format, flags);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008019 if (SHOW_TRANSACTIONS) Slog.i(TAG, " CREATE SURFACE "
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07008020 + mSurface + " IN SESSION "
8021 + mSession.mSurfaceSession
8022 + ": pid=" + mSession.mPid + " format="
8023 + mAttrs.format + " flags=0x"
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008024 + Integer.toHexString(flags)
8025 + " / " + this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008026 } catch (Surface.OutOfResourcesException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008027 Slog.w(TAG, "OutOfResourcesException creating surface");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008028 reclaimSomeSurfaceMemoryLocked(this, "create");
8029 return null;
8030 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008031 Slog.e(TAG, "Exception creating surface", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008032 return null;
8033 }
Romain Guy06882f82009-06-10 13:36:04 -07008034
Joe Onorato8a9b2202010-02-26 18:56:32 -08008035 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008036 TAG, "Got surface: " + mSurface
8037 + ", set left=" + mFrame.left + " top=" + mFrame.top
8038 + ", animLayer=" + mAnimLayer);
8039 if (SHOW_TRANSACTIONS) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008040 Slog.i(TAG, ">>> OPEN TRANSACTION");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008041 if (SHOW_TRANSACTIONS) logSurface(this,
8042 "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
8043 mFrame.width() + "x" + mFrame.height() + "), layer=" +
8044 mAnimLayer + " HIDE", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 }
8046 Surface.openTransaction();
8047 try {
8048 try {
Dianne Hackborn16064f92010-03-25 00:47:24 -07008049 mSurfaceX = mFrame.left + mXOffset;
Dianne Hackborn529bef62010-03-25 11:48:43 -07008050 mSurfaceY = mFrame.top + mYOffset;
Dianne Hackborn16064f92010-03-25 00:47:24 -07008051 mSurface.setPosition(mSurfaceX, mSurfaceY);
8052 mSurfaceLayer = mAnimLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008053 mSurface.setLayer(mAnimLayer);
Dianne Hackborn16064f92010-03-25 00:47:24 -07008054 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008055 mSurface.hide();
8056 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008057 if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008058 mSurface.setFlags(Surface.SURFACE_DITHER,
8059 Surface.SURFACE_DITHER);
8060 }
8061 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008062 Slog.w(TAG, "Error creating surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 reclaimSomeSurfaceMemoryLocked(this, "create-init");
8064 }
8065 mLastHidden = true;
8066 } finally {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008067 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008068 Surface.closeTransaction();
8069 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008070 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008071 TAG, "Created surface " + this);
8072 }
8073 return mSurface;
8074 }
Romain Guy06882f82009-06-10 13:36:04 -07008075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008076 void destroySurfaceLocked() {
8077 // Window is no longer on-screen, so can no longer receive
8078 // key events... if we were waiting for it to finish
8079 // handling a key event, the wait is over!
Jeff Brown349703e2010-06-22 01:27:15 -07008080 if (! ENABLE_NATIVE_INPUT_DISPATCH) {
8081 mKeyWaiter.finishedKey(mSession, mClient, true,
8082 KeyWaiter.RETURN_NOTHING);
8083 mKeyWaiter.releasePendingPointerLocked(mSession);
8084 mKeyWaiter.releasePendingTrackballLocked(mSession);
8085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008086
8087 if (mAppToken != null && this == mAppToken.startingWindow) {
8088 mAppToken.startingDisplayed = false;
8089 }
Romain Guy06882f82009-06-10 13:36:04 -07008090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008091 if (mSurface != null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008092 mDrawPending = false;
8093 mCommitDrawPending = false;
8094 mReadyToShow = false;
8095
8096 int i = mChildWindows.size();
8097 while (i > 0) {
8098 i--;
8099 WindowState c = (WindowState)mChildWindows.get(i);
8100 c.mAttachedHidden = true;
Jeff Brown349703e2010-06-22 01:27:15 -07008101
8102 if (ENABLE_NATIVE_INPUT_DISPATCH) {
8103 mInputMonitor.windowIsBecomingInvisibleLw(c);
8104 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008105 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008106
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008107 if (mReportDestroySurface) {
8108 mReportDestroySurface = false;
8109 mSurfacePendingDestroy = true;
8110 try {
8111 mClient.dispatchGetNewSurface();
8112 // We'll really destroy on the next time around.
8113 return;
8114 } catch (RemoteException e) {
8115 }
8116 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008118 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008119 if (DEBUG_VISIBILITY) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008120 RuntimeException e = null;
8121 if (!HIDE_STACK_CRAWLS) {
8122 e = new RuntimeException();
8123 e.fillInStackTrace();
8124 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008125 Slog.w(TAG, "Window " + this + " destroying surface "
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008126 + mSurface + ", session " + mSession, e);
8127 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008128 if (SHOW_TRANSACTIONS) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008129 RuntimeException e = null;
8130 if (!HIDE_STACK_CRAWLS) {
8131 e = new RuntimeException();
8132 e.fillInStackTrace();
8133 }
8134 if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008135 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07008136 mSurface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008137 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008138 Slog.w(TAG, "Exception thrown when destroying Window " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 + " surface " + mSurface + " session " + mSession
8140 + ": " + e.toString());
8141 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008142
Dianne Hackborn16064f92010-03-25 00:47:24 -07008143 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008144 mSurface = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008145 }
8146 }
8147
8148 boolean finishDrawingLocked() {
8149 if (mDrawPending) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008150 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008151 TAG, "finishDrawingLocked: " + mSurface);
8152 mCommitDrawPending = true;
8153 mDrawPending = false;
8154 return true;
8155 }
8156 return false;
8157 }
8158
8159 // This must be called while inside a transaction.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07008160 boolean commitFinishDrawingLocked(long currentTime) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008161 //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008162 if (!mCommitDrawPending) {
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07008163 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008164 }
8165 mCommitDrawPending = false;
8166 mReadyToShow = true;
8167 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
8168 final AppWindowToken atoken = mAppToken;
8169 if (atoken == null || atoken.allDrawn || starting) {
8170 performShowLocked();
8171 }
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07008172 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008173 }
8174
8175 // This must be called while inside a transaction.
8176 boolean performShowLocked() {
8177 if (DEBUG_VISIBILITY) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008178 RuntimeException e = null;
8179 if (!HIDE_STACK_CRAWLS) {
8180 e = new RuntimeException();
8181 e.fillInStackTrace();
8182 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008183 Slog.v(TAG, "performShow on " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008184 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
8185 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
8186 }
8187 if (mReadyToShow && isReadyForDisplay()) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008188 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this,
8189 "SHOW (performShowLocked)", null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008190 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008191 + " during animation: policyVis=" + mPolicyVisibility
8192 + " attHidden=" + mAttachedHidden
8193 + " tok.hiddenRequested="
8194 + (mAppToken != null ? mAppToken.hiddenRequested : false)
Dianne Hackborn248b1882009-09-16 16:46:44 -07008195 + " tok.hidden="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008196 + (mAppToken != null ? mAppToken.hidden : false)
8197 + " animating=" + mAnimating
8198 + " tok animating="
8199 + (mAppToken != null ? mAppToken.animating : false));
8200 if (!showSurfaceRobustlyLocked(this)) {
8201 return false;
8202 }
8203 mLastAlpha = -1;
8204 mHasDrawn = true;
8205 mLastHidden = false;
8206 mReadyToShow = false;
8207 enableScreenIfNeededLocked();
8208
8209 applyEnterAnimationLocked(this);
Romain Guy06882f82009-06-10 13:36:04 -07008210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008211 int i = mChildWindows.size();
8212 while (i > 0) {
8213 i--;
8214 WindowState c = (WindowState)mChildWindows.get(i);
Dianne Hackbornf09c1a22010-04-22 15:59:21 -07008215 if (c.mAttachedHidden) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008216 c.mAttachedHidden = false;
Dianne Hackbornf09c1a22010-04-22 15:59:21 -07008217 if (c.mSurface != null) {
8218 c.performShowLocked();
8219 // It hadn't been shown, which means layout not
8220 // performed on it, so now we want to make sure to
8221 // do a layout. If called from within the transaction
8222 // loop, this will cause it to restart with a new
8223 // layout.
8224 mLayoutNeeded = true;
8225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008226 }
8227 }
Romain Guy06882f82009-06-10 13:36:04 -07008228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008229 if (mAttrs.type != TYPE_APPLICATION_STARTING
8230 && mAppToken != null) {
8231 mAppToken.firstWindowDrawn = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008232
Dianne Hackborn248b1882009-09-16 16:46:44 -07008233 if (mAppToken.startingData != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008234 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG,
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07008235 "Finish starting " + mToken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008236 + ": first real window is shown, no animation");
Dianne Hackborn248b1882009-09-16 16:46:44 -07008237 // If this initial window is animating, stop it -- we
8238 // will do an animation to reveal it from behind the
8239 // starting window, so there is no need for it to also
8240 // be doing its own stuff.
8241 if (mAnimation != null) {
8242 mAnimation = null;
8243 // Make sure we clean up the animation.
8244 mAnimating = true;
8245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008246 mFinishedStarting.add(mAppToken);
8247 mH.sendEmptyMessage(H.FINISHED_STARTING);
8248 }
8249 mAppToken.updateReportedVisibilityLocked();
8250 }
8251 }
8252 return true;
8253 }
Romain Guy06882f82009-06-10 13:36:04 -07008254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008255 // This must be called while inside a transaction. Returns true if
8256 // there is more animation to run.
8257 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -08008258 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008259 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07008260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008261 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
8262 mHasTransformation = true;
8263 mHasLocalTransformation = true;
8264 if (!mLocalAnimating) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008265 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008266 TAG, "Starting animation in " + this +
8267 " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
8268 " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
8269 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
8270 mAnimation.setStartTime(currentTime);
8271 mLocalAnimating = true;
8272 mAnimating = true;
8273 }
8274 mTransformation.clear();
8275 final boolean more = mAnimation.getTransformation(
8276 currentTime, mTransformation);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008277 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008278 TAG, "Stepped animation in " + this +
8279 ": more=" + more + ", xform=" + mTransformation);
8280 if (more) {
8281 // we're not done!
8282 return true;
8283 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008284 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008285 TAG, "Finished animation in " + this +
8286 " @ " + currentTime);
8287 mAnimation = null;
8288 //WindowManagerService.this.dump();
8289 }
8290 mHasLocalTransformation = false;
8291 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008292 && mAppToken.animation != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008293 // When our app token is animating, we kind-of pretend like
8294 // we are as well. Note the mLocalAnimating mAnimationIsEntrance
8295 // part of this check means that we will only do this if
8296 // our window is not currently exiting, or it is not
8297 // locally animating itself. The idea being that one that
8298 // is exiting and doing a local animation should be removed
8299 // once that animation is done.
8300 mAnimating = true;
8301 mHasTransformation = true;
8302 mTransformation.clear();
8303 return false;
8304 } else if (mHasTransformation) {
8305 // Little trick to get through the path below to act like
8306 // we have finished an animation.
8307 mAnimating = true;
8308 } else if (isAnimating()) {
8309 mAnimating = true;
8310 }
8311 } else if (mAnimation != null) {
8312 // If the display is frozen, and there is a pending animation,
8313 // clear it and make sure we run the cleanup code.
8314 mAnimating = true;
8315 mLocalAnimating = true;
8316 mAnimation = null;
8317 }
Romain Guy06882f82009-06-10 13:36:04 -07008318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008319 if (!mAnimating && !mLocalAnimating) {
8320 return false;
8321 }
8322
Joe Onorato8a9b2202010-02-26 18:56:32 -08008323 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008324 TAG, "Animation done in " + this + ": exiting=" + mExiting
8325 + ", reportedVisible="
8326 + (mAppToken != null ? mAppToken.reportedVisible : false));
Romain Guy06882f82009-06-10 13:36:04 -07008327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008328 mAnimating = false;
8329 mLocalAnimating = false;
8330 mAnimation = null;
8331 mAnimLayer = mLayer;
8332 if (mIsImWindow) {
8333 mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008334 } else if (mIsWallpaper) {
8335 mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008336 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008337 if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008338 + " anim layer: " + mAnimLayer);
8339 mHasTransformation = false;
8340 mHasLocalTransformation = false;
Dianne Hackbornb601ce12010-03-01 23:36:02 -08008341 if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
8342 if (DEBUG_VISIBILITY) {
8343 Slog.v(TAG, "Policy visibility changing after anim in " + this + ": "
8344 + mPolicyVisibilityAfterAnim);
8345 }
8346 mPolicyVisibility = mPolicyVisibilityAfterAnim;
8347 if (!mPolicyVisibility) {
8348 if (mCurrentFocus == this) {
8349 mFocusMayChange = true;
8350 }
8351 // Window is no longer visible -- make sure if we were waiting
8352 // for it to be displayed before enabling the display, that
8353 // we allow the display to be enabled now.
8354 enableScreenIfNeededLocked();
8355 }
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -08008356 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008357 mTransformation.clear();
8358 if (mHasDrawn
8359 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
8360 && mAppToken != null
8361 && mAppToken.firstWindowDrawn
8362 && mAppToken.startingData != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008363 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008364 + mToken + ": first real window done animating");
8365 mFinishedStarting.add(mAppToken);
8366 mH.sendEmptyMessage(H.FINISHED_STARTING);
8367 }
Romain Guy06882f82009-06-10 13:36:04 -07008368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008369 finishExit();
8370
8371 if (mAppToken != null) {
8372 mAppToken.updateReportedVisibilityLocked();
8373 }
8374
8375 return false;
8376 }
8377
8378 void finishExit() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008379 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008380 TAG, "finishExit in " + this
8381 + ": exiting=" + mExiting
8382 + " remove=" + mRemoveOnExit
8383 + " windowAnimating=" + isWindowAnimating());
Romain Guy06882f82009-06-10 13:36:04 -07008384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 final int N = mChildWindows.size();
8386 for (int i=0; i<N; i++) {
8387 ((WindowState)mChildWindows.get(i)).finishExit();
8388 }
Romain Guy06882f82009-06-10 13:36:04 -07008389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008390 if (!mExiting) {
8391 return;
8392 }
Romain Guy06882f82009-06-10 13:36:04 -07008393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008394 if (isWindowAnimating()) {
8395 return;
8396 }
8397
Joe Onorato8a9b2202010-02-26 18:56:32 -08008398 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008399 TAG, "Exit animation finished in " + this
8400 + ": remove=" + mRemoveOnExit);
8401 if (mSurface != null) {
8402 mDestroySurface.add(this);
8403 mDestroying = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008404 if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null);
Dianne Hackborn16064f92010-03-25 00:47:24 -07008405 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008406 try {
8407 mSurface.hide();
8408 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008409 Slog.w(TAG, "Error hiding surface in " + this, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008410 }
8411 mLastHidden = true;
Jeff Brown349703e2010-06-22 01:27:15 -07008412
8413 if (ENABLE_NATIVE_INPUT_DISPATCH) {
8414 for (int i=0; i<N; i++) {
8415 mInputMonitor.windowIsBecomingInvisibleLw((WindowState)mChildWindows.get(i));
8416 }
8417 } else {
8418 mKeyWaiter.releasePendingPointerLocked(mSession);
8419 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008420 }
8421 mExiting = false;
8422 if (mRemoveOnExit) {
8423 mPendingRemove.add(this);
8424 mRemoveOnExit = false;
8425 }
8426 }
Romain Guy06882f82009-06-10 13:36:04 -07008427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008428 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
8429 if (dsdx < .99999f || dsdx > 1.00001f) return false;
8430 if (dtdy < .99999f || dtdy > 1.00001f) return false;
8431 if (dtdx < -.000001f || dtdx > .000001f) return false;
8432 if (dsdy < -.000001f || dsdy > .000001f) return false;
8433 return true;
8434 }
Romain Guy06882f82009-06-10 13:36:04 -07008435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 void computeShownFrameLocked() {
8437 final boolean selfTransformation = mHasLocalTransformation;
8438 Transformation attachedTransformation =
8439 (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
8440 ? mAttachedWindow.mTransformation : null;
8441 Transformation appTransformation =
8442 (mAppToken != null && mAppToken.hasTransformation)
8443 ? mAppToken.transformation : null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008444
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008445 // Wallpapers are animated based on the "real" window they
8446 // are currently targeting.
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008447 if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07008448 && mWallpaperTarget != null) {
Dianne Hackborn5baba162009-09-23 17:01:12 -07008449 if (mWallpaperTarget.mHasLocalTransformation &&
8450 mWallpaperTarget.mAnimation != null &&
8451 !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008452 attachedTransformation = mWallpaperTarget.mTransformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07008453 if (DEBUG_WALLPAPER && attachedTransformation != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008454 Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
Dianne Hackborn5baba162009-09-23 17:01:12 -07008455 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008456 }
8457 if (mWallpaperTarget.mAppToken != null &&
Dianne Hackborn5baba162009-09-23 17:01:12 -07008458 mWallpaperTarget.mAppToken.hasTransformation &&
8459 mWallpaperTarget.mAppToken.animation != null &&
8460 !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008461 appTransformation = mWallpaperTarget.mAppToken.transformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07008462 if (DEBUG_WALLPAPER && appTransformation != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008463 Slog.v(TAG, "WP target app xform: " + appTransformation);
Dianne Hackborn5baba162009-09-23 17:01:12 -07008464 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008465 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008466 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008468 if (selfTransformation || attachedTransformation != null
8469 || appTransformation != null) {
Romain Guy06882f82009-06-10 13:36:04 -07008470 // cache often used attributes locally
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 final Rect frame = mFrame;
8472 final float tmpFloats[] = mTmpFloats;
8473 final Matrix tmpMatrix = mTmpMatrix;
8474
8475 // Compute the desired transformation.
Dianne Hackborn65c23872009-09-18 17:47:02 -07008476 tmpMatrix.setTranslate(0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008477 if (selfTransformation) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07008478 tmpMatrix.postConcat(mTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008479 }
Dianne Hackborn65c23872009-09-18 17:47:02 -07008480 tmpMatrix.postTranslate(frame.left, frame.top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008481 if (attachedTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07008482 tmpMatrix.postConcat(attachedTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008483 }
8484 if (appTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07008485 tmpMatrix.postConcat(appTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 }
8487
8488 // "convert" it into SurfaceFlinger's format
8489 // (a 2x2 matrix + an offset)
8490 // Here we must not transform the position of the surface
8491 // since it is already included in the transformation.
Joe Onorato8a9b2202010-02-26 18:56:32 -08008492 //Slog.i(TAG, "Transform: " + matrix);
Romain Guy06882f82009-06-10 13:36:04 -07008493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008494 tmpMatrix.getValues(tmpFloats);
8495 mDsDx = tmpFloats[Matrix.MSCALE_X];
8496 mDtDx = tmpFloats[Matrix.MSKEW_X];
8497 mDsDy = tmpFloats[Matrix.MSKEW_Y];
8498 mDtDy = tmpFloats[Matrix.MSCALE_Y];
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008499 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
8500 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008501 int w = frame.width();
8502 int h = frame.height();
8503 mShownFrame.set(x, y, x+w, y+h);
8504
8505 // Now set the alpha... but because our current hardware
8506 // can't do alpha transformation on a non-opaque surface,
8507 // turn it off if we are running an animation that is also
8508 // transforming since it is more important to have that
8509 // animation be smooth.
8510 mShownAlpha = mAlpha;
8511 if (!mLimitedAlphaCompositing
8512 || (!PixelFormat.formatHasAlpha(mAttrs.format)
8513 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
8514 && x == frame.left && y == frame.top))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008515 //Slog.i(TAG, "Applying alpha transform");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 if (selfTransformation) {
8517 mShownAlpha *= mTransformation.getAlpha();
8518 }
8519 if (attachedTransformation != null) {
8520 mShownAlpha *= attachedTransformation.getAlpha();
8521 }
8522 if (appTransformation != null) {
8523 mShownAlpha *= appTransformation.getAlpha();
8524 }
8525 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008526 //Slog.i(TAG, "Not applying alpha transform");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008527 }
Romain Guy06882f82009-06-10 13:36:04 -07008528
Joe Onorato8a9b2202010-02-26 18:56:32 -08008529 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008530 TAG, "Continuing animation in " + this +
8531 ": " + mShownFrame +
8532 ", alpha=" + mTransformation.getAlpha());
8533 return;
8534 }
Romain Guy06882f82009-06-10 13:36:04 -07008535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008536 mShownFrame.set(mFrame);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008537 if (mXOffset != 0 || mYOffset != 0) {
8538 mShownFrame.offset(mXOffset, mYOffset);
8539 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 mShownAlpha = mAlpha;
8541 mDsDx = 1;
8542 mDtDx = 0;
8543 mDsDy = 0;
8544 mDtDy = 1;
8545 }
Romain Guy06882f82009-06-10 13:36:04 -07008546
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008547 /**
8548 * Is this window visible? It is not visible if there is no
8549 * surface, or we are in the process of running an exit animation
8550 * that will remove the surface, or its app token has been hidden.
8551 */
8552 public boolean isVisibleLw() {
8553 final AppWindowToken atoken = mAppToken;
8554 return mSurface != null && mPolicyVisibility && !mAttachedHidden
8555 && (atoken == null || !atoken.hiddenRequested)
8556 && !mExiting && !mDestroying;
8557 }
8558
8559 /**
Dianne Hackborn3d163f072009-10-07 21:26:57 -07008560 * Like {@link #isVisibleLw}, but also counts a window that is currently
8561 * "hidden" behind the keyguard as visible. This allows us to apply
8562 * things like window flags that impact the keyguard.
8563 * XXX I am starting to think we need to have ANOTHER visibility flag
8564 * for this "hidden behind keyguard" state rather than overloading
8565 * mPolicyVisibility. Ungh.
8566 */
8567 public boolean isVisibleOrBehindKeyguardLw() {
8568 final AppWindowToken atoken = mAppToken;
8569 return mSurface != null && !mAttachedHidden
8570 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
Dianne Hackborn5943c202010-04-12 21:36:49 -07008571 && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending))
Dianne Hackborn3d163f072009-10-07 21:26:57 -07008572 && !mExiting && !mDestroying;
8573 }
8574
8575 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008576 * Is this window visible, ignoring its app token? It is not visible
8577 * if there is no surface, or we are in the process of running an exit animation
8578 * that will remove the surface.
8579 */
8580 public boolean isWinVisibleLw() {
8581 final AppWindowToken atoken = mAppToken;
8582 return mSurface != null && mPolicyVisibility && !mAttachedHidden
8583 && (atoken == null || !atoken.hiddenRequested || atoken.animating)
8584 && !mExiting && !mDestroying;
8585 }
8586
8587 /**
8588 * The same as isVisible(), but follows the current hidden state of
8589 * the associated app token, not the pending requested hidden state.
8590 */
8591 boolean isVisibleNow() {
8592 return mSurface != null && mPolicyVisibility && !mAttachedHidden
The Android Open Source Project10592532009-03-18 17:39:46 -07008593 && !mRootToken.hidden && !mExiting && !mDestroying;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008594 }
8595
8596 /**
8597 * Same as isVisible(), but we also count it as visible between the
8598 * call to IWindowSession.add() and the first relayout().
8599 */
8600 boolean isVisibleOrAdding() {
8601 final AppWindowToken atoken = mAppToken;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008602 return ((mSurface != null && !mReportDestroySurface)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008603 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
8604 && mPolicyVisibility && !mAttachedHidden
8605 && (atoken == null || !atoken.hiddenRequested)
8606 && !mExiting && !mDestroying;
8607 }
8608
8609 /**
8610 * Is this window currently on-screen? It is on-screen either if it
8611 * is visible or it is currently running an animation before no longer
8612 * being visible.
8613 */
8614 boolean isOnScreen() {
8615 final AppWindowToken atoken = mAppToken;
8616 if (atoken != null) {
8617 return mSurface != null && mPolicyVisibility && !mDestroying
8618 && ((!mAttachedHidden && !atoken.hiddenRequested)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008619 || mAnimation != null || atoken.animation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008620 } else {
8621 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008622 && (!mAttachedHidden || mAnimation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008623 }
8624 }
Romain Guy06882f82009-06-10 13:36:04 -07008625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008626 /**
8627 * Like isOnScreen(), but we don't return true if the window is part
8628 * of a transition that has not yet been started.
8629 */
8630 boolean isReadyForDisplay() {
Dianne Hackborna8f60182009-09-01 19:01:50 -07008631 if (mRootToken.waitingToShow &&
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07008632 mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07008633 return false;
8634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008635 final AppWindowToken atoken = mAppToken;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008636 final boolean animating = atoken != null
8637 ? (atoken.animation != null) : false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008638 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008639 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
8640 && !mRootToken.hidden)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008641 || mAnimation != null || animating);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008642 }
8643
8644 /** Is the window or its container currently animating? */
8645 boolean isAnimating() {
8646 final WindowState attached = mAttachedWindow;
8647 final AppWindowToken atoken = mAppToken;
8648 return mAnimation != null
8649 || (attached != null && attached.mAnimation != null)
Romain Guy06882f82009-06-10 13:36:04 -07008650 || (atoken != null &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008651 (atoken.animation != null
8652 || atoken.inPendingTransaction));
8653 }
8654
8655 /** Is this window currently animating? */
8656 boolean isWindowAnimating() {
8657 return mAnimation != null;
8658 }
8659
8660 /**
8661 * Like isOnScreen, but returns false if the surface hasn't yet
8662 * been drawn.
8663 */
8664 public boolean isDisplayedLw() {
8665 final AppWindowToken atoken = mAppToken;
8666 return mSurface != null && mPolicyVisibility && !mDestroying
8667 && !mDrawPending && !mCommitDrawPending
8668 && ((!mAttachedHidden &&
8669 (atoken == null || !atoken.hiddenRequested))
8670 || mAnimating);
8671 }
8672
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008673 /**
8674 * Returns true if the window has a surface that it has drawn a
Dianne Hackborn5943c202010-04-12 21:36:49 -07008675 * complete UI in to. Note that this returns true if the orientation
8676 * is changing even if the window hasn't redrawn because we don't want
8677 * to stop things from executing during that time.
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008678 */
8679 public boolean isDrawnLw() {
8680 final AppWindowToken atoken = mAppToken;
8681 return mSurface != null && !mDestroying
Dianne Hackborn5943c202010-04-12 21:36:49 -07008682 && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending));
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008683 }
8684
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008685 public boolean fillsScreenLw(int screenWidth, int screenHeight,
8686 boolean shownFrame, boolean onlyOpaque) {
8687 if (mSurface == null) {
8688 return false;
8689 }
8690 if (mAppToken != null && !mAppToken.appFullscreen) {
8691 return false;
8692 }
8693 if (onlyOpaque && mAttrs.format != PixelFormat.OPAQUE) {
8694 return false;
8695 }
8696 final Rect frame = shownFrame ? mShownFrame : mFrame;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008697
8698 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
8699 return frame.left <= mCompatibleScreenFrame.left &&
8700 frame.top <= mCompatibleScreenFrame.top &&
8701 frame.right >= mCompatibleScreenFrame.right &&
8702 frame.bottom >= mCompatibleScreenFrame.bottom;
8703 } else {
8704 return frame.left <= 0 && frame.top <= 0
8705 && frame.right >= screenWidth
8706 && frame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008707 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008708 }
Romain Guy06882f82009-06-10 13:36:04 -07008709
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008710 /**
Dianne Hackborn25994b42009-09-04 14:21:19 -07008711 * Return true if the window is opaque and fully drawn. This indicates
8712 * it may obscure windows behind it.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008713 */
8714 boolean isOpaqueDrawn() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07008715 return (mAttrs.format == PixelFormat.OPAQUE
8716 || mAttrs.type == TYPE_WALLPAPER)
8717 && mSurface != null && mAnimation == null
8718 && (mAppToken == null || mAppToken.animation == null)
8719 && !mDrawPending && !mCommitDrawPending;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008720 }
8721
8722 boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
8723 return
8724 // only if the application is requesting compatible window
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008725 (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
8726 // only if it's visible
8727 mHasDrawn && mViewVisibility == View.VISIBLE &&
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008728 // and only if the application fills the compatible screen
8729 mFrame.left <= mCompatibleScreenFrame.left &&
8730 mFrame.top <= mCompatibleScreenFrame.top &&
8731 mFrame.right >= mCompatibleScreenFrame.right &&
8732 mFrame.bottom >= mCompatibleScreenFrame.bottom &&
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008733 // and starting window do not need background filler
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008734 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008735 }
8736
8737 boolean isFullscreen(int screenWidth, int screenHeight) {
8738 return mFrame.left <= 0 && mFrame.top <= 0 &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07008739 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008740 }
8741
8742 void removeLocked() {
8743 if (mAttachedWindow != null) {
8744 mAttachedWindow.mChildWindows.remove(this);
8745 }
8746 destroySurfaceLocked();
8747 mSession.windowRemovedLocked();
8748 try {
8749 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
8750 } catch (RuntimeException e) {
8751 // Ignore if it has already been removed (usually because
8752 // we are doing this as part of processing a death note.)
8753 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07008754
8755 if (ENABLE_NATIVE_INPUT_DISPATCH) {
8756 if (mInputChannel != null) {
8757 mInputManager.unregisterInputChannel(mInputChannel);
8758
8759 mInputChannel.dispose();
8760 mInputChannel = null;
8761 }
8762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008763 }
8764
8765 private class DeathRecipient implements IBinder.DeathRecipient {
8766 public void binderDied() {
8767 try {
8768 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008769 WindowState win = windowForClientLocked(mSession, mClient, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008770 Slog.i(TAG, "WIN DEATH: " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008771 if (win != null) {
8772 removeWindowLocked(mSession, win);
8773 }
8774 }
8775 } catch (IllegalArgumentException ex) {
8776 // This will happen if the window has already been
8777 // removed.
8778 }
8779 }
8780 }
8781
8782 /** Returns true if this window desires key events. */
8783 public final boolean canReceiveKeys() {
8784 return isVisibleOrAdding()
8785 && (mViewVisibility == View.VISIBLE)
8786 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
8787 }
8788
8789 public boolean hasDrawnLw() {
8790 return mHasDrawn;
8791 }
8792
8793 public boolean showLw(boolean doAnimation) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008794 return showLw(doAnimation, true);
8795 }
8796
8797 boolean showLw(boolean doAnimation, boolean requestAnim) {
8798 if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
8799 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008800 }
Dianne Hackbornb601ce12010-03-01 23:36:02 -08008801 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008802 if (doAnimation) {
8803 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
8804 + mPolicyVisibility + " mAnimation=" + mAnimation);
8805 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8806 doAnimation = false;
8807 } else if (mPolicyVisibility && mAnimation == null) {
8808 // Check for the case where we are currently visible and
8809 // not animating; we do not want to do animation at such a
8810 // point to become visible when we already are.
8811 doAnimation = false;
8812 }
8813 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008814 mPolicyVisibility = true;
8815 mPolicyVisibilityAfterAnim = true;
8816 if (doAnimation) {
8817 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
8818 }
8819 if (requestAnim) {
8820 requestAnimationLocked(0);
8821 }
8822 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008823 }
8824
8825 public boolean hideLw(boolean doAnimation) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008826 return hideLw(doAnimation, true);
8827 }
8828
8829 boolean hideLw(boolean doAnimation, boolean requestAnim) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008830 if (doAnimation) {
8831 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8832 doAnimation = false;
8833 }
8834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008835 boolean current = doAnimation ? mPolicyVisibilityAfterAnim
8836 : mPolicyVisibility;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008837 if (!current) {
8838 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008839 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008840 if (doAnimation) {
8841 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
8842 if (mAnimation == null) {
8843 doAnimation = false;
8844 }
8845 }
8846 if (doAnimation) {
8847 mPolicyVisibilityAfterAnim = false;
8848 } else {
Dianne Hackbornb601ce12010-03-01 23:36:02 -08008849 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008850 mPolicyVisibilityAfterAnim = false;
8851 mPolicyVisibility = false;
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -08008852 // Window is no longer visible -- make sure if we were waiting
8853 // for it to be displayed before enabling the display, that
8854 // we allow the display to be enabled now.
8855 enableScreenIfNeededLocked();
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008856 if (mCurrentFocus == this) {
8857 mFocusMayChange = true;
8858 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008859 }
8860 if (requestAnim) {
8861 requestAnimationLocked(0);
8862 }
8863 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008864 }
8865
8866 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008867 pw.print(prefix); pw.print("mSession="); pw.print(mSession);
8868 pw.print(" mClient="); pw.println(mClient.asBinder());
8869 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
8870 if (mAttachedWindow != null || mLayoutAttached) {
8871 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
8872 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
8873 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07008874 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
8875 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
8876 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008877 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
8878 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008879 }
8880 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
8881 pw.print(" mSubLayer="); pw.print(mSubLayer);
8882 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
8883 pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
8884 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
8885 pw.print("="); pw.print(mAnimLayer);
8886 pw.print(" mLastLayer="); pw.println(mLastLayer);
8887 if (mSurface != null) {
8888 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
Dianne Hackborn16064f92010-03-25 00:47:24 -07008889 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
8890 pw.print(" layer="); pw.print(mSurfaceLayer);
8891 pw.print(" alpha="); pw.print(mSurfaceAlpha);
8892 pw.print(" rect=("); pw.print(mSurfaceX);
8893 pw.print(","); pw.print(mSurfaceY);
8894 pw.print(") "); pw.print(mSurfaceW);
8895 pw.print(" x "); pw.println(mSurfaceH);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008896 }
8897 pw.print(prefix); pw.print("mToken="); pw.println(mToken);
8898 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
8899 if (mAppToken != null) {
8900 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
8901 }
8902 if (mTargetAppToken != null) {
8903 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
8904 }
8905 pw.print(prefix); pw.print("mViewVisibility=0x");
8906 pw.print(Integer.toHexString(mViewVisibility));
8907 pw.print(" mLastHidden="); pw.print(mLastHidden);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008908 pw.print(" mHaveFrame="); pw.print(mHaveFrame);
8909 pw.print(" mObscured="); pw.println(mObscured);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008910 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
8911 pw.print(prefix); pw.print("mPolicyVisibility=");
8912 pw.print(mPolicyVisibility);
8913 pw.print(" mPolicyVisibilityAfterAnim=");
8914 pw.print(mPolicyVisibilityAfterAnim);
8915 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
8916 }
Dianne Hackborn9b52a212009-12-11 14:51:35 -08008917 if (!mRelayoutCalled) {
8918 pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
8919 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008920 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008921 pw.print(" h="); pw.print(mRequestedHeight);
8922 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008923 if (mXOffset != 0 || mYOffset != 0) {
8924 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
8925 pw.print(" y="); pw.println(mYOffset);
8926 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008927 pw.print(prefix); pw.print("mGivenContentInsets=");
8928 mGivenContentInsets.printShortString(pw);
8929 pw.print(" mGivenVisibleInsets=");
8930 mGivenVisibleInsets.printShortString(pw);
8931 pw.println();
8932 if (mTouchableInsets != 0 || mGivenInsetsPending) {
8933 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
8934 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
8935 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008936 pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008937 pw.print(prefix); pw.print("mShownFrame=");
8938 mShownFrame.printShortString(pw);
8939 pw.print(" last="); mLastShownFrame.printShortString(pw);
8940 pw.println();
8941 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
8942 pw.print(" last="); mLastFrame.printShortString(pw);
8943 pw.println();
8944 pw.print(prefix); pw.print("mContainingFrame=");
8945 mContainingFrame.printShortString(pw);
8946 pw.print(" mDisplayFrame=");
8947 mDisplayFrame.printShortString(pw);
8948 pw.println();
8949 pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
8950 pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
8951 pw.println();
8952 pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
8953 pw.print(" last="); mLastContentInsets.printShortString(pw);
8954 pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
8955 pw.print(" last="); mLastVisibleInsets.printShortString(pw);
8956 pw.println();
8957 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
8958 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
8959 pw.print(" mAlpha="); pw.print(mAlpha);
8960 pw.print(" mLastAlpha="); pw.println(mLastAlpha);
8961 }
8962 if (mAnimating || mLocalAnimating || mAnimationIsEntrance
8963 || mAnimation != null) {
8964 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
8965 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
8966 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
8967 pw.print(" mAnimation="); pw.println(mAnimation);
8968 }
8969 if (mHasTransformation || mHasLocalTransformation) {
8970 pw.print(prefix); pw.print("XForm: has=");
8971 pw.print(mHasTransformation);
8972 pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
8973 pw.print(" "); mTransformation.printShortString(pw);
8974 pw.println();
8975 }
8976 pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
8977 pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
8978 pw.print(" mReadyToShow="); pw.print(mReadyToShow);
8979 pw.print(" mHasDrawn="); pw.println(mHasDrawn);
8980 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
8981 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
8982 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
8983 pw.print(" mDestroying="); pw.print(mDestroying);
8984 pw.print(" mRemoved="); pw.println(mRemoved);
8985 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07008986 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008987 pw.print(prefix); pw.print("mOrientationChanging=");
8988 pw.print(mOrientationChanging);
Dianne Hackborn93e462b2009-09-15 22:50:40 -07008989 pw.print(" mAppFreezing="); pw.print(mAppFreezing);
8990 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008991 }
Mitsuru Oshima589cebe2009-07-22 20:38:58 -07008992 if (mHScale != 1 || mVScale != 1) {
8993 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
8994 pw.print(" mVScale="); pw.println(mVScale);
8995 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07008996 if (mWallpaperX != -1 || mWallpaperY != -1) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008997 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
8998 pw.print(" mWallpaperY="); pw.println(mWallpaperY);
8999 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08009000 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
9001 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
9002 pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
9003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009004 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07009005
9006 String makeInputChannelName() {
9007 return Integer.toHexString(System.identityHashCode(this))
9008 + " " + mAttrs.getTitle();
9009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009010
9011 @Override
9012 public String toString() {
9013 return "Window{"
9014 + Integer.toHexString(System.identityHashCode(this))
9015 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
9016 }
9017 }
Romain Guy06882f82009-06-10 13:36:04 -07009018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009019 // -------------------------------------------------------------
9020 // Window Token State
9021 // -------------------------------------------------------------
9022
9023 class WindowToken {
9024 // The actual token.
9025 final IBinder token;
9026
9027 // The type of window this token is for, as per WindowManager.LayoutParams.
9028 final int windowType;
Romain Guy06882f82009-06-10 13:36:04 -07009029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009030 // Set if this token was explicitly added by a client, so should
9031 // not be removed when all windows are removed.
9032 final boolean explicit;
Romain Guy06882f82009-06-10 13:36:04 -07009033
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009034 // For printing.
9035 String stringName;
Romain Guy06882f82009-06-10 13:36:04 -07009036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009037 // If this is an AppWindowToken, this is non-null.
9038 AppWindowToken appWindowToken;
Romain Guy06882f82009-06-10 13:36:04 -07009039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009040 // All of the windows associated with this token.
9041 final ArrayList<WindowState> windows = new ArrayList<WindowState>();
9042
9043 // Is key dispatching paused for this token?
9044 boolean paused = false;
9045
9046 // Should this token's windows be hidden?
9047 boolean hidden;
9048
9049 // Temporary for finding which tokens no longer have visible windows.
9050 boolean hasVisible;
9051
Dianne Hackborna8f60182009-09-01 19:01:50 -07009052 // Set to true when this token is in a pending transaction where it
9053 // will be shown.
9054 boolean waitingToShow;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009055
Dianne Hackborna8f60182009-09-01 19:01:50 -07009056 // Set to true when this token is in a pending transaction where it
9057 // will be hidden.
9058 boolean waitingToHide;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009059
Dianne Hackborna8f60182009-09-01 19:01:50 -07009060 // Set to true when this token is in a pending transaction where its
9061 // windows will be put to the bottom of the list.
9062 boolean sendingToBottom;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009063
Dianne Hackborna8f60182009-09-01 19:01:50 -07009064 // Set to true when this token is in a pending transaction where its
9065 // windows will be put to the top of the list.
9066 boolean sendingToTop;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009068 WindowToken(IBinder _token, int type, boolean _explicit) {
9069 token = _token;
9070 windowType = type;
9071 explicit = _explicit;
9072 }
9073
9074 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009075 pw.print(prefix); pw.print("token="); pw.println(token);
9076 pw.print(prefix); pw.print("windows="); pw.println(windows);
9077 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
9078 pw.print(" hidden="); pw.print(hidden);
9079 pw.print(" hasVisible="); pw.println(hasVisible);
Dianne Hackborna8f60182009-09-01 19:01:50 -07009080 if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
9081 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
9082 pw.print(" waitingToHide="); pw.print(waitingToHide);
9083 pw.print(" sendingToBottom="); pw.print(sendingToBottom);
9084 pw.print(" sendingToTop="); pw.println(sendingToTop);
9085 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009086 }
9087
9088 @Override
9089 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009090 if (stringName == null) {
9091 StringBuilder sb = new StringBuilder();
9092 sb.append("WindowToken{");
9093 sb.append(Integer.toHexString(System.identityHashCode(this)));
9094 sb.append(" token="); sb.append(token); sb.append('}');
9095 stringName = sb.toString();
9096 }
9097 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009098 }
9099 };
9100
9101 class AppWindowToken extends WindowToken {
9102 // Non-null only for application tokens.
9103 final IApplicationToken appToken;
9104
9105 // All of the windows and child windows that are included in this
9106 // application token. Note this list is NOT sorted!
9107 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
9108
9109 int groupId = -1;
9110 boolean appFullscreen;
9111 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Jeff Brown349703e2010-06-22 01:27:15 -07009112
9113 // The input dispatching timeout for this application token in nanoseconds.
9114 long inputDispatchingTimeoutNanos;
Romain Guy06882f82009-06-10 13:36:04 -07009115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009116 // These are used for determining when all windows associated with
9117 // an activity have been drawn, so they can be made visible together
9118 // at the same time.
9119 int lastTransactionSequence = mTransactionSequence-1;
9120 int numInterestingWindows;
9121 int numDrawnWindows;
9122 boolean inPendingTransaction;
9123 boolean allDrawn;
Romain Guy06882f82009-06-10 13:36:04 -07009124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 // Is this token going to be hidden in a little while? If so, it
9126 // won't be taken into account for setting the screen orientation.
9127 boolean willBeHidden;
Romain Guy06882f82009-06-10 13:36:04 -07009128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009129 // Is this window's surface needed? This is almost like hidden, except
9130 // it will sometimes be true a little earlier: when the token has
9131 // been shown, but is still waiting for its app transition to execute
9132 // before making its windows shown.
9133 boolean hiddenRequested;
Romain Guy06882f82009-06-10 13:36:04 -07009134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009135 // Have we told the window clients to hide themselves?
9136 boolean clientHidden;
Romain Guy06882f82009-06-10 13:36:04 -07009137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009138 // Last visibility state we reported to the app token.
9139 boolean reportedVisible;
9140
9141 // Set to true when the token has been removed from the window mgr.
9142 boolean removed;
9143
9144 // Have we been asked to have this token keep the screen frozen?
9145 boolean freezingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07009146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009147 boolean animating;
9148 Animation animation;
9149 boolean hasTransformation;
9150 final Transformation transformation = new Transformation();
Romain Guy06882f82009-06-10 13:36:04 -07009151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009152 // Offset to the window of all layers in the token, for use by
9153 // AppWindowToken animations.
9154 int animLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -07009155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009156 // Information about an application starting window if displayed.
9157 StartingData startingData;
9158 WindowState startingWindow;
9159 View startingView;
9160 boolean startingDisplayed;
9161 boolean startingMoved;
9162 boolean firstWindowDrawn;
9163
9164 AppWindowToken(IApplicationToken _token) {
9165 super(_token.asBinder(),
9166 WindowManager.LayoutParams.TYPE_APPLICATION, true);
9167 appWindowToken = this;
9168 appToken = _token;
9169 }
Romain Guy06882f82009-06-10 13:36:04 -07009170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009171 public void setAnimation(Animation anim) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009172 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 TAG, "Setting animation in " + this + ": " + anim);
9174 animation = anim;
9175 animating = false;
9176 anim.restrictDuration(MAX_ANIMATION_DURATION);
9177 anim.scaleCurrentDuration(mTransitionAnimationScale);
9178 int zorder = anim.getZAdjustment();
9179 int adj = 0;
9180 if (zorder == Animation.ZORDER_TOP) {
9181 adj = TYPE_LAYER_OFFSET;
9182 } else if (zorder == Animation.ZORDER_BOTTOM) {
9183 adj = -TYPE_LAYER_OFFSET;
9184 }
Romain Guy06882f82009-06-10 13:36:04 -07009185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 if (animLayerAdjustment != adj) {
9187 animLayerAdjustment = adj;
9188 updateLayers();
9189 }
9190 }
Romain Guy06882f82009-06-10 13:36:04 -07009191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009192 public void setDummyAnimation() {
9193 if (animation == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009194 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009195 TAG, "Setting dummy animation in " + this);
9196 animation = sDummyAnimation;
9197 }
9198 }
9199
9200 public void clearAnimation() {
9201 if (animation != null) {
9202 animation = null;
9203 animating = true;
9204 }
9205 }
Romain Guy06882f82009-06-10 13:36:04 -07009206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009207 void updateLayers() {
9208 final int N = allAppWindows.size();
9209 final int adj = animLayerAdjustment;
9210 for (int i=0; i<N; i++) {
9211 WindowState w = allAppWindows.get(i);
9212 w.mAnimLayer = w.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009213 if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009214 + w.mAnimLayer);
9215 if (w == mInputMethodTarget) {
9216 setInputMethodAnimLayerAdjustment(adj);
9217 }
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009218 if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07009219 setWallpaperAnimLayerAdjustmentLocked(adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07009220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 }
9222 }
Romain Guy06882f82009-06-10 13:36:04 -07009223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009224 void sendAppVisibilityToClients() {
9225 final int N = allAppWindows.size();
9226 for (int i=0; i<N; i++) {
9227 WindowState win = allAppWindows.get(i);
9228 if (win == startingWindow && clientHidden) {
9229 // Don't hide the starting window.
9230 continue;
9231 }
9232 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009233 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009234 "Setting visibility of " + win + ": " + (!clientHidden));
9235 win.mClient.dispatchAppVisibility(!clientHidden);
9236 } catch (RemoteException e) {
9237 }
9238 }
9239 }
Romain Guy06882f82009-06-10 13:36:04 -07009240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009241 void showAllWindowsLocked() {
9242 final int NW = allAppWindows.size();
9243 for (int i=0; i<NW; i++) {
9244 WindowState w = allAppWindows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009245 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009246 "performing show on: " + w);
9247 w.performShowLocked();
9248 }
9249 }
Romain Guy06882f82009-06-10 13:36:04 -07009250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009251 // This must be called while inside a transaction.
9252 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -08009253 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009254 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07009255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009256 if (animation == sDummyAnimation) {
9257 // This guy is going to animate, but not yet. For now count
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009258 // it as not animating for purposes of scheduling transactions;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009259 // when it is really time to animate, this will be set to
9260 // a real animation and the next call will execute normally.
9261 return false;
9262 }
Romain Guy06882f82009-06-10 13:36:04 -07009263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009264 if ((allDrawn || animating || startingDisplayed) && animation != null) {
9265 if (!animating) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009266 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009267 TAG, "Starting animation in " + this +
9268 " @ " + currentTime + ": dw=" + dw + " dh=" + dh
9269 + " scale=" + mTransitionAnimationScale
9270 + " allDrawn=" + allDrawn + " animating=" + animating);
9271 animation.initialize(dw, dh, dw, dh);
9272 animation.setStartTime(currentTime);
9273 animating = true;
9274 }
9275 transformation.clear();
9276 final boolean more = animation.getTransformation(
9277 currentTime, transformation);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009278 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009279 TAG, "Stepped animation in " + this +
9280 ": more=" + more + ", xform=" + transformation);
9281 if (more) {
9282 // we're done!
9283 hasTransformation = true;
9284 return true;
9285 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009286 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287 TAG, "Finished animation in " + this +
9288 " @ " + currentTime);
9289 animation = null;
9290 }
9291 } else if (animation != null) {
9292 // If the display is frozen, and there is a pending animation,
9293 // clear it and make sure we run the cleanup code.
9294 animating = true;
9295 animation = null;
9296 }
9297
9298 hasTransformation = false;
Romain Guy06882f82009-06-10 13:36:04 -07009299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009300 if (!animating) {
9301 return false;
9302 }
9303
9304 clearAnimation();
9305 animating = false;
9306 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
9307 moveInputMethodWindowsIfNeededLocked(true);
9308 }
Romain Guy06882f82009-06-10 13:36:04 -07009309
Joe Onorato8a9b2202010-02-26 18:56:32 -08009310 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009311 TAG, "Animation done in " + this
9312 + ": reportedVisible=" + reportedVisible);
9313
9314 transformation.clear();
9315 if (animLayerAdjustment != 0) {
9316 animLayerAdjustment = 0;
9317 updateLayers();
9318 }
Romain Guy06882f82009-06-10 13:36:04 -07009319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009320 final int N = windows.size();
9321 for (int i=0; i<N; i++) {
9322 ((WindowState)windows.get(i)).finishExit();
9323 }
9324 updateReportedVisibilityLocked();
Romain Guy06882f82009-06-10 13:36:04 -07009325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 return false;
9327 }
9328
9329 void updateReportedVisibilityLocked() {
9330 if (appToken == null) {
9331 return;
9332 }
Romain Guy06882f82009-06-10 13:36:04 -07009333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009334 int numInteresting = 0;
9335 int numVisible = 0;
9336 boolean nowGone = true;
Romain Guy06882f82009-06-10 13:36:04 -07009337
Joe Onorato8a9b2202010-02-26 18:56:32 -08009338 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009339 final int N = allAppWindows.size();
9340 for (int i=0; i<N; i++) {
9341 WindowState win = allAppWindows.get(i);
Dianne Hackborn6cf67fa2009-12-21 16:46:34 -08009342 if (win == startingWindow || win.mAppFreezing
The Android Open Source Project727cec02010-04-08 11:35:37 -07009343 || win.mViewVisibility != View.VISIBLE
9344 || win.mAttrs.type == TYPE_APPLICATION_STARTING) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009345 continue;
9346 }
9347 if (DEBUG_VISIBILITY) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009348 Slog.v(TAG, "Win " + win + ": isDrawn="
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009349 + win.isDrawnLw()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009350 + ", isAnimating=" + win.isAnimating());
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009351 if (!win.isDrawnLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009352 Slog.v(TAG, "Not displayed: s=" + win.mSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009353 + " pv=" + win.mPolicyVisibility
9354 + " dp=" + win.mDrawPending
9355 + " cdp=" + win.mCommitDrawPending
9356 + " ah=" + win.mAttachedHidden
9357 + " th="
9358 + (win.mAppToken != null
9359 ? win.mAppToken.hiddenRequested : false)
9360 + " a=" + win.mAnimating);
9361 }
9362 }
9363 numInteresting++;
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009364 if (win.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009365 if (!win.isAnimating()) {
9366 numVisible++;
9367 }
9368 nowGone = false;
9369 } else if (win.isAnimating()) {
9370 nowGone = false;
9371 }
9372 }
Romain Guy06882f82009-06-10 13:36:04 -07009373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009374 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009375 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009376 + numInteresting + " visible=" + numVisible);
9377 if (nowVisible != reportedVisible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009378 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009379 TAG, "Visibility changed in " + this
9380 + ": vis=" + nowVisible);
9381 reportedVisible = nowVisible;
9382 Message m = mH.obtainMessage(
9383 H.REPORT_APPLICATION_TOKEN_WINDOWS,
9384 nowVisible ? 1 : 0,
9385 nowGone ? 1 : 0,
9386 this);
9387 mH.sendMessage(m);
9388 }
9389 }
Romain Guy06882f82009-06-10 13:36:04 -07009390
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009391 WindowState findMainWindow() {
9392 int j = windows.size();
9393 while (j > 0) {
9394 j--;
9395 WindowState win = windows.get(j);
9396 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
9397 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
9398 return win;
9399 }
9400 }
9401 return null;
9402 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009404 void dump(PrintWriter pw, String prefix) {
9405 super.dump(pw, prefix);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009406 if (appToken != null) {
9407 pw.print(prefix); pw.println("app=true");
9408 }
9409 if (allAppWindows.size() > 0) {
9410 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
9411 }
9412 pw.print(prefix); pw.print("groupId="); pw.print(groupId);
Dianne Hackborna8f60182009-09-01 19:01:50 -07009413 pw.print(" appFullscreen="); pw.print(appFullscreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009414 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
9415 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
9416 pw.print(" clientHidden="); pw.print(clientHidden);
9417 pw.print(" willBeHidden="); pw.print(willBeHidden);
9418 pw.print(" reportedVisible="); pw.println(reportedVisible);
9419 if (paused || freezingScreen) {
9420 pw.print(prefix); pw.print("paused="); pw.print(paused);
9421 pw.print(" freezingScreen="); pw.println(freezingScreen);
9422 }
9423 if (numInterestingWindows != 0 || numDrawnWindows != 0
9424 || inPendingTransaction || allDrawn) {
9425 pw.print(prefix); pw.print("numInterestingWindows=");
9426 pw.print(numInterestingWindows);
9427 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
9428 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
9429 pw.print(" allDrawn="); pw.println(allDrawn);
9430 }
9431 if (animating || animation != null) {
9432 pw.print(prefix); pw.print("animating="); pw.print(animating);
9433 pw.print(" animation="); pw.println(animation);
9434 }
9435 if (animLayerAdjustment != 0) {
9436 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
9437 }
9438 if (hasTransformation) {
9439 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
9440 pw.print(" transformation="); transformation.printShortString(pw);
9441 pw.println();
9442 }
9443 if (startingData != null || removed || firstWindowDrawn) {
9444 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
9445 pw.print(" removed="); pw.print(removed);
9446 pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
9447 }
9448 if (startingWindow != null || startingView != null
9449 || startingDisplayed || startingMoved) {
9450 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
9451 pw.print(" startingView="); pw.print(startingView);
9452 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
9453 pw.print(" startingMoved"); pw.println(startingMoved);
9454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009455 }
9456
9457 @Override
9458 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009459 if (stringName == null) {
9460 StringBuilder sb = new StringBuilder();
9461 sb.append("AppWindowToken{");
9462 sb.append(Integer.toHexString(System.identityHashCode(this)));
9463 sb.append(" token="); sb.append(token); sb.append('}');
9464 stringName = sb.toString();
9465 }
9466 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009467 }
9468 }
Romain Guy06882f82009-06-10 13:36:04 -07009469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009470 // -------------------------------------------------------------
9471 // DummyAnimation
9472 // -------------------------------------------------------------
9473
9474 // This is an animation that does nothing: it just immediately finishes
9475 // itself every time it is called. It is used as a stub animation in cases
9476 // where we want to synchronize multiple things that may be animating.
9477 static final class DummyAnimation extends Animation {
9478 public boolean getTransformation(long currentTime, Transformation outTransformation) {
9479 return false;
9480 }
9481 }
9482 static final Animation sDummyAnimation = new DummyAnimation();
Romain Guy06882f82009-06-10 13:36:04 -07009483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009484 // -------------------------------------------------------------
9485 // Async Handler
9486 // -------------------------------------------------------------
9487
9488 static final class StartingData {
9489 final String pkg;
9490 final int theme;
9491 final CharSequence nonLocalizedLabel;
9492 final int labelRes;
9493 final int icon;
Romain Guy06882f82009-06-10 13:36:04 -07009494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009495 StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
9496 int _labelRes, int _icon) {
9497 pkg = _pkg;
9498 theme = _theme;
9499 nonLocalizedLabel = _nonLocalizedLabel;
9500 labelRes = _labelRes;
9501 icon = _icon;
9502 }
9503 }
9504
9505 private final class H extends Handler {
9506 public static final int REPORT_FOCUS_CHANGE = 2;
9507 public static final int REPORT_LOSING_FOCUS = 3;
9508 public static final int ANIMATE = 4;
9509 public static final int ADD_STARTING = 5;
9510 public static final int REMOVE_STARTING = 6;
9511 public static final int FINISHED_STARTING = 7;
9512 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009513 public static final int WINDOW_FREEZE_TIMEOUT = 11;
9514 public static final int HOLD_SCREEN_CHANGED = 12;
9515 public static final int APP_TRANSITION_TIMEOUT = 13;
9516 public static final int PERSIST_ANIMATION_SCALE = 14;
9517 public static final int FORCE_GC = 15;
9518 public static final int ENABLE_SCREEN = 16;
9519 public static final int APP_FREEZE_TIMEOUT = 17;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009520 public static final int SEND_NEW_CONFIGURATION = 18;
Romain Guy06882f82009-06-10 13:36:04 -07009521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009522 private Session mLastReportedHold;
Romain Guy06882f82009-06-10 13:36:04 -07009523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009524 public H() {
9525 }
Romain Guy06882f82009-06-10 13:36:04 -07009526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009527 @Override
9528 public void handleMessage(Message msg) {
9529 switch (msg.what) {
9530 case REPORT_FOCUS_CHANGE: {
9531 WindowState lastFocus;
9532 WindowState newFocus;
Romain Guy06882f82009-06-10 13:36:04 -07009533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009534 synchronized(mWindowMap) {
9535 lastFocus = mLastFocus;
9536 newFocus = mCurrentFocus;
9537 if (lastFocus == newFocus) {
9538 // Focus is not changing, so nothing to do.
9539 return;
9540 }
9541 mLastFocus = newFocus;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009542 //Slog.i(TAG, "Focus moving from " + lastFocus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009543 // + " to " + newFocus);
9544 if (newFocus != null && lastFocus != null
9545 && !newFocus.isDisplayedLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009546 //Slog.i(TAG, "Delaying loss of focus...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009547 mLosingFocus.add(lastFocus);
9548 lastFocus = null;
9549 }
9550 }
9551
9552 if (lastFocus != newFocus) {
9553 //System.out.println("Changing focus from " + lastFocus
9554 // + " to " + newFocus);
9555 if (newFocus != null) {
9556 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009557 //Slog.i(TAG, "Gaining focus: " + newFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009558 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
9559 } catch (RemoteException e) {
9560 // Ignore if process has died.
9561 }
9562 }
9563
9564 if (lastFocus != null) {
9565 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009566 //Slog.i(TAG, "Losing focus: " + lastFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009567 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
9568 } catch (RemoteException e) {
9569 // Ignore if process has died.
9570 }
9571 }
9572 }
9573 } break;
9574
9575 case REPORT_LOSING_FOCUS: {
9576 ArrayList<WindowState> losers;
Romain Guy06882f82009-06-10 13:36:04 -07009577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009578 synchronized(mWindowMap) {
9579 losers = mLosingFocus;
9580 mLosingFocus = new ArrayList<WindowState>();
9581 }
9582
9583 final int N = losers.size();
9584 for (int i=0; i<N; i++) {
9585 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009586 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009587 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
9588 } catch (RemoteException e) {
9589 // Ignore if process has died.
9590 }
9591 }
9592 } break;
9593
9594 case ANIMATE: {
9595 synchronized(mWindowMap) {
9596 mAnimationPending = false;
9597 performLayoutAndPlaceSurfacesLocked();
9598 }
9599 } break;
9600
9601 case ADD_STARTING: {
9602 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9603 final StartingData sd = wtoken.startingData;
9604
9605 if (sd == null) {
9606 // Animation has been canceled... do nothing.
9607 return;
9608 }
Romain Guy06882f82009-06-10 13:36:04 -07009609
Joe Onorato8a9b2202010-02-26 18:56:32 -08009610 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009611 + wtoken + ": pkg=" + sd.pkg);
Romain Guy06882f82009-06-10 13:36:04 -07009612
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009613 View view = null;
9614 try {
9615 view = mPolicy.addStartingWindow(
9616 wtoken.token, sd.pkg,
9617 sd.theme, sd.nonLocalizedLabel, sd.labelRes,
9618 sd.icon);
9619 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009620 Slog.w(TAG, "Exception when adding starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009621 }
9622
9623 if (view != null) {
9624 boolean abort = false;
9625
9626 synchronized(mWindowMap) {
9627 if (wtoken.removed || wtoken.startingData == null) {
9628 // If the window was successfully added, then
9629 // we need to remove it.
9630 if (wtoken.startingWindow != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009631 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009632 "Aborted starting " + wtoken
9633 + ": removed=" + wtoken.removed
9634 + " startingData=" + wtoken.startingData);
9635 wtoken.startingWindow = null;
9636 wtoken.startingData = null;
9637 abort = true;
9638 }
9639 } else {
9640 wtoken.startingView = view;
9641 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009642 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009643 "Added starting " + wtoken
9644 + ": startingWindow="
9645 + wtoken.startingWindow + " startingView="
9646 + wtoken.startingView);
9647 }
9648
9649 if (abort) {
9650 try {
9651 mPolicy.removeStartingWindow(wtoken.token, view);
9652 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009653 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009654 }
9655 }
9656 }
9657 } break;
9658
9659 case REMOVE_STARTING: {
9660 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9661 IBinder token = null;
9662 View view = null;
9663 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009664 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009665 + wtoken + ": startingWindow="
9666 + wtoken.startingWindow + " startingView="
9667 + wtoken.startingView);
9668 if (wtoken.startingWindow != null) {
9669 view = wtoken.startingView;
9670 token = wtoken.token;
9671 wtoken.startingData = null;
9672 wtoken.startingView = null;
9673 wtoken.startingWindow = null;
9674 }
9675 }
9676 if (view != null) {
9677 try {
9678 mPolicy.removeStartingWindow(token, view);
9679 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009680 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009681 }
9682 }
9683 } break;
9684
9685 case FINISHED_STARTING: {
9686 IBinder token = null;
9687 View view = null;
9688 while (true) {
9689 synchronized (mWindowMap) {
9690 final int N = mFinishedStarting.size();
9691 if (N <= 0) {
9692 break;
9693 }
9694 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
9695
Joe Onorato8a9b2202010-02-26 18:56:32 -08009696 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009697 "Finished starting " + wtoken
9698 + ": startingWindow=" + wtoken.startingWindow
9699 + " startingView=" + wtoken.startingView);
9700
9701 if (wtoken.startingWindow == null) {
9702 continue;
9703 }
9704
9705 view = wtoken.startingView;
9706 token = wtoken.token;
9707 wtoken.startingData = null;
9708 wtoken.startingView = null;
9709 wtoken.startingWindow = null;
9710 }
9711
9712 try {
9713 mPolicy.removeStartingWindow(token, view);
9714 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009715 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009716 }
9717 }
9718 } break;
9719
9720 case REPORT_APPLICATION_TOKEN_WINDOWS: {
9721 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9722
9723 boolean nowVisible = msg.arg1 != 0;
9724 boolean nowGone = msg.arg2 != 0;
9725
9726 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009727 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009728 TAG, "Reporting visible in " + wtoken
9729 + " visible=" + nowVisible
9730 + " gone=" + nowGone);
9731 if (nowVisible) {
9732 wtoken.appToken.windowsVisible();
9733 } else {
9734 wtoken.appToken.windowsGone();
9735 }
9736 } catch (RemoteException ex) {
9737 }
9738 } break;
Romain Guy06882f82009-06-10 13:36:04 -07009739
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009740 case WINDOW_FREEZE_TIMEOUT: {
9741 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009742 Slog.w(TAG, "Window freeze timeout expired.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009743 int i = mWindows.size();
9744 while (i > 0) {
9745 i--;
9746 WindowState w = (WindowState)mWindows.get(i);
9747 if (w.mOrientationChanging) {
9748 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009749 Slog.w(TAG, "Force clearing orientation change: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009750 }
9751 }
9752 performLayoutAndPlaceSurfacesLocked();
9753 }
9754 break;
9755 }
Romain Guy06882f82009-06-10 13:36:04 -07009756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 case HOLD_SCREEN_CHANGED: {
9758 Session oldHold;
9759 Session newHold;
9760 synchronized (mWindowMap) {
9761 oldHold = mLastReportedHold;
9762 newHold = (Session)msg.obj;
9763 mLastReportedHold = newHold;
9764 }
Romain Guy06882f82009-06-10 13:36:04 -07009765
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009766 if (oldHold != newHold) {
9767 try {
9768 if (oldHold != null) {
9769 mBatteryStats.noteStopWakelock(oldHold.mUid,
9770 "window",
9771 BatteryStats.WAKE_TYPE_WINDOW);
9772 }
9773 if (newHold != null) {
9774 mBatteryStats.noteStartWakelock(newHold.mUid,
9775 "window",
9776 BatteryStats.WAKE_TYPE_WINDOW);
9777 }
9778 } catch (RemoteException e) {
9779 }
9780 }
9781 break;
9782 }
Romain Guy06882f82009-06-10 13:36:04 -07009783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 case APP_TRANSITION_TIMEOUT: {
9785 synchronized (mWindowMap) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009786 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009787 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 "*** APP TRANSITION TIMEOUT");
9789 mAppTransitionReady = true;
9790 mAppTransitionTimeout = true;
9791 performLayoutAndPlaceSurfacesLocked();
9792 }
9793 }
9794 break;
9795 }
Romain Guy06882f82009-06-10 13:36:04 -07009796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009797 case PERSIST_ANIMATION_SCALE: {
9798 Settings.System.putFloat(mContext.getContentResolver(),
9799 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
9800 Settings.System.putFloat(mContext.getContentResolver(),
9801 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
9802 break;
9803 }
Romain Guy06882f82009-06-10 13:36:04 -07009804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009805 case FORCE_GC: {
9806 synchronized(mWindowMap) {
9807 if (mAnimationPending) {
9808 // If we are animating, don't do the gc now but
9809 // delay a bit so we don't interrupt the animation.
9810 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
9811 2000);
9812 return;
9813 }
9814 // If we are currently rotating the display, it will
9815 // schedule a new message when done.
9816 if (mDisplayFrozen) {
9817 return;
9818 }
9819 mFreezeGcPending = 0;
9820 }
9821 Runtime.getRuntime().gc();
9822 break;
9823 }
Romain Guy06882f82009-06-10 13:36:04 -07009824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009825 case ENABLE_SCREEN: {
9826 performEnableScreen();
9827 break;
9828 }
Romain Guy06882f82009-06-10 13:36:04 -07009829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830 case APP_FREEZE_TIMEOUT: {
9831 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009832 Slog.w(TAG, "App freeze timeout expired.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009833 int i = mAppTokens.size();
9834 while (i > 0) {
9835 i--;
9836 AppWindowToken tok = mAppTokens.get(i);
9837 if (tok.freezingScreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009838 Slog.w(TAG, "Force clearing freeze: " + tok);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 unsetAppFreezingScreenLocked(tok, true, true);
9840 }
9841 }
9842 }
9843 break;
9844 }
Romain Guy06882f82009-06-10 13:36:04 -07009845
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009846 case SEND_NEW_CONFIGURATION: {
9847 removeMessages(SEND_NEW_CONFIGURATION);
9848 sendNewConfiguration();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07009849 break;
9850 }
Romain Guy06882f82009-06-10 13:36:04 -07009851
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009852 }
9853 }
9854 }
9855
9856 // -------------------------------------------------------------
9857 // IWindowManager API
9858 // -------------------------------------------------------------
9859
9860 public IWindowSession openSession(IInputMethodClient client,
9861 IInputContext inputContext) {
9862 if (client == null) throw new IllegalArgumentException("null client");
9863 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07009864 Session session = new Session(client, inputContext);
9865 return session;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009866 }
9867
9868 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
9869 synchronized (mWindowMap) {
9870 // The focus for the client is the window immediately below
9871 // where we would place the input method window.
9872 int idx = findDesiredInputMethodWindowIndexLocked(false);
9873 WindowState imFocus;
9874 if (idx > 0) {
9875 imFocus = (WindowState)mWindows.get(idx-1);
9876 if (imFocus != null) {
9877 if (imFocus.mSession.mClient != null &&
9878 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
9879 return true;
9880 }
9881 }
9882 }
9883 }
9884 return false;
9885 }
Romain Guy06882f82009-06-10 13:36:04 -07009886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009887 // -------------------------------------------------------------
9888 // Internals
9889 // -------------------------------------------------------------
9890
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009891 final WindowState windowForClientLocked(Session session, IWindow client,
9892 boolean throwOnError) {
9893 return windowForClientLocked(session, client.asBinder(), throwOnError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009894 }
Romain Guy06882f82009-06-10 13:36:04 -07009895
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009896 final WindowState windowForClientLocked(Session session, IBinder client,
9897 boolean throwOnError) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009898 WindowState win = mWindowMap.get(client);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009899 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009900 TAG, "Looking up client " + client + ": " + win);
9901 if (win == null) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009902 RuntimeException ex = new IllegalArgumentException(
9903 "Requested window " + client + " does not exist");
9904 if (throwOnError) {
9905 throw ex;
9906 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009907 Slog.w(TAG, "Failed looking up window", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009908 return null;
9909 }
9910 if (session != null && win.mSession != session) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009911 RuntimeException ex = new IllegalArgumentException(
9912 "Requested window " + client + " is in session " +
9913 win.mSession + ", not " + session);
9914 if (throwOnError) {
9915 throw ex;
9916 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009917 Slog.w(TAG, "Failed looking up window", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009918 return null;
9919 }
9920
9921 return win;
9922 }
9923
Dianne Hackborna8f60182009-09-01 19:01:50 -07009924 final void rebuildAppWindowListLocked() {
9925 int NW = mWindows.size();
9926 int i;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009927 int lastWallpaper = -1;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009928 int numRemoved = 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009929
Dianne Hackborna8f60182009-09-01 19:01:50 -07009930 // First remove all existing app windows.
9931 i=0;
9932 while (i < NW) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009933 WindowState w = (WindowState)mWindows.get(i);
9934 if (w.mAppToken != null) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009935 WindowState win = (WindowState)mWindows.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009936 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009937 "Rebuild removing window: " + win);
Dianne Hackborna8f60182009-09-01 19:01:50 -07009938 NW--;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009939 numRemoved++;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009940 continue;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009941 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
9942 && lastWallpaper == i-1) {
9943 lastWallpaper = i;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009944 }
9945 i++;
9946 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009947
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009948 // The wallpaper window(s) typically live at the bottom of the stack,
9949 // so skip them before adding app tokens.
9950 lastWallpaper++;
9951 i = lastWallpaper;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009952
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009953 // First add all of the exiting app tokens... these are no longer
9954 // in the main app list, but still have windows shown. We put them
9955 // in the back because now that the animation is over we no longer
9956 // will care about them.
9957 int NT = mExitingAppTokens.size();
Dianne Hackborna8f60182009-09-01 19:01:50 -07009958 for (int j=0; j<NT; j++) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009959 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
9960 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009961
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009962 // And add in the still active app tokens in Z order.
9963 NT = mAppTokens.size();
9964 for (int j=0; j<NT; j++) {
9965 i = reAddAppWindowsLocked(i, mAppTokens.get(j));
Dianne Hackborna8f60182009-09-01 19:01:50 -07009966 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009967
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009968 i -= lastWallpaper;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009969 if (i != numRemoved) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009970 Slog.w(TAG, "Rebuild removed " + numRemoved
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009971 + " windows but added " + i);
9972 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07009973 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009975 private final void assignLayersLocked() {
9976 int N = mWindows.size();
9977 int curBaseLayer = 0;
9978 int curLayer = 0;
9979 int i;
Romain Guy06882f82009-06-10 13:36:04 -07009980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009981 for (i=0; i<N; i++) {
9982 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009983 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
9984 || (i > 0 && w.mIsWallpaper)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009985 curLayer += WINDOW_LAYER_MULTIPLIER;
9986 w.mLayer = curLayer;
9987 } else {
9988 curBaseLayer = curLayer = w.mBaseLayer;
9989 w.mLayer = curLayer;
9990 }
9991 if (w.mTargetAppToken != null) {
9992 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
9993 } else if (w.mAppToken != null) {
9994 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
9995 } else {
9996 w.mAnimLayer = w.mLayer;
9997 }
9998 if (w.mIsImWindow) {
9999 w.mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -070010000 } else if (w.mIsWallpaper) {
10001 w.mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010002 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010003 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010004 + w.mAnimLayer);
10005 //System.out.println(
10006 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
10007 }
10008 }
10009
10010 private boolean mInLayout = false;
10011 private final void performLayoutAndPlaceSurfacesLocked() {
10012 if (mInLayout) {
Dave Bortcfe65242009-04-09 14:51:04 -070010013 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010014 throw new RuntimeException("Recursive call!");
10015 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010016 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010017 return;
10018 }
10019
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010020 if (mWaitingForConfig) {
10021 // Our configuration has changed (most likely rotation), but we
10022 // don't yet have the complete configuration to report to
10023 // applications. Don't do any window layout until we have it.
10024 return;
10025 }
10026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010027 boolean recoveringMemory = false;
10028 if (mForceRemoves != null) {
10029 recoveringMemory = true;
10030 // Wait a little it for things to settle down, and off we go.
10031 for (int i=0; i<mForceRemoves.size(); i++) {
10032 WindowState ws = mForceRemoves.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010033 Slog.i(TAG, "Force removing: " + ws);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010034 removeWindowInnerLocked(ws.mSession, ws);
10035 }
10036 mForceRemoves = null;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010037 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038 Object tmp = new Object();
10039 synchronized (tmp) {
10040 try {
10041 tmp.wait(250);
10042 } catch (InterruptedException e) {
10043 }
10044 }
10045 }
Romain Guy06882f82009-06-10 13:36:04 -070010046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010047 mInLayout = true;
10048 try {
10049 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
Romain Guy06882f82009-06-10 13:36:04 -070010050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010051 int i = mPendingRemove.size()-1;
10052 if (i >= 0) {
10053 while (i >= 0) {
10054 WindowState w = mPendingRemove.get(i);
10055 removeWindowInnerLocked(w.mSession, w);
10056 i--;
10057 }
10058 mPendingRemove.clear();
10059
10060 mInLayout = false;
10061 assignLayersLocked();
10062 mLayoutNeeded = true;
10063 performLayoutAndPlaceSurfacesLocked();
10064
10065 } else {
10066 mInLayout = false;
10067 if (mLayoutNeeded) {
10068 requestAnimationLocked(0);
10069 }
10070 }
10071 } catch (RuntimeException e) {
10072 mInLayout = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010073 Slog.e(TAG, "Unhandled exception while layout out windows", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010074 }
10075 }
10076
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010077 private final int performLayoutLockedInner() {
10078 if (!mLayoutNeeded) {
10079 return 0;
10080 }
10081
10082 mLayoutNeeded = false;
10083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010084 final int dw = mDisplay.getWidth();
10085 final int dh = mDisplay.getHeight();
10086
10087 final int N = mWindows.size();
10088 int i;
10089
Joe Onorato8a9b2202010-02-26 18:56:32 -080010090 if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed="
Dianne Hackborn9b52a212009-12-11 14:51:35 -080010091 + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
10092
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010093 mPolicy.beginLayoutLw(dw, dh);
Romain Guy06882f82009-06-10 13:36:04 -070010094
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010095 int seq = mLayoutSeq+1;
10096 if (seq < 0) seq = 0;
10097 mLayoutSeq = seq;
10098
10099 // First perform layout of any root windows (not attached
10100 // to another window).
10101 int topAttached = -1;
10102 for (i = N-1; i >= 0; i--) {
10103 WindowState win = (WindowState) mWindows.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010104
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010105 // Don't do layout of a window if it is not visible, or
10106 // soon won't be visible, to avoid wasting time and funky
10107 // changes while a window is animating away.
10108 final AppWindowToken atoken = win.mAppToken;
10109 final boolean gone = win.mViewVisibility == View.GONE
10110 || !win.mRelayoutCalled
10111 || win.mRootToken.hidden
10112 || (atoken != null && atoken.hiddenRequested)
10113 || win.mAttachedHidden
10114 || win.mExiting || win.mDestroying;
10115
10116 if (!win.mLayoutAttached) {
10117 if (DEBUG_LAYOUT) Slog.v(TAG, "First pass " + win
10118 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
10119 + " mLayoutAttached=" + win.mLayoutAttached);
10120 if (DEBUG_LAYOUT && gone) Slog.v(TAG, " (mViewVisibility="
10121 + win.mViewVisibility + " mRelayoutCalled="
10122 + win.mRelayoutCalled + " hidden="
10123 + win.mRootToken.hidden + " hiddenRequested="
10124 + (atoken != null && atoken.hiddenRequested)
10125 + " mAttachedHidden=" + win.mAttachedHidden);
10126 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010127
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010128 // If this view is GONE, then skip it -- keep the current
10129 // frame, and let the caller know so they can ignore it
10130 // if they want. (We do the normal layout for INVISIBLE
10131 // windows, since that means "perform layout as normal,
10132 // just don't display").
10133 if (!gone || !win.mHaveFrame) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010134 if (!win.mLayoutAttached) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010135 mPolicy.layoutWindowLw(win, win.mAttrs, null);
10136 win.mLayoutSeq = seq;
10137 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
10138 + win.mFrame + " mContainingFrame="
10139 + win.mContainingFrame + " mDisplayFrame="
10140 + win.mDisplayFrame);
10141 } else {
10142 if (topAttached < 0) topAttached = i;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -070010143 }
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070010144 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010145 }
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010146
10147 // Now perform layout of attached windows, which usually
10148 // depend on the position of the window they are attached to.
10149 // XXX does not deal with windows that are attached to windows
10150 // that are themselves attached.
10151 for (i = topAttached; i >= 0; i--) {
10152 WindowState win = (WindowState) mWindows.get(i);
10153
10154 // If this view is GONE, then skip it -- keep the current
10155 // frame, and let the caller know so they can ignore it
10156 // if they want. (We do the normal layout for INVISIBLE
10157 // windows, since that means "perform layout as normal,
10158 // just don't display").
10159 if (win.mLayoutAttached) {
10160 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win
10161 + " mHaveFrame=" + win.mHaveFrame
10162 + " mViewVisibility=" + win.mViewVisibility
10163 + " mRelayoutCalled=" + win.mRelayoutCalled);
10164 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
10165 || !win.mHaveFrame) {
10166 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
10167 win.mLayoutSeq = seq;
10168 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
10169 + win.mFrame + " mContainingFrame="
10170 + win.mContainingFrame + " mDisplayFrame="
10171 + win.mDisplayFrame);
10172 }
10173 }
10174 }
Jeff Brown349703e2010-06-22 01:27:15 -070010175
10176 // Window frames may have changed. Tell the input dispatcher about it.
10177 if (ENABLE_NATIVE_INPUT_DISPATCH) {
10178 mInputMonitor.updateInputWindowsLw();
10179 }
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010180
10181 return mPolicy.finishLayoutLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 }
Romain Guy06882f82009-06-10 13:36:04 -070010183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010184 private final void performLayoutAndPlaceSurfacesLockedInner(
10185 boolean recoveringMemory) {
10186 final long currentTime = SystemClock.uptimeMillis();
10187 final int dw = mDisplay.getWidth();
10188 final int dh = mDisplay.getHeight();
10189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010190 int i;
10191
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010192 if (mFocusMayChange) {
10193 mFocusMayChange = false;
10194 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
10195 }
10196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010197 if (mFxSession == null) {
10198 mFxSession = new SurfaceSession();
10199 }
Romain Guy06882f82009-06-10 13:36:04 -070010200
Joe Onorato8a9b2202010-02-26 18:56:32 -080010201 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010202
10203 // Initialize state of exiting tokens.
10204 for (i=mExitingTokens.size()-1; i>=0; i--) {
10205 mExitingTokens.get(i).hasVisible = false;
10206 }
10207
10208 // Initialize state of exiting applications.
10209 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
10210 mExitingAppTokens.get(i).hasVisible = false;
10211 }
10212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010213 boolean orientationChangeComplete = true;
10214 Session holdScreen = null;
10215 float screenBrightness = -1;
Mike Lockwoodfb73f792009-11-20 11:31:18 -050010216 float buttonBrightness = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010217 boolean focusDisplayed = false;
10218 boolean animating = false;
10219
10220 Surface.openTransaction();
10221 try {
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010222 boolean wallpaperForceHidingChanged = false;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010223 int repeats = 0;
10224 int changes = 0;
10225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010226 do {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010227 repeats++;
10228 if (repeats > 6) {
10229 Slog.w(TAG, "Animation repeat aborted after too many iterations");
10230 mLayoutNeeded = false;
10231 break;
10232 }
10233
10234 if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER
10235 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG
10236 | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) {
10237 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
10238 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
10239 assignLayersLocked();
10240 mLayoutNeeded = true;
10241 }
10242 }
10243 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
10244 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
10245 if (updateOrientationFromAppTokensLocked()) {
10246 mLayoutNeeded = true;
10247 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10248 }
10249 }
10250 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
10251 mLayoutNeeded = true;
10252 }
10253 }
10254
10255 // FIRST LOOP: Perform a layout, if needed.
10256 if (repeats < 4) {
10257 changes = performLayoutLockedInner();
10258 if (changes != 0) {
10259 continue;
10260 }
10261 } else {
10262 Slog.w(TAG, "Layout repeat skipped after too many iterations");
10263 changes = 0;
10264 }
10265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 final int transactionSequence = ++mTransactionSequence;
10267
10268 // Update animations of all applications, including those
10269 // associated with exiting/removed apps
10270 boolean tokensAnimating = false;
10271 final int NAT = mAppTokens.size();
10272 for (i=0; i<NAT; i++) {
10273 if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
10274 tokensAnimating = true;
10275 }
10276 }
10277 final int NEAT = mExitingAppTokens.size();
10278 for (i=0; i<NEAT; i++) {
10279 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
10280 tokensAnimating = true;
10281 }
10282 }
10283
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010284 // SECOND LOOP: Execute animations and update visibility of windows.
10285
Joe Onorato8a9b2202010-02-26 18:56:32 -080010286 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010287 + transactionSequence + " tokensAnimating="
10288 + tokensAnimating);
10289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010290 animating = tokensAnimating;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291
10292 boolean tokenMayBeDrawn = false;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010293 boolean wallpaperMayChange = false;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010294 boolean forceHiding = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010295
10296 mPolicy.beginAnimationLw(dw, dh);
10297
Dianne Hackbornbdd52b22009-09-02 21:46:19 -070010298 final int N = mWindows.size();
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010300 for (i=N-1; i>=0; i--) {
10301 WindowState w = (WindowState)mWindows.get(i);
10302
10303 final WindowManager.LayoutParams attrs = w.mAttrs;
10304
10305 if (w.mSurface != null) {
10306 // Execute animation.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010307 if (w.commitFinishDrawingLocked(currentTime)) {
10308 if ((w.mAttrs.flags
10309 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010310 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010311 "First draw done in potential wallpaper target " + w);
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010312 wallpaperMayChange = true;
10313 }
10314 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010315
Dianne Hackborn6136b7e2009-09-18 01:53:49 -070010316 boolean wasAnimating = w.mAnimating;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010317 if (w.stepAnimationLocked(currentTime, dw, dh)) {
10318 animating = true;
10319 //w.dump(" ");
10320 }
Dianne Hackborn6136b7e2009-09-18 01:53:49 -070010321 if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
10322 wallpaperMayChange = true;
10323 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010324
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010325 if (mPolicy.doesForceHide(w, attrs)) {
10326 if (!wasAnimating && animating) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080010327 if (DEBUG_VISIBILITY) Slog.v(TAG,
10328 "Animation done that could impact force hide: "
10329 + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010330 wallpaperForceHidingChanged = true;
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010331 mFocusMayChange = true;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010332 } else if (w.isReadyForDisplay() && w.mAnimation == null) {
10333 forceHiding = true;
10334 }
10335 } else if (mPolicy.canBeForceHidden(w, attrs)) {
10336 boolean changed;
10337 if (forceHiding) {
10338 changed = w.hideLw(false, false);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080010339 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
10340 "Now policy hidden: " + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010341 } else {
10342 changed = w.showLw(false, false);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080010343 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
10344 "Now policy shown: " + w);
10345 if (changed) {
10346 if (wallpaperForceHidingChanged
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010347 && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080010348 // Assume we will need to animate. If
10349 // we don't (because the wallpaper will
10350 // stay with the lock screen), then we will
10351 // clean up later.
10352 Animation a = mPolicy.createForceHideEnterAnimation();
10353 if (a != null) {
10354 w.setAnimation(a);
10355 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010356 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080010357 if (mCurrentFocus == null ||
10358 mCurrentFocus.mLayer < w.mLayer) {
10359 // We are showing on to of the current
10360 // focus, so re-evaluate focus to make
10361 // sure it is correct.
10362 mFocusMayChange = true;
10363 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010364 }
10365 }
10366 if (changed && (attrs.flags
10367 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
10368 wallpaperMayChange = true;
10369 }
10370 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010372 mPolicy.animatingWindowLw(w, attrs);
10373 }
10374
10375 final AppWindowToken atoken = w.mAppToken;
10376 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
10377 if (atoken.lastTransactionSequence != transactionSequence) {
10378 atoken.lastTransactionSequence = transactionSequence;
10379 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
10380 atoken.startingDisplayed = false;
10381 }
10382 if ((w.isOnScreen() || w.mAttrs.type
10383 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
10384 && !w.mExiting && !w.mDestroying) {
10385 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010386 Slog.v(TAG, "Eval win " + w + ": isDrawn="
Dianne Hackborn7433e8a2009-09-27 13:21:20 -070010387 + w.isDrawnLw()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010388 + ", isAnimating=" + w.isAnimating());
Dianne Hackborn7433e8a2009-09-27 13:21:20 -070010389 if (!w.isDrawnLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010390 Slog.v(TAG, "Not displayed: s=" + w.mSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010391 + " pv=" + w.mPolicyVisibility
10392 + " dp=" + w.mDrawPending
10393 + " cdp=" + w.mCommitDrawPending
10394 + " ah=" + w.mAttachedHidden
10395 + " th=" + atoken.hiddenRequested
10396 + " a=" + w.mAnimating);
10397 }
10398 }
10399 if (w != atoken.startingWindow) {
10400 if (!atoken.freezingScreen || !w.mAppFreezing) {
10401 atoken.numInterestingWindows++;
Dianne Hackborn7433e8a2009-09-27 13:21:20 -070010402 if (w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403 atoken.numDrawnWindows++;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010404 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010405 "tokenMayBeDrawn: " + atoken
10406 + " freezingScreen=" + atoken.freezingScreen
10407 + " mAppFreezing=" + w.mAppFreezing);
10408 tokenMayBeDrawn = true;
10409 }
10410 }
Dianne Hackborn7433e8a2009-09-27 13:21:20 -070010411 } else if (w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010412 atoken.startingDisplayed = true;
10413 }
10414 }
10415 } else if (w.mReadyToShow) {
10416 w.performShowLocked();
10417 }
10418 }
10419
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010420 changes |= mPolicy.finishAnimationLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010421
10422 if (tokenMayBeDrawn) {
10423 // See if any windows have been drawn, so they (and others
10424 // associated with them) can now be shown.
10425 final int NT = mTokenList.size();
10426 for (i=0; i<NT; i++) {
10427 AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
10428 if (wtoken == null) {
10429 continue;
10430 }
10431 if (wtoken.freezingScreen) {
10432 int numInteresting = wtoken.numInterestingWindows;
10433 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010434 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 "allDrawn: " + wtoken
10436 + " interesting=" + numInteresting
10437 + " drawn=" + wtoken.numDrawnWindows);
10438 wtoken.showAllWindowsLocked();
10439 unsetAppFreezingScreenLocked(wtoken, false, true);
10440 orientationChangeComplete = true;
10441 }
10442 } else if (!wtoken.allDrawn) {
10443 int numInteresting = wtoken.numInterestingWindows;
10444 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010445 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 "allDrawn: " + wtoken
10447 + " interesting=" + numInteresting
10448 + " drawn=" + wtoken.numDrawnWindows);
10449 wtoken.allDrawn = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010450 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010451
10452 // We can now show all of the drawn windows!
10453 if (!mOpeningApps.contains(wtoken)) {
10454 wtoken.showAllWindowsLocked();
10455 }
10456 }
10457 }
10458 }
10459 }
10460
10461 // If we are ready to perform an app transition, check through
10462 // all of the app tokens to be shown and see if they are ready
10463 // to go.
10464 if (mAppTransitionReady) {
10465 int NN = mOpeningApps.size();
10466 boolean goodToGo = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010467 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010468 "Checking " + NN + " opening apps (frozen="
10469 + mDisplayFrozen + " timeout="
10470 + mAppTransitionTimeout + ")...");
10471 if (!mDisplayFrozen && !mAppTransitionTimeout) {
10472 // If the display isn't frozen, wait to do anything until
10473 // all of the apps are ready. Otherwise just go because
10474 // we'll unfreeze the display when everyone is ready.
10475 for (i=0; i<NN && goodToGo; i++) {
10476 AppWindowToken wtoken = mOpeningApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010477 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010478 "Check opening app" + wtoken + ": allDrawn="
10479 + wtoken.allDrawn + " startingDisplayed="
10480 + wtoken.startingDisplayed);
10481 if (!wtoken.allDrawn && !wtoken.startingDisplayed
10482 && !wtoken.startingMoved) {
10483 goodToGo = false;
10484 }
10485 }
10486 }
10487 if (goodToGo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010488 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010489 int transit = mNextAppTransition;
10490 if (mSkipAppTransitionAnimation) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -070010491 transit = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010492 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -070010493 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010494 mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -070010495 mAppTransitionRunning = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010496 mAppTransitionTimeout = false;
10497 mStartingIconInTransition = false;
10498 mSkipAppTransitionAnimation = false;
10499
10500 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
10501
Dianne Hackborna8f60182009-09-01 19:01:50 -070010502 // If there are applications waiting to come to the
10503 // top of the stack, now is the time to move their windows.
10504 // (Note that we don't do apps going to the bottom
10505 // here -- we want to keep their windows in the old
10506 // Z-order until the animation completes.)
10507 if (mToTopApps.size() > 0) {
10508 NN = mAppTokens.size();
10509 for (i=0; i<NN; i++) {
10510 AppWindowToken wtoken = mAppTokens.get(i);
10511 if (wtoken.sendingToTop) {
10512 wtoken.sendingToTop = false;
10513 moveAppWindowsLocked(wtoken, NN, false);
10514 }
10515 }
10516 mToTopApps.clear();
10517 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010518
Dianne Hackborn25994b42009-09-04 14:21:19 -070010519 WindowState oldWallpaper = mWallpaperTarget;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010520
Dianne Hackborn3be63c02009-08-20 19:31:38 -070010521 adjustWallpaperWindowsLocked();
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010522 wallpaperMayChange = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010523
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010524 // The top-most window will supply the layout params,
10525 // and we will determine it below.
10526 LayoutParams animLp = null;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010527 AppWindowToken animToken = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010528 int bestAnimLayer = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010529
Joe Onorato8a9b2202010-02-26 18:56:32 -080010530 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -070010531 "New wallpaper target=" + mWallpaperTarget
10532 + ", lower target=" + mLowerWallpaperTarget
10533 + ", upper target=" + mUpperWallpaperTarget);
Dianne Hackborn25994b42009-09-04 14:21:19 -070010534 int foundWallpapers = 0;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010535 // Do a first pass through the tokens for two
10536 // things:
10537 // (1) Determine if both the closing and opening
10538 // app token sets are wallpaper targets, in which
10539 // case special animations are needed
10540 // (since the wallpaper needs to stay static
10541 // behind them).
10542 // (2) Find the layout params of the top-most
10543 // application window in the tokens, which is
10544 // what will control the animation theme.
10545 final int NC = mClosingApps.size();
10546 NN = NC + mOpeningApps.size();
10547 for (i=0; i<NN; i++) {
10548 AppWindowToken wtoken;
10549 int mode;
10550 if (i < NC) {
10551 wtoken = mClosingApps.get(i);
10552 mode = 1;
10553 } else {
10554 wtoken = mOpeningApps.get(i-NC);
10555 mode = 2;
10556 }
10557 if (mLowerWallpaperTarget != null) {
10558 if (mLowerWallpaperTarget.mAppToken == wtoken
10559 || mUpperWallpaperTarget.mAppToken == wtoken) {
10560 foundWallpapers |= mode;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -070010561 }
10562 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010563 if (wtoken.appFullscreen) {
10564 WindowState ws = wtoken.findMainWindow();
10565 if (ws != null) {
10566 // If this is a compatibility mode
10567 // window, we will always use its anim.
10568 if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
10569 animLp = ws.mAttrs;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010570 animToken = ws.mAppToken;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010571 bestAnimLayer = Integer.MAX_VALUE;
10572 } else if (ws.mLayer > bestAnimLayer) {
10573 animLp = ws.mAttrs;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010574 animToken = ws.mAppToken;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010575 bestAnimLayer = ws.mLayer;
10576 }
Dianne Hackborn25994b42009-09-04 14:21:19 -070010577 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -070010578 }
10579 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010580
Dianne Hackborn25994b42009-09-04 14:21:19 -070010581 if (foundWallpapers == 3) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010582 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010583 "Wallpaper animation!");
10584 switch (transit) {
10585 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
10586 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
10587 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
10588 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN;
10589 break;
10590 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
10591 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
10592 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
10593 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE;
10594 break;
10595 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010596 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010597 "New transit: " + transit);
10598 } else if (oldWallpaper != null) {
10599 // We are transitioning from an activity with
10600 // a wallpaper to one without.
10601 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010602 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010603 "New transit away from wallpaper: " + transit);
10604 } else if (mWallpaperTarget != null) {
10605 // We are transitioning from an activity without
10606 // a wallpaper to now showing the wallpaper
10607 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010608 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010609 "New transit into wallpaper: " + transit);
10610 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010611
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010612 if ((transit&WindowManagerPolicy.TRANSIT_ENTER_MASK) != 0) {
10613 mLastEnterAnimToken = animToken;
10614 mLastEnterAnimParams = animLp;
10615 } else if (mLastEnterAnimParams != null) {
10616 animLp = mLastEnterAnimParams;
10617 mLastEnterAnimToken = null;
10618 mLastEnterAnimParams = null;
10619 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010620
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010621 // If all closing windows are obscured, then there is
10622 // no need to do an animation. This is the case, for
10623 // example, when this transition is being done behind
10624 // the lock screen.
10625 if (!mPolicy.allowAppAnimationsLw()) {
10626 animLp = null;
10627 }
10628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010629 NN = mOpeningApps.size();
10630 for (i=0; i<NN; i++) {
10631 AppWindowToken wtoken = mOpeningApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010632 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010633 "Now opening app" + wtoken);
10634 wtoken.reportedVisible = false;
10635 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -070010636 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010637 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010638 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070010639 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010640 wtoken.showAllWindowsLocked();
10641 }
10642 NN = mClosingApps.size();
10643 for (i=0; i<NN; i++) {
10644 AppWindowToken wtoken = mClosingApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010645 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010646 "Now closing app" + wtoken);
10647 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -070010648 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010649 setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010650 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070010651 wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 // Force the allDrawn flag, because we want to start
10653 // this guy's animations regardless of whether it's
10654 // gotten drawn.
10655 wtoken.allDrawn = true;
10656 }
10657
Dianne Hackborn8b571a82009-09-25 16:09:43 -070010658 mNextAppTransitionPackage = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010660 mOpeningApps.clear();
10661 mClosingApps.clear();
10662
10663 // This has changed the visibility of windows, so perform
10664 // a new layout to get them all up-to-date.
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010665 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010666 mLayoutNeeded = true;
Dianne Hackborn20583ff2009-07-27 21:51:05 -070010667 if (!moveInputMethodWindowsIfNeededLocked(true)) {
10668 assignLayersLocked();
10669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010670 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010671 mFocusMayChange = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010672 }
10673 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010674
Dianne Hackborn16064f92010-03-25 00:47:24 -070010675 int adjResult = 0;
10676
Dianne Hackborna8f60182009-09-01 19:01:50 -070010677 if (!animating && mAppTransitionRunning) {
10678 // We have finished the animation of an app transition. To do
10679 // this, we have delayed a lot of operations like showing and
10680 // hiding apps, moving apps in Z-order, etc. The app token list
10681 // reflects the correct Z-order, but the window list may now
10682 // be out of sync with it. So here we will just rebuild the
10683 // entire app window list. Fun!
10684 mAppTransitionRunning = false;
10685 // Clear information about apps that were moving.
10686 mToBottomApps.clear();
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010687
Dianne Hackborna8f60182009-09-01 19:01:50 -070010688 rebuildAppWindowListLocked();
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010689 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn16064f92010-03-25 00:47:24 -070010690 adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED;
Dianne Hackborna8f60182009-09-01 19:01:50 -070010691 moveInputMethodWindowsIfNeededLocked(false);
10692 wallpaperMayChange = true;
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -080010693 // Since the window list has been rebuilt, focus might
10694 // have to be recomputed since the actual order of windows
10695 // might have changed again.
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010696 mFocusMayChange = true;
Dianne Hackborna8f60182009-09-01 19:01:50 -070010697 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010698
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010699 if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010700 // At this point, there was a window with a wallpaper that
10701 // was force hiding other windows behind it, but now it
10702 // is going away. This may be simple -- just animate
10703 // away the wallpaper and its window -- or it may be
10704 // hard -- the wallpaper now needs to be shown behind
10705 // something that was hidden.
10706 WindowState oldWallpaper = mWallpaperTarget;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010707 if (mLowerWallpaperTarget != null
10708 && mLowerWallpaperTarget.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010709 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010710 "wallpaperForceHiding changed with lower="
10711 + mLowerWallpaperTarget);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010712 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010713 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden +
10714 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested);
10715 if (mLowerWallpaperTarget.mAppToken.hidden) {
10716 // The lower target has become hidden before we
10717 // actually started the animation... let's completely
10718 // re-evaluate everything.
10719 mLowerWallpaperTarget = mUpperWallpaperTarget = null;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010720 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010721 }
10722 }
Dianne Hackborn16064f92010-03-25 00:47:24 -070010723 adjResult |= adjustWallpaperWindowsLocked();
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010724 wallpaperMayChange = false;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010725 wallpaperForceHidingChanged = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010726 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010727 + " NEW: " + mWallpaperTarget
10728 + " LOWER: " + mLowerWallpaperTarget);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010729 if (mLowerWallpaperTarget == null) {
10730 // Whoops, we don't need a special wallpaper animation.
10731 // Clear them out.
10732 forceHiding = false;
10733 for (i=N-1; i>=0; i--) {
10734 WindowState w = (WindowState)mWindows.get(i);
10735 if (w.mSurface != null) {
10736 final WindowManager.LayoutParams attrs = w.mAttrs;
Suchi Amalapurapuc03d28b2009-10-28 14:32:05 -070010737 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010738 if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010739 forceHiding = true;
10740 } else if (mPolicy.canBeForceHidden(w, attrs)) {
10741 if (!w.mAnimating) {
10742 // We set the animation above so it
10743 // is not yet running.
10744 w.clearAnimation();
10745 }
10746 }
10747 }
10748 }
10749 }
10750 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010751
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010752 if (wallpaperMayChange) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010753 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010754 "Wallpaper may change! Adjusting");
Dianne Hackborn16064f92010-03-25 00:47:24 -070010755 adjResult |= adjustWallpaperWindowsLocked();
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010756 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010757
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010758 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010759 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010760 "Wallpaper layer changed: assigning layers + relayout");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010761 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010762 assignLayersLocked();
10763 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010764 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010765 "Wallpaper visibility changed: relayout");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010766 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010767 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010768
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010769 if (mFocusMayChange) {
10770 mFocusMayChange = false;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010771 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010772 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010773 adjResult = 0;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010774 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010775 }
10776
10777 if (mLayoutNeeded) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010778 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010779 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010780
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010781 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
10782 + Integer.toHexString(changes));
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010783
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010784 } while (changes != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010785
10786 // THIRD LOOP: Update the surfaces of all windows.
10787
10788 final boolean someoneLosingFocus = mLosingFocus.size() != 0;
10789
10790 boolean obscured = false;
10791 boolean blurring = false;
10792 boolean dimming = false;
10793 boolean covered = false;
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070010794 boolean syswin = false;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010795 boolean backgroundFillerShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010796
Dianne Hackbornbdd52b22009-09-02 21:46:19 -070010797 final int N = mWindows.size();
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 for (i=N-1; i>=0; i--) {
10800 WindowState w = (WindowState)mWindows.get(i);
10801
10802 boolean displayed = false;
10803 final WindowManager.LayoutParams attrs = w.mAttrs;
10804 final int attrFlags = attrs.flags;
10805
10806 if (w.mSurface != null) {
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010807 // XXX NOTE: The logic here could be improved. We have
10808 // the decision about whether to resize a window separated
10809 // from whether to hide the surface. This can cause us to
10810 // resize a surface even if we are going to hide it. You
10811 // can see this by (1) holding device in landscape mode on
10812 // home screen; (2) tapping browser icon (device will rotate
10813 // to landscape; (3) tap home. The wallpaper will be resized
10814 // in step 2 but then immediately hidden, causing us to
10815 // have to resize and then redraw it again in step 3. It
10816 // would be nice to figure out how to avoid this, but it is
10817 // difficult because we do need to resize surfaces in some
10818 // cases while they are hidden such as when first showing a
10819 // window.
10820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010821 w.computeShownFrameLocked();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010822 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010823 TAG, "Placing surface #" + i + " " + w.mSurface
10824 + ": new=" + w.mShownFrame + ", old="
10825 + w.mLastShownFrame);
10826
10827 boolean resize;
10828 int width, height;
10829 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
10830 resize = w.mLastRequestedWidth != w.mRequestedWidth ||
10831 w.mLastRequestedHeight != w.mRequestedHeight;
10832 // for a scaled surface, we just want to use
10833 // the requested size.
10834 width = w.mRequestedWidth;
10835 height = w.mRequestedHeight;
10836 w.mLastRequestedWidth = width;
10837 w.mLastRequestedHeight = height;
10838 w.mLastShownFrame.set(w.mShownFrame);
10839 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010840 if (SHOW_TRANSACTIONS) logSurface(w,
10841 "POS " + w.mShownFrame.left
10842 + ", " + w.mShownFrame.top, null);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010843 w.mSurfaceX = w.mShownFrame.left;
10844 w.mSurfaceY = w.mShownFrame.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010845 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
10846 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010847 Slog.w(TAG, "Error positioning surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010848 if (!recoveringMemory) {
10849 reclaimSomeSurfaceMemoryLocked(w, "position");
10850 }
10851 }
10852 } else {
10853 resize = !w.mLastShownFrame.equals(w.mShownFrame);
10854 width = w.mShownFrame.width();
10855 height = w.mShownFrame.height();
10856 w.mLastShownFrame.set(w.mShownFrame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010857 }
10858
10859 if (resize) {
10860 if (width < 1) width = 1;
10861 if (height < 1) height = 1;
10862 if (w.mSurface != null) {
10863 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010864 if (SHOW_TRANSACTIONS) logSurface(w,
10865 "POS " + w.mShownFrame.left + ","
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010866 + w.mShownFrame.top + " SIZE "
10867 + w.mShownFrame.width() + "x"
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010868 + w.mShownFrame.height(), null);
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010869 w.mSurfaceResized = true;
Dianne Hackborn16064f92010-03-25 00:47:24 -070010870 w.mSurfaceW = width;
10871 w.mSurfaceH = height;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010872 w.mSurface.setSize(width, height);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010873 w.mSurfaceX = w.mShownFrame.left;
10874 w.mSurfaceY = w.mShownFrame.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010875 w.mSurface.setPosition(w.mShownFrame.left,
10876 w.mShownFrame.top);
10877 } catch (RuntimeException e) {
10878 // If something goes wrong with the surface (such
10879 // as running out of memory), don't take down the
10880 // entire system.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010881 Slog.e(TAG, "Failure updating surface of " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010882 + "size=(" + width + "x" + height
10883 + "), pos=(" + w.mShownFrame.left
10884 + "," + w.mShownFrame.top + ")", e);
10885 if (!recoveringMemory) {
10886 reclaimSomeSurfaceMemoryLocked(w, "size");
10887 }
10888 }
10889 }
10890 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010891 if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010892 w.mContentInsetsChanged =
10893 !w.mLastContentInsets.equals(w.mContentInsets);
10894 w.mVisibleInsetsChanged =
10895 !w.mLastVisibleInsets.equals(w.mVisibleInsets);
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010896 boolean configChanged =
10897 w.mConfiguration != mCurConfiguration
10898 && (w.mConfiguration == null
10899 || mCurConfiguration.diff(w.mConfiguration) != 0);
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010900 if (DEBUG_CONFIGURATION && configChanged) {
10901 Slog.v(TAG, "Win " + w + " config changed: "
10902 + mCurConfiguration);
10903 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010904 if (localLOGV) Slog.v(TAG, "Resizing " + w
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010905 + ": configChanged=" + configChanged
10906 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
Romain Guy06882f82009-06-10 13:36:04 -070010907 if (!w.mLastFrame.equals(w.mFrame)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010908 || w.mContentInsetsChanged
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010909 || w.mVisibleInsetsChanged
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010910 || w.mSurfaceResized
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010911 || configChanged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010912 w.mLastFrame.set(w.mFrame);
10913 w.mLastContentInsets.set(w.mContentInsets);
10914 w.mLastVisibleInsets.set(w.mVisibleInsets);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010915 // If the screen is currently frozen, then keep
10916 // it frozen until this window draws at its new
10917 // orientation.
10918 if (mDisplayFrozen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010919 if (DEBUG_ORIENTATION) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010920 "Resizing while display frozen: " + w);
10921 w.mOrientationChanging = true;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010922 if (!mWindowsFreezingScreen) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010923 mWindowsFreezingScreen = true;
10924 // XXX should probably keep timeout from
10925 // when we first froze the display.
10926 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10927 mH.sendMessageDelayed(mH.obtainMessage(
10928 H.WINDOW_FREEZE_TIMEOUT), 2000);
10929 }
10930 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010931 // If the orientation is changing, then we need to
10932 // hold off on unfreezing the display until this
10933 // window has been redrawn; to do that, we need
10934 // to go through the process of getting informed
10935 // by the application when it has finished drawing.
10936 if (w.mOrientationChanging) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010937 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 "Orientation start waiting for draw in "
10939 + w + ", surface " + w.mSurface);
10940 w.mDrawPending = true;
10941 w.mCommitDrawPending = false;
10942 w.mReadyToShow = false;
10943 if (w.mAppToken != null) {
10944 w.mAppToken.allDrawn = false;
10945 }
10946 }
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010947 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 "Resizing window " + w + " to " + w.mFrame);
10949 mResizingWindows.add(w);
10950 } else if (w.mOrientationChanging) {
10951 if (!w.mDrawPending && !w.mCommitDrawPending) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010952 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010953 "Orientation not waiting for draw in "
10954 + w + ", surface " + w.mSurface);
10955 w.mOrientationChanging = false;
10956 }
10957 }
10958 }
10959
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010960 if (w.mAttachedHidden || !w.isReadyForDisplay()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010961 if (!w.mLastHidden) {
10962 //dump();
Dianne Hackborn5943c202010-04-12 21:36:49 -070010963 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Window hiding: waitingToShow="
10964 + w.mRootToken.waitingToShow + " polvis="
10965 + w.mPolicyVisibility + " atthid="
10966 + w.mAttachedHidden + " tokhid="
10967 + w.mRootToken.hidden + " vis="
10968 + w.mViewVisibility);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 w.mLastHidden = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010970 if (SHOW_TRANSACTIONS) logSurface(w,
10971 "HIDE (performLayout)", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010972 if (w.mSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010973 w.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010974 try {
10975 w.mSurface.hide();
10976 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010977 Slog.w(TAG, "Exception hiding surface in " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010978 }
10979 }
Jeff Brown349703e2010-06-22 01:27:15 -070010980 if (ENABLE_NATIVE_INPUT_DISPATCH) {
10981 mInputMonitor.windowIsBecomingInvisibleLw(w);
10982 } else {
10983 mKeyWaiter.releasePendingPointerLocked(w.mSession);
10984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010985 }
10986 // If we are waiting for this window to handle an
10987 // orientation change, well, it is hidden, so
10988 // doesn't really matter. Note that this does
10989 // introduce a potential glitch if the window
10990 // becomes unhidden before it has drawn for the
10991 // new orientation.
10992 if (w.mOrientationChanging) {
10993 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010994 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010995 "Orientation change skips hidden " + w);
10996 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010997 } else if (w.mLastLayer != w.mAnimLayer
10998 || w.mLastAlpha != w.mShownAlpha
10999 || w.mLastDsDx != w.mDsDx
11000 || w.mLastDtDx != w.mDtDx
11001 || w.mLastDsDy != w.mDsDy
11002 || w.mLastDtDy != w.mDtDy
11003 || w.mLastHScale != w.mHScale
11004 || w.mLastVScale != w.mVScale
11005 || w.mLastHidden) {
11006 displayed = true;
11007 w.mLastAlpha = w.mShownAlpha;
11008 w.mLastLayer = w.mAnimLayer;
11009 w.mLastDsDx = w.mDsDx;
11010 w.mLastDtDx = w.mDtDx;
11011 w.mLastDsDy = w.mDsDy;
11012 w.mLastDtDy = w.mDtDy;
11013 w.mLastHScale = w.mHScale;
11014 w.mLastVScale = w.mVScale;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011015 if (SHOW_TRANSACTIONS) logSurface(w,
11016 "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011017 + " matrix=[" + (w.mDsDx*w.mHScale)
11018 + "," + (w.mDtDx*w.mVScale)
11019 + "][" + (w.mDsDy*w.mHScale)
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011020 + "," + (w.mDtDy*w.mVScale) + "]", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011021 if (w.mSurface != null) {
11022 try {
Dianne Hackborn16064f92010-03-25 00:47:24 -070011023 w.mSurfaceAlpha = w.mShownAlpha;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011024 w.mSurface.setAlpha(w.mShownAlpha);
Dianne Hackborn16064f92010-03-25 00:47:24 -070011025 w.mSurfaceLayer = w.mAnimLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011026 w.mSurface.setLayer(w.mAnimLayer);
11027 w.mSurface.setMatrix(
11028 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
11029 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
11030 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011031 Slog.w(TAG, "Error updating surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011032 if (!recoveringMemory) {
11033 reclaimSomeSurfaceMemoryLocked(w, "update");
11034 }
11035 }
11036 }
11037
11038 if (w.mLastHidden && !w.mDrawPending
11039 && !w.mCommitDrawPending
11040 && !w.mReadyToShow) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011041 if (SHOW_TRANSACTIONS) logSurface(w,
11042 "SHOW (performLayout)", null);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011043 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011044 + " during relayout");
11045 if (showSurfaceRobustlyLocked(w)) {
11046 w.mHasDrawn = true;
11047 w.mLastHidden = false;
11048 } else {
11049 w.mOrientationChanging = false;
11050 }
11051 }
11052 if (w.mSurface != null) {
11053 w.mToken.hasVisible = true;
11054 }
11055 } else {
11056 displayed = true;
11057 }
11058
11059 if (displayed) {
11060 if (!covered) {
Romain Guy980a9382010-01-08 15:06:28 -080011061 if (attrs.width == LayoutParams.MATCH_PARENT
11062 && attrs.height == LayoutParams.MATCH_PARENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011063 covered = true;
11064 }
11065 }
11066 if (w.mOrientationChanging) {
11067 if (w.mDrawPending || w.mCommitDrawPending) {
11068 orientationChangeComplete = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011069 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011070 "Orientation continue waiting for draw in " + w);
11071 } else {
11072 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011073 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011074 "Orientation change complete in " + w);
11075 }
11076 }
11077 w.mToken.hasVisible = true;
11078 }
11079 } else if (w.mOrientationChanging) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011080 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011081 "Orientation change skips hidden " + w);
11082 w.mOrientationChanging = false;
11083 }
11084
11085 final boolean canBeSeen = w.isDisplayedLw();
11086
11087 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
11088 focusDisplayed = true;
11089 }
11090
Dianne Hackborne9e9bca2009-08-18 15:08:22 -070011091 final boolean obscuredChanged = w.mObscured != obscured;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011093 // Update effect.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011094 if (!(w.mObscured=obscured)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011095 if (w.mSurface != null) {
11096 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
11097 holdScreen = w.mSession;
11098 }
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070011099 if (!syswin && w.mAttrs.screenBrightness >= 0
11100 && screenBrightness < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011101 screenBrightness = w.mAttrs.screenBrightness;
11102 }
Mike Lockwoodfb73f792009-11-20 11:31:18 -050011103 if (!syswin && w.mAttrs.buttonBrightness >= 0
11104 && buttonBrightness < 0) {
11105 buttonBrightness = w.mAttrs.buttonBrightness;
11106 }
Mike Lockwood46af6a82010-03-09 08:28:22 -050011107 if (canBeSeen
11108 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
11109 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
11110 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070011111 syswin = true;
11112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011113 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011114
Dianne Hackborn25994b42009-09-04 14:21:19 -070011115 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
11116 if (opaqueDrawn && w.isFullscreen(dw, dh)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 // This window completely covers everything behind it,
11118 // so we want to leave all of them as unblurred (for
11119 // performance reasons).
11120 obscured = true;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011121 } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011122 if (SHOW_TRANSACTIONS) Slog.d(TAG, "showing background filler");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011123 // This window is in compatibility mode, and needs background filler.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011124 obscured = true;
11125 if (mBackgroundFillerSurface == null) {
11126 try {
11127 mBackgroundFillerSurface = new Surface(mFxSession, 0,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080011128 "BackGroundFiller",
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011129 0, dw, dh,
11130 PixelFormat.OPAQUE,
11131 Surface.FX_SURFACE_NORMAL);
11132 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011133 Slog.e(TAG, "Exception creating filler surface", e);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011134 }
11135 }
11136 try {
11137 mBackgroundFillerSurface.setPosition(0, 0);
11138 mBackgroundFillerSurface.setSize(dw, dh);
11139 // Using the same layer as Dim because they will never be shown at the
11140 // same time.
11141 mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
11142 mBackgroundFillerSurface.show();
11143 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011144 Slog.e(TAG, "Exception showing filler surface");
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011145 }
11146 backgroundFillerShown = true;
11147 mBackgroundFillerShown = true;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011148 } else if (canBeSeen && !obscured &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011149 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011150 if (localLOGV) Slog.v(TAG, "Win " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 + ": blurring=" + blurring
11152 + " obscured=" + obscured
11153 + " displayed=" + displayed);
11154 if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
11155 if (!dimming) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011156 //Slog.i(TAG, "DIM BEHIND: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011157 dimming = true;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011158 if (mDimAnimator == null) {
11159 mDimAnimator = new DimAnimator(mFxSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011160 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011161 mDimAnimator.show(dw, dh);
Dianne Hackborn16064f92010-03-25 00:47:24 -070011162 mDimAnimator.updateParameters(w, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 }
11165 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
11166 if (!blurring) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011167 //Slog.i(TAG, "BLUR BEHIND: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011168 blurring = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011169 if (mBlurSurface == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011170 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011171 + mBlurSurface + ": CREATE");
11172 try {
Romain Guy06882f82009-06-10 13:36:04 -070011173 mBlurSurface = new Surface(mFxSession, 0,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080011174 "BlurSurface",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011175 -1, 16, 16,
11176 PixelFormat.OPAQUE,
11177 Surface.FX_SURFACE_BLUR);
11178 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011179 Slog.e(TAG, "Exception creating Blur surface", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011180 }
11181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011182 if (mBlurSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070011183 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
11184 + mBlurSurface + ": pos=(0,0) (" +
11185 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011186 mBlurSurface.setPosition(0, 0);
11187 mBlurSurface.setSize(dw, dh);
Dianne Hackborn16064f92010-03-25 00:47:24 -070011188 mBlurSurface.setLayer(w.mAnimLayer-2);
11189 if (!mBlurShown) {
11190 try {
11191 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
11192 + mBlurSurface + ": SHOW");
11193 mBlurSurface.show();
11194 } catch (RuntimeException e) {
11195 Slog.w(TAG, "Failure showing blur surface", e);
11196 }
11197 mBlurShown = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 }
11199 }
11200 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011201 }
11202 }
11203 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011204
Dianne Hackborne9e9bca2009-08-18 15:08:22 -070011205 if (obscuredChanged && mWallpaperTarget == w) {
11206 // This is the wallpaper target and its obscured state
11207 // changed... make sure the current wallaper's visibility
11208 // has been updated accordingly.
11209 updateWallpaperVisibilityLocked();
11210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011211 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011212
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011213 if (backgroundFillerShown == false && mBackgroundFillerShown) {
11214 mBackgroundFillerShown = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011215 if (SHOW_TRANSACTIONS) Slog.d(TAG, "hiding background filler");
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011216 try {
11217 mBackgroundFillerSurface.hide();
11218 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011219 Slog.e(TAG, "Exception hiding filler surface", e);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011220 }
11221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011222
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011223 if (mDimAnimator != null && mDimAnimator.mDimShown) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -080011224 animating |= mDimAnimator.updateSurface(dimming, currentTime,
11225 mDisplayFrozen || !mPolicy.isScreenOn());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011226 }
Romain Guy06882f82009-06-10 13:36:04 -070011227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011228 if (!blurring && mBlurShown) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011229 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " + mBlurSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011230 + ": HIDE");
11231 try {
11232 mBlurSurface.hide();
11233 } catch (IllegalArgumentException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011234 Slog.w(TAG, "Illegal argument exception hiding blur surface");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 }
11236 mBlurShown = false;
11237 }
11238
Joe Onorato8a9b2202010-02-26 18:56:32 -080011239 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011240 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011241 Slog.e(TAG, "Unhandled exception in Window Manager", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011242 }
11243
11244 Surface.closeTransaction();
Romain Guy06882f82009-06-10 13:36:04 -070011245
Joe Onorato8a9b2202010-02-26 18:56:32 -080011246 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011247 "With display frozen, orientationChangeComplete="
11248 + orientationChangeComplete);
11249 if (orientationChangeComplete) {
11250 if (mWindowsFreezingScreen) {
11251 mWindowsFreezingScreen = false;
11252 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
11253 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011254 stopFreezingDisplayLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011255 }
Romain Guy06882f82009-06-10 13:36:04 -070011256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011257 i = mResizingWindows.size();
11258 if (i > 0) {
11259 do {
11260 i--;
11261 WindowState win = mResizingWindows.get(i);
11262 try {
Dianne Hackbornac3587d2010-03-11 11:12:11 -080011263 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
11264 "Reporting new frame to " + win + ": " + win.mFrame);
Dianne Hackborn694f79b2010-03-17 19:44:59 -070011265 int diff = 0;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011266 boolean configChanged =
11267 win.mConfiguration != mCurConfiguration
11268 && (win.mConfiguration == null
Dianne Hackborn694f79b2010-03-17 19:44:59 -070011269 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0);
11270 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
11271 && configChanged) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011272 Slog.i(TAG, "Sending new config to window " + win + ": "
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011273 + win.mFrame.width() + "x" + win.mFrame.height()
Dianne Hackborn694f79b2010-03-17 19:44:59 -070011274 + " / " + mCurConfiguration + " / 0x"
11275 + Integer.toHexString(diff));
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011276 }
Dianne Hackborn694f79b2010-03-17 19:44:59 -070011277 win.mConfiguration = mCurConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 win.mClient.resized(win.mFrame.width(),
11279 win.mFrame.height(), win.mLastContentInsets,
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011280 win.mLastVisibleInsets, win.mDrawPending,
11281 configChanged ? win.mConfiguration : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 win.mContentInsetsChanged = false;
11283 win.mVisibleInsetsChanged = false;
Dianne Hackbornac3587d2010-03-11 11:12:11 -080011284 win.mSurfaceResized = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011285 } catch (RemoteException e) {
11286 win.mOrientationChanging = false;
11287 }
11288 } while (i > 0);
11289 mResizingWindows.clear();
11290 }
Romain Guy06882f82009-06-10 13:36:04 -070011291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011292 // Destroy the surface of any windows that are no longer visible.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011293 boolean wallpaperDestroyed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011294 i = mDestroySurface.size();
11295 if (i > 0) {
11296 do {
11297 i--;
11298 WindowState win = mDestroySurface.get(i);
11299 win.mDestroying = false;
11300 if (mInputMethodWindow == win) {
11301 mInputMethodWindow = null;
11302 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011303 if (win == mWallpaperTarget) {
11304 wallpaperDestroyed = true;
11305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011306 win.destroySurfaceLocked();
11307 } while (i > 0);
11308 mDestroySurface.clear();
11309 }
11310
11311 // Time to remove any exiting tokens?
11312 for (i=mExitingTokens.size()-1; i>=0; i--) {
11313 WindowToken token = mExitingTokens.get(i);
11314 if (!token.hasVisible) {
11315 mExitingTokens.remove(i);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070011316 if (token.windowType == TYPE_WALLPAPER) {
11317 mWallpaperTokens.remove(token);
11318 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011319 }
11320 }
11321
11322 // Time to remove any exiting applications?
11323 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
11324 AppWindowToken token = mExitingAppTokens.get(i);
11325 if (!token.hasVisible && !mClosingApps.contains(token)) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -070011326 // Make sure there is no animation running on this token,
11327 // so any windows associated with it will be removed as
11328 // soon as their animations are complete
11329 token.animation = null;
11330 token.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011331 mAppTokens.remove(token);
11332 mExitingAppTokens.remove(i);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011333 if (mLastEnterAnimToken == token) {
11334 mLastEnterAnimToken = null;
11335 mLastEnterAnimParams = null;
11336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011337 }
11338 }
11339
Dianne Hackborna8f60182009-09-01 19:01:50 -070011340 boolean needRelayout = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011341
Dianne Hackborna8f60182009-09-01 19:01:50 -070011342 if (!animating && mAppTransitionRunning) {
11343 // We have finished the animation of an app transition. To do
11344 // this, we have delayed a lot of operations like showing and
11345 // hiding apps, moving apps in Z-order, etc. The app token list
11346 // reflects the correct Z-order, but the window list may now
11347 // be out of sync with it. So here we will just rebuild the
11348 // entire app window list. Fun!
11349 mAppTransitionRunning = false;
11350 needRelayout = true;
11351 rebuildAppWindowListLocked();
Dianne Hackborn16064f92010-03-25 00:47:24 -070011352 assignLayersLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070011353 // Clear information about apps that were moving.
11354 mToBottomApps.clear();
11355 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011357 if (focusDisplayed) {
11358 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
11359 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011360 if (wallpaperDestroyed) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011361 needRelayout = adjustWallpaperWindowsLocked() != 0;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011362 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070011363 if (needRelayout) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011364 requestAnimationLocked(0);
11365 } else if (animating) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011366 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
11367 }
Dianne Hackbornce73c1e2010-04-12 23:11:38 -070011368
11369 if (DEBUG_FREEZE) Slog.v(TAG, "Layout: mDisplayFrozen=" + mDisplayFrozen
11370 + " holdScreen=" + holdScreen);
11371 if (!mDisplayFrozen) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070011372 setHoldScreenLocked(holdScreen != null);
Dianne Hackbornce73c1e2010-04-12 23:11:38 -070011373 if (screenBrightness < 0 || screenBrightness > 1.0f) {
11374 mPowerManager.setScreenBrightnessOverride(-1);
11375 } else {
11376 mPowerManager.setScreenBrightnessOverride((int)
11377 (screenBrightness * Power.BRIGHTNESS_ON));
11378 }
11379 if (buttonBrightness < 0 || buttonBrightness > 1.0f) {
11380 mPowerManager.setButtonBrightnessOverride(-1);
11381 } else {
11382 mPowerManager.setButtonBrightnessOverride((int)
11383 (buttonBrightness * Power.BRIGHTNESS_ON));
11384 }
11385 if (holdScreen != mHoldingScreenOn) {
11386 mHoldingScreenOn = holdScreen;
11387 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
11388 mH.sendMessage(m);
11389 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011390 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011391
Dianne Hackborn93e462b2009-09-15 22:50:40 -070011392 if (mTurnOnScreen) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -080011393 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
Dianne Hackborn93e462b2009-09-15 22:50:40 -070011394 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
11395 LocalPowerManager.BUTTON_EVENT, true);
11396 mTurnOnScreen = false;
11397 }
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -080011398
11399 // Check to see if we are now in a state where the screen should
11400 // be enabled, because the window obscured flags have changed.
11401 enableScreenIfNeededLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011402 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070011403
11404 /**
11405 * Must be called with the main window manager lock held.
11406 */
11407 void setHoldScreenLocked(boolean holding) {
11408 boolean state = mHoldingScreenWakeLock.isHeld();
11409 if (holding != state) {
11410 if (holding) {
11411 mHoldingScreenWakeLock.acquire();
11412 } else {
11413 mPolicy.screenOnStoppedLw();
11414 mHoldingScreenWakeLock.release();
11415 }
11416 }
11417 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418
11419 void requestAnimationLocked(long delay) {
11420 if (!mAnimationPending) {
11421 mAnimationPending = true;
11422 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
11423 }
11424 }
Romain Guy06882f82009-06-10 13:36:04 -070011425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011426 /**
11427 * Have the surface flinger show a surface, robustly dealing with
11428 * error conditions. In particular, if there is not enough memory
11429 * to show the surface, then we will try to get rid of other surfaces
11430 * in order to succeed.
Romain Guy06882f82009-06-10 13:36:04 -070011431 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011432 * @return Returns true if the surface was successfully shown.
11433 */
11434 boolean showSurfaceRobustlyLocked(WindowState win) {
11435 try {
11436 if (win.mSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070011437 win.mSurfaceShown = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011438 win.mSurface.show();
Dianne Hackborn93e462b2009-09-15 22:50:40 -070011439 if (win.mTurnOnScreen) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -080011440 if (DEBUG_VISIBILITY) Slog.v(TAG,
11441 "Show surface turning screen on: " + win);
Dianne Hackborn93e462b2009-09-15 22:50:40 -070011442 win.mTurnOnScreen = false;
11443 mTurnOnScreen = true;
11444 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011445 }
11446 return true;
11447 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011448 Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011449 }
Romain Guy06882f82009-06-10 13:36:04 -070011450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011451 reclaimSomeSurfaceMemoryLocked(win, "show");
Romain Guy06882f82009-06-10 13:36:04 -070011452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011453 return false;
11454 }
Romain Guy06882f82009-06-10 13:36:04 -070011455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011456 void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
11457 final Surface surface = win.mSurface;
Romain Guy06882f82009-06-10 13:36:04 -070011458
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011459 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011460 win.mSession.mPid, operation);
Romain Guy06882f82009-06-10 13:36:04 -070011461
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011462 if (mForceRemoves == null) {
11463 mForceRemoves = new ArrayList<WindowState>();
11464 }
Romain Guy06882f82009-06-10 13:36:04 -070011465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011466 long callingIdentity = Binder.clearCallingIdentity();
11467 try {
11468 // There was some problem... first, do a sanity check of the
11469 // window list to make sure we haven't left any dangling surfaces
11470 // around.
11471 int N = mWindows.size();
11472 boolean leakedSurface = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011473 Slog.i(TAG, "Out of memory for surface! Looking for leaks...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011474 for (int i=0; i<N; i++) {
11475 WindowState ws = (WindowState)mWindows.get(i);
11476 if (ws.mSurface != null) {
11477 if (!mSessions.contains(ws.mSession)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011478 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011479 + ws + " surface=" + ws.mSurface
11480 + " token=" + win.mToken
11481 + " pid=" + ws.mSession.mPid
11482 + " uid=" + ws.mSession.mUid);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011483 ws.mSurface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070011484 ws.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011485 ws.mSurface = null;
11486 mForceRemoves.add(ws);
11487 i--;
11488 N--;
11489 leakedSurface = true;
11490 } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011491 Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011492 + ws + " surface=" + ws.mSurface
11493 + " token=" + win.mAppToken);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011494 ws.mSurface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070011495 ws.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011496 ws.mSurface = null;
11497 leakedSurface = true;
11498 }
11499 }
11500 }
Romain Guy06882f82009-06-10 13:36:04 -070011501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011502 boolean killedApps = false;
11503 if (!leakedSurface) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011504 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011505 SparseIntArray pidCandidates = new SparseIntArray();
11506 for (int i=0; i<N; i++) {
11507 WindowState ws = (WindowState)mWindows.get(i);
11508 if (ws.mSurface != null) {
11509 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
11510 }
11511 }
11512 if (pidCandidates.size() > 0) {
11513 int[] pids = new int[pidCandidates.size()];
11514 for (int i=0; i<pids.length; i++) {
11515 pids[i] = pidCandidates.keyAt(i);
11516 }
11517 try {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070011518 if (mActivityManager.killPids(pids, "Free memory")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011519 killedApps = true;
11520 }
11521 } catch (RemoteException e) {
11522 }
11523 }
11524 }
Romain Guy06882f82009-06-10 13:36:04 -070011525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 if (leakedSurface || killedApps) {
11527 // We managed to reclaim some memory, so get rid of the trouble
11528 // surface and ask the app to request another one.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011529 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011530 if (surface != null) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011531 surface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070011532 win.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011533 win.mSurface = null;
11534 }
Romain Guy06882f82009-06-10 13:36:04 -070011535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011536 try {
11537 win.mClient.dispatchGetNewSurface();
11538 } catch (RemoteException e) {
11539 }
11540 }
11541 } finally {
11542 Binder.restoreCallingIdentity(callingIdentity);
11543 }
11544 }
Romain Guy06882f82009-06-10 13:36:04 -070011545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011546 private boolean updateFocusedWindowLocked(int mode) {
11547 WindowState newFocus = computeFocusedWindowLocked();
11548 if (mCurrentFocus != newFocus) {
11549 // This check makes sure that we don't already have the focus
11550 // change message pending.
11551 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
11552 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011553 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011554 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
11555 final WindowState oldFocus = mCurrentFocus;
11556 mCurrentFocus = newFocus;
11557 mLosingFocus.remove(newFocus);
Romain Guy06882f82009-06-10 13:36:04 -070011558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011559 final WindowState imWindow = mInputMethodWindow;
11560 if (newFocus != imWindow && oldFocus != imWindow) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080011561 if (moveInputMethodWindowsIfNeededLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011562 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080011563 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
11564 mLayoutNeeded = true;
11565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011566 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
11567 performLayoutLockedInner();
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080011568 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
11569 // Client will do the layout, but we need to assign layers
11570 // for handleNewWindowLocked() below.
11571 assignLayersLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011572 }
11573 }
Jeff Brown349703e2010-06-22 01:27:15 -070011574
11575 if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
11576 // If we defer assigning layers, then the caller is responsible for
11577 // doing this part.
11578 finishUpdateFocusedWindowAfterAssignLayersLocked();
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080011579 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011580 return true;
11581 }
11582 return false;
11583 }
Jeff Brown349703e2010-06-22 01:27:15 -070011584
11585 private void finishUpdateFocusedWindowAfterAssignLayersLocked() {
11586 if (ENABLE_NATIVE_INPUT_DISPATCH) {
11587 mInputMonitor.setInputFocusLw(mCurrentFocus);
11588 } else {
11589 if (mCurrentFocus != null) {
11590 mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
11591 }
11592 }
11593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011594
11595 private WindowState computeFocusedWindowLocked() {
11596 WindowState result = null;
11597 WindowState win;
11598
11599 int i = mWindows.size() - 1;
11600 int nextAppIndex = mAppTokens.size()-1;
11601 WindowToken nextApp = nextAppIndex >= 0
11602 ? mAppTokens.get(nextAppIndex) : null;
11603
11604 while (i >= 0) {
11605 win = (WindowState)mWindows.get(i);
11606
Joe Onorato8a9b2202010-02-26 18:56:32 -080011607 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011608 TAG, "Looking for focus: " + i
11609 + " = " + win
11610 + ", flags=" + win.mAttrs.flags
11611 + ", canReceive=" + win.canReceiveKeys());
11612
11613 AppWindowToken thisApp = win.mAppToken;
Romain Guy06882f82009-06-10 13:36:04 -070011614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011615 // If this window's application has been removed, just skip it.
11616 if (thisApp != null && thisApp.removed) {
11617 i--;
11618 continue;
11619 }
Romain Guy06882f82009-06-10 13:36:04 -070011620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011621 // If there is a focused app, don't allow focus to go to any
11622 // windows below it. If this is an application window, step
11623 // through the app tokens until we find its app.
11624 if (thisApp != null && nextApp != null && thisApp != nextApp
11625 && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
11626 int origAppIndex = nextAppIndex;
11627 while (nextAppIndex > 0) {
11628 if (nextApp == mFocusedApp) {
11629 // Whoops, we are below the focused app... no focus
11630 // for you!
Joe Onorato8a9b2202010-02-26 18:56:32 -080011631 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011632 TAG, "Reached focused app: " + mFocusedApp);
11633 return null;
11634 }
11635 nextAppIndex--;
11636 nextApp = mAppTokens.get(nextAppIndex);
11637 if (nextApp == thisApp) {
11638 break;
11639 }
11640 }
11641 if (thisApp != nextApp) {
11642 // Uh oh, the app token doesn't exist! This shouldn't
11643 // happen, but if it does we can get totally hosed...
11644 // so restart at the original app.
11645 nextAppIndex = origAppIndex;
11646 nextApp = mAppTokens.get(nextAppIndex);
11647 }
11648 }
11649
11650 // Dispatch to this window if it is wants key events.
11651 if (win.canReceiveKeys()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011652 if (DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011653 TAG, "Found focus @ " + i + " = " + win);
11654 result = win;
11655 break;
11656 }
11657
11658 i--;
11659 }
11660
11661 return result;
11662 }
11663
11664 private void startFreezingDisplayLocked() {
11665 if (mDisplayFrozen) {
Chris Tate2ad63a92009-03-25 17:36:48 -070011666 // Freezing the display also suspends key event delivery, to
11667 // keep events from going astray while the display is reconfigured.
11668 // If someone has changed orientation again while the screen is
11669 // still frozen, the events will continue to be blocked while the
11670 // successive orientation change is processed. To prevent spurious
11671 // ANRs, we reset the event dispatch timeout in this case.
Jeff Brown349703e2010-06-22 01:27:15 -070011672 if (! ENABLE_NATIVE_INPUT_DISPATCH) {
11673 synchronized (mKeyWaiter) {
11674 mKeyWaiter.mWasFrozen = true;
11675 }
Chris Tate2ad63a92009-03-25 17:36:48 -070011676 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011677 return;
11678 }
Romain Guy06882f82009-06-10 13:36:04 -070011679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011680 mScreenFrozenLock.acquire();
Romain Guy06882f82009-06-10 13:36:04 -070011681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011682 long now = SystemClock.uptimeMillis();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011683 //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011684 if (mFreezeGcPending != 0) {
11685 if (now > (mFreezeGcPending+1000)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011686 //Slog.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011687 mH.removeMessages(H.FORCE_GC);
11688 Runtime.getRuntime().gc();
11689 mFreezeGcPending = now;
11690 }
11691 } else {
11692 mFreezeGcPending = now;
11693 }
Romain Guy06882f82009-06-10 13:36:04 -070011694
Dianne Hackbornce73c1e2010-04-12 23:11:38 -070011695 if (DEBUG_FREEZE) Slog.v(TAG, "*** FREEZING DISPLAY", new RuntimeException());
11696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011697 mDisplayFrozen = true;
Jeff Brown349703e2010-06-22 01:27:15 -070011698
11699 if (ENABLE_NATIVE_INPUT_DISPATCH) {
11700 mInputMonitor.freezeInputDispatchingLw();
11701 }
11702
Dianne Hackbornbfe319e2009-09-21 00:34:05 -070011703 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
11704 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011705 mNextAppTransitionPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011706 mAppTransitionReady = true;
11707 }
Romain Guy06882f82009-06-10 13:36:04 -070011708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011709 if (PROFILE_ORIENTATION) {
11710 File file = new File("/data/system/frozen");
11711 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
11712 }
11713 Surface.freezeDisplay(0);
11714 }
Romain Guy06882f82009-06-10 13:36:04 -070011715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011716 private void stopFreezingDisplayLocked() {
11717 if (!mDisplayFrozen) {
11718 return;
11719 }
Romain Guy06882f82009-06-10 13:36:04 -070011720
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011721 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
11722 return;
11723 }
11724
Dianne Hackbornce73c1e2010-04-12 23:11:38 -070011725 if (DEBUG_FREEZE) Slog.v(TAG, "*** UNFREEZING DISPLAY", new RuntimeException());
11726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011727 mDisplayFrozen = false;
11728 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
11729 if (PROFILE_ORIENTATION) {
11730 Debug.stopMethodTracing();
11731 }
11732 Surface.unfreezeDisplay(0);
Romain Guy06882f82009-06-10 13:36:04 -070011733
Chris Tate2ad63a92009-03-25 17:36:48 -070011734 // Reset the key delivery timeout on unfreeze, too. We force a wakeup here
11735 // too because regular key delivery processing should resume immediately.
Jeff Brown349703e2010-06-22 01:27:15 -070011736 if (ENABLE_NATIVE_INPUT_DISPATCH) {
11737 mInputMonitor.thawInputDispatchingLw();
11738 } else {
11739 synchronized (mKeyWaiter) {
11740 mKeyWaiter.mWasFrozen = true;
11741 mKeyWaiter.notifyAll();
11742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011743 }
11744
Christopher Tateb696aee2010-04-02 19:08:30 -070011745 // While the display is frozen we don't re-compute the orientation
11746 // to avoid inconsistent states. However, something interesting
11747 // could have actually changed during that time so re-evaluate it
11748 // now to catch that.
11749 if (updateOrientationFromAppTokensLocked()) {
11750 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
11751 }
11752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011753 // A little kludge: a lot could have happened while the
11754 // display was frozen, so now that we are coming back we
11755 // do a gc so that any remote references the system
11756 // processes holds on others can be released if they are
11757 // no longer needed.
11758 mH.removeMessages(H.FORCE_GC);
11759 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
11760 2000);
Romain Guy06882f82009-06-10 13:36:04 -070011761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011762 mScreenFrozenLock.release();
11763 }
Romain Guy06882f82009-06-10 13:36:04 -070011764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011765 @Override
11766 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
11767 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
11768 != PackageManager.PERMISSION_GRANTED) {
11769 pw.println("Permission Denial: can't dump WindowManager from from pid="
11770 + Binder.getCallingPid()
11771 + ", uid=" + Binder.getCallingUid());
11772 return;
11773 }
Romain Guy06882f82009-06-10 13:36:04 -070011774
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070011775 if (ENABLE_NATIVE_INPUT_DISPATCH) {
11776 pw.println("Input Dispatcher State:");
11777 mInputManager.dump(pw);
11778 } else {
11779 pw.println("Input State:");
11780 mQueue.dump(pw, " ");
11781 }
Dianne Hackborna2e92262010-03-02 17:19:29 -080011782 pw.println(" ");
11783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011784 synchronized(mWindowMap) {
11785 pw.println("Current Window Manager state:");
11786 for (int i=mWindows.size()-1; i>=0; i--) {
11787 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011788 pw.print(" Window #"); pw.print(i); pw.print(' ');
11789 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011790 w.dump(pw, " ");
11791 }
11792 if (mInputMethodDialogs.size() > 0) {
11793 pw.println(" ");
11794 pw.println(" Input method dialogs:");
11795 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
11796 WindowState w = mInputMethodDialogs.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011797 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011798 }
11799 }
11800 if (mPendingRemove.size() > 0) {
11801 pw.println(" ");
11802 pw.println(" Remove pending for:");
11803 for (int i=mPendingRemove.size()-1; i>=0; i--) {
11804 WindowState w = mPendingRemove.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011805 pw.print(" Remove #"); pw.print(i); pw.print(' ');
11806 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807 w.dump(pw, " ");
11808 }
11809 }
11810 if (mForceRemoves != null && mForceRemoves.size() > 0) {
11811 pw.println(" ");
11812 pw.println(" Windows force removing:");
11813 for (int i=mForceRemoves.size()-1; i>=0; i--) {
11814 WindowState w = mForceRemoves.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011815 pw.print(" Removing #"); pw.print(i); pw.print(' ');
11816 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011817 w.dump(pw, " ");
11818 }
11819 }
11820 if (mDestroySurface.size() > 0) {
11821 pw.println(" ");
11822 pw.println(" Windows waiting to destroy their surface:");
11823 for (int i=mDestroySurface.size()-1; i>=0; i--) {
11824 WindowState w = mDestroySurface.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011825 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
11826 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011827 w.dump(pw, " ");
11828 }
11829 }
11830 if (mLosingFocus.size() > 0) {
11831 pw.println(" ");
11832 pw.println(" Windows losing focus:");
11833 for (int i=mLosingFocus.size()-1; i>=0; i--) {
11834 WindowState w = mLosingFocus.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011835 pw.print(" Losing #"); pw.print(i); pw.print(' ');
11836 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011837 w.dump(pw, " ");
11838 }
11839 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011840 if (mResizingWindows.size() > 0) {
11841 pw.println(" ");
11842 pw.println(" Windows waiting to resize:");
11843 for (int i=mResizingWindows.size()-1; i>=0; i--) {
11844 WindowState w = mResizingWindows.get(i);
11845 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
11846 pw.print(w); pw.println(":");
11847 w.dump(pw, " ");
11848 }
11849 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011850 if (mSessions.size() > 0) {
11851 pw.println(" ");
11852 pw.println(" All active sessions:");
11853 Iterator<Session> it = mSessions.iterator();
11854 while (it.hasNext()) {
11855 Session s = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011856 pw.print(" Session "); pw.print(s); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011857 s.dump(pw, " ");
11858 }
11859 }
11860 if (mTokenMap.size() > 0) {
11861 pw.println(" ");
11862 pw.println(" All tokens:");
11863 Iterator<WindowToken> it = mTokenMap.values().iterator();
11864 while (it.hasNext()) {
11865 WindowToken token = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011866 pw.print(" Token "); pw.print(token.token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011867 token.dump(pw, " ");
11868 }
11869 }
11870 if (mTokenList.size() > 0) {
11871 pw.println(" ");
11872 pw.println(" Window token list:");
11873 for (int i=0; i<mTokenList.size(); i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011874 pw.print(" #"); pw.print(i); pw.print(": ");
11875 pw.println(mTokenList.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011876 }
11877 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070011878 if (mWallpaperTokens.size() > 0) {
11879 pw.println(" ");
11880 pw.println(" Wallpaper tokens:");
11881 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
11882 WindowToken token = mWallpaperTokens.get(i);
11883 pw.print(" Wallpaper #"); pw.print(i);
11884 pw.print(' '); pw.print(token); pw.println(':');
11885 token.dump(pw, " ");
11886 }
11887 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011888 if (mAppTokens.size() > 0) {
11889 pw.println(" ");
11890 pw.println(" Application tokens in Z order:");
11891 for (int i=mAppTokens.size()-1; i>=0; i--) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011892 pw.print(" App #"); pw.print(i); pw.print(": ");
11893 pw.println(mAppTokens.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011894 }
11895 }
11896 if (mFinishedStarting.size() > 0) {
11897 pw.println(" ");
11898 pw.println(" Finishing start of application tokens:");
11899 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
11900 WindowToken token = mFinishedStarting.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011901 pw.print(" Finished Starting #"); pw.print(i);
11902 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011903 token.dump(pw, " ");
11904 }
11905 }
11906 if (mExitingTokens.size() > 0) {
11907 pw.println(" ");
11908 pw.println(" Exiting tokens:");
11909 for (int i=mExitingTokens.size()-1; i>=0; i--) {
11910 WindowToken token = mExitingTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011911 pw.print(" Exiting #"); pw.print(i);
11912 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011913 token.dump(pw, " ");
11914 }
11915 }
11916 if (mExitingAppTokens.size() > 0) {
11917 pw.println(" ");
11918 pw.println(" Exiting application tokens:");
11919 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
11920 WindowToken token = mExitingAppTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011921 pw.print(" Exiting App #"); pw.print(i);
11922 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011923 token.dump(pw, " ");
11924 }
11925 }
11926 pw.println(" ");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011927 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
11928 pw.print(" mLastFocus="); pw.println(mLastFocus);
11929 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
11930 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
11931 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
Dianne Hackbornf21adf62009-08-13 10:20:21 -070011932 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
Dianne Hackborn284ac932009-08-28 10:34:25 -070011933 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
11934 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
11935 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
11936 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011937 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration);
11938 pw.print(" mInTouchMode="); pw.print(mInTouchMode);
11939 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011940 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
11941 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
11942 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
11943 pw.print(" mBlurShown="); pw.println(mBlurShown);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011944 if (mDimAnimator != null) {
11945 mDimAnimator.printTo(pw);
11946 } else {
Dianne Hackborna2e92262010-03-02 17:19:29 -080011947 pw.println( " no DimAnimator ");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011948 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011949 pw.print(" mInputMethodAnimLayerAdjustment=");
Dianne Hackborn759a39e2009-08-09 17:20:27 -070011950 pw.print(mInputMethodAnimLayerAdjustment);
11951 pw.print(" mWallpaperAnimLayerAdjustment=");
11952 pw.println(mWallpaperAnimLayerAdjustment);
Dianne Hackborn284ac932009-08-28 10:34:25 -070011953 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
11954 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011955 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
11956 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011957 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
11958 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011959 pw.print(" mRotation="); pw.print(mRotation);
11960 pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
11961 pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
11962 pw.print(" mAnimationPending="); pw.print(mAnimationPending);
11963 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
11964 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
11965 pw.print(" mNextAppTransition=0x");
11966 pw.print(Integer.toHexString(mNextAppTransition));
11967 pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
Dianne Hackborna8f60182009-09-01 19:01:50 -070011968 pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011969 pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011970 if (mNextAppTransitionPackage != null) {
11971 pw.print(" mNextAppTransitionPackage=");
11972 pw.print(mNextAppTransitionPackage);
11973 pw.print(", mNextAppTransitionEnter=0x");
11974 pw.print(Integer.toHexString(mNextAppTransitionEnter));
11975 pw.print(", mNextAppTransitionExit=0x");
11976 pw.print(Integer.toHexString(mNextAppTransitionExit));
11977 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011978 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
11979 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011980 if (mLastEnterAnimToken != null || mLastEnterAnimToken != null) {
11981 pw.print(" mLastEnterAnimToken="); pw.print(mLastEnterAnimToken);
11982 pw.print(", mLastEnterAnimParams="); pw.println(mLastEnterAnimParams);
11983 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011984 if (mOpeningApps.size() > 0) {
11985 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
11986 }
11987 if (mClosingApps.size() > 0) {
11988 pw.print(" mClosingApps="); pw.println(mClosingApps);
11989 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070011990 if (mToTopApps.size() > 0) {
11991 pw.print(" mToTopApps="); pw.println(mToTopApps);
11992 }
11993 if (mToBottomApps.size() > 0) {
11994 pw.print(" mToBottomApps="); pw.println(mToBottomApps);
11995 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011996 pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth());
11997 pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
Jeff Brown349703e2010-06-22 01:27:15 -070011998
11999 if (! ENABLE_NATIVE_INPUT_DISPATCH) {
12000 pw.println(" KeyWaiter state:");
12001 pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin);
12002 pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
12003 pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished);
12004 pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
12005 pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
12006 pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
12007 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012008 }
12009 }
12010
Jeff Brown349703e2010-06-22 01:27:15 -070012011 // Called by the heartbeat to ensure locks are not held indefnitely (for deadlock detection).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012012 public void monitor() {
12013 synchronized (mWindowMap) { }
Mike Lockwood983ee092009-11-22 01:42:24 -050012014 synchronized (mKeyguardTokenWatcher) { }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012015 synchronized (mKeyWaiter) { }
Jeff Brown349703e2010-06-22 01:27:15 -070012016 synchronized (mInputMonitor) { }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012017 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012018
Dianne Hackbornddca3ee2009-07-23 19:01:31 -070012019 public void virtualKeyFeedback(KeyEvent event) {
12020 mPolicy.keyFeedbackFromInput(event);
12021 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080012022
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012023 /**
12024 * DimAnimator class that controls the dim animation. This holds the surface and
Doug Zongkerab5c49c2009-12-04 10:31:43 -080012025 * all state used for dim animation.
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012026 */
12027 private static class DimAnimator {
12028 Surface mDimSurface;
12029 boolean mDimShown = false;
12030 float mDimCurrentAlpha;
12031 float mDimTargetAlpha;
12032 float mDimDeltaPerMs;
12033 long mLastDimAnimTime;
Dianne Hackbornf83c5552010-03-31 22:19:32 -070012034
12035 int mLastDimWidth, mLastDimHeight;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012036
12037 DimAnimator (SurfaceSession session) {
12038 if (mDimSurface == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012039 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012040 + mDimSurface + ": CREATE");
12041 try {
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080012042 mDimSurface = new Surface(session, 0,
12043 "DimSurface",
12044 -1, 16, 16, PixelFormat.OPAQUE,
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012045 Surface.FX_SURFACE_DIM);
Maciej Białka9ee5c222010-03-24 10:25:40 +010012046 mDimSurface.setAlpha(0.0f);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012047 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012048 Slog.e(TAG, "Exception creating Dim surface", e);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012049 }
12050 }
12051 }
12052
12053 /**
12054 * Show the dim surface.
12055 */
12056 void show(int dw, int dh) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070012057 if (!mDimShown) {
12058 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
12059 dw + "x" + dh + ")");
12060 mDimShown = true;
12061 try {
Dianne Hackbornf83c5552010-03-31 22:19:32 -070012062 mLastDimWidth = dw;
12063 mLastDimHeight = dh;
Dianne Hackborn16064f92010-03-25 00:47:24 -070012064 mDimSurface.setPosition(0, 0);
12065 mDimSurface.setSize(dw, dh);
12066 mDimSurface.show();
12067 } catch (RuntimeException e) {
12068 Slog.w(TAG, "Failure showing dim surface", e);
12069 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -070012070 } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
12071 mLastDimWidth = dw;
12072 mLastDimHeight = dh;
12073 mDimSurface.setSize(dw, dh);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012074 }
12075 }
12076
12077 /**
12078 * Set's the dim surface's layer and update dim parameters that will be used in
12079 * {@link updateSurface} after all windows are examined.
12080 */
12081 void updateParameters(WindowState w, long currentTime) {
12082 mDimSurface.setLayer(w.mAnimLayer-1);
12083
12084 final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012085 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070012086 + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012087 if (mDimTargetAlpha != target) {
12088 // If the desired dim level has changed, then
12089 // start an animation to it.
12090 mLastDimAnimTime = currentTime;
12091 long duration = (w.mAnimating && w.mAnimation != null)
12092 ? w.mAnimation.computeDurationHint()
12093 : DEFAULT_DIM_DURATION;
12094 if (target > mDimTargetAlpha) {
12095 // This is happening behind the activity UI,
12096 // so we can make it run a little longer to
12097 // give a stronger impression without disrupting
12098 // the user.
12099 duration *= DIM_DURATION_MULTIPLIER;
12100 }
12101 if (duration < 1) {
12102 // Don't divide by zero
12103 duration = 1;
12104 }
12105 mDimTargetAlpha = target;
12106 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
12107 }
12108 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080012109
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012110 /**
12111 * Updating the surface's alpha. Returns true if the animation continues, or returns
12112 * false when the animation is finished and the dim surface is hidden.
12113 */
12114 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
12115 if (!dimming) {
12116 if (mDimTargetAlpha != 0) {
12117 mLastDimAnimTime = currentTime;
12118 mDimTargetAlpha = 0;
12119 mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
12120 }
12121 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080012122
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012123 boolean animating = false;
12124 if (mLastDimAnimTime != 0) {
12125 mDimCurrentAlpha += mDimDeltaPerMs
12126 * (currentTime-mLastDimAnimTime);
12127 boolean more = true;
12128 if (displayFrozen) {
12129 // If the display is frozen, there is no reason to animate.
12130 more = false;
12131 } else if (mDimDeltaPerMs > 0) {
12132 if (mDimCurrentAlpha > mDimTargetAlpha) {
12133 more = false;
12134 }
12135 } else if (mDimDeltaPerMs < 0) {
12136 if (mDimCurrentAlpha < mDimTargetAlpha) {
12137 more = false;
12138 }
12139 } else {
12140 more = false;
12141 }
12142
12143 // Do we need to continue animating?
12144 if (more) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012145 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012146 + mDimSurface + ": alpha=" + mDimCurrentAlpha);
12147 mLastDimAnimTime = currentTime;
12148 mDimSurface.setAlpha(mDimCurrentAlpha);
12149 animating = true;
12150 } else {
12151 mDimCurrentAlpha = mDimTargetAlpha;
12152 mLastDimAnimTime = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012153 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012154 + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
12155 mDimSurface.setAlpha(mDimCurrentAlpha);
12156 if (!dimming) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012157 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012158 + ": HIDE");
12159 try {
12160 mDimSurface.hide();
12161 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012162 Slog.w(TAG, "Illegal argument exception hiding dim surface");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012163 }
12164 mDimShown = false;
12165 }
12166 }
12167 }
12168 return animating;
12169 }
12170
12171 public void printTo(PrintWriter pw) {
12172 pw.print(" mDimShown="); pw.print(mDimShown);
12173 pw.print(" current="); pw.print(mDimCurrentAlpha);
12174 pw.print(" target="); pw.print(mDimTargetAlpha);
12175 pw.print(" delta="); pw.print(mDimDeltaPerMs);
12176 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
12177 }
12178 }
12179
12180 /**
12181 * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
12182 * This is used for opening/closing transition for apps in compatible mode.
12183 */
12184 private static class FadeInOutAnimation extends Animation {
12185 int mWidth;
12186 boolean mFadeIn;
12187
12188 public FadeInOutAnimation(boolean fadeIn) {
12189 setInterpolator(new AccelerateInterpolator());
12190 setDuration(DEFAULT_FADE_IN_OUT_DURATION);
12191 mFadeIn = fadeIn;
12192 }
12193
12194 @Override
12195 protected void applyTransformation(float interpolatedTime, Transformation t) {
12196 float x = interpolatedTime;
12197 if (!mFadeIn) {
12198 x = 1.0f - x; // reverse the interpolation for fade out
12199 }
12200 if (x < 0.5) {
12201 // move the window out of the screen.
12202 t.getMatrix().setTranslate(mWidth, 0);
12203 } else {
12204 t.getMatrix().setTranslate(0, 0);// show
12205 t.setAlpha((x - 0.5f) * 2);
12206 }
12207 }
12208
12209 @Override
12210 public void initialize(int width, int height, int parentWidth, int parentHeight) {
12211 // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
12212 mWidth = width;
12213 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012214
12215 @Override
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -070012216 public int getZAdjustment() {
12217 return Animation.ZORDER_TOP;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012218 }
12219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012220}