blob: f742f9fa023e0903856dce043914db868cdecf2a [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;
46import com.android.internal.view.IInputContext;
47import com.android.internal.view.IInputMethodClient;
48import com.android.internal.view.IInputMethodManager;
49import com.android.server.KeyInputQueue.QueuedEvent;
50import com.android.server.am.BatteryStatsService;
51
52import android.Manifest;
53import android.app.ActivityManagerNative;
54import android.app.IActivityManager;
55import android.content.Context;
56import android.content.pm.ActivityInfo;
57import android.content.pm.PackageManager;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070058import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.res.Configuration;
60import android.graphics.Matrix;
61import android.graphics.PixelFormat;
62import android.graphics.Rect;
63import android.graphics.Region;
64import android.os.BatteryStats;
65import android.os.Binder;
66import android.os.Debug;
67import android.os.Handler;
68import android.os.IBinder;
Michael Chan53071d62009-05-13 17:29:48 -070069import android.os.LatencyTimer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070import android.os.LocalPowerManager;
71import android.os.Looper;
72import android.os.Message;
73import android.os.Parcel;
74import android.os.ParcelFileDescriptor;
75import android.os.Power;
76import android.os.PowerManager;
77import android.os.Process;
78import android.os.RemoteException;
79import android.os.ServiceManager;
80import android.os.SystemClock;
81import android.os.SystemProperties;
82import android.os.TokenWatcher;
83import android.provider.Settings;
Dianne Hackborn723738c2009-06-25 19:48:04 -070084import android.util.DisplayMetrics;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085import android.util.EventLog;
86import android.util.Log;
87import android.util.SparseIntArray;
88import android.view.Display;
89import android.view.Gravity;
90import android.view.IApplicationToken;
91import android.view.IOnKeyguardExitResult;
92import android.view.IRotationWatcher;
93import android.view.IWindow;
94import android.view.IWindowManager;
95import android.view.IWindowSession;
96import android.view.KeyEvent;
97import android.view.MotionEvent;
98import android.view.RawInputEvent;
99import android.view.Surface;
100import android.view.SurfaceSession;
101import android.view.View;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700102import android.view.ViewConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103import android.view.ViewTreeObserver;
104import android.view.WindowManager;
105import android.view.WindowManagerImpl;
106import android.view.WindowManagerPolicy;
107import android.view.WindowManager.LayoutParams;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700108import android.view.animation.AccelerateInterpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800109import android.view.animation.Animation;
110import android.view.animation.AnimationUtils;
111import android.view.animation.Transformation;
112
113import java.io.BufferedWriter;
114import java.io.File;
115import java.io.FileDescriptor;
116import java.io.IOException;
117import java.io.OutputStream;
118import java.io.OutputStreamWriter;
119import java.io.PrintWriter;
120import java.io.StringWriter;
121import java.net.Socket;
122import java.util.ArrayList;
123import java.util.HashMap;
124import java.util.HashSet;
125import java.util.Iterator;
126import java.util.List;
127
128/** {@hide} */
Dianne Hackbornddca3ee2009-07-23 19:01:31 -0700129public class WindowManagerService extends IWindowManager.Stub
130 implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800131 static final String TAG = "WindowManager";
132 static final boolean DEBUG = false;
133 static final boolean DEBUG_FOCUS = false;
134 static final boolean DEBUG_ANIM = false;
135 static final boolean DEBUG_LAYERS = false;
136 static final boolean DEBUG_INPUT = false;
137 static final boolean DEBUG_INPUT_METHOD = false;
138 static final boolean DEBUG_VISIBILITY = false;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -0700139 static final boolean DEBUG_WINDOW_MOVEMENT = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 static final boolean DEBUG_ORIENTATION = false;
141 static final boolean DEBUG_APP_TRANSITIONS = false;
142 static final boolean DEBUG_STARTING_WINDOW = false;
143 static final boolean DEBUG_REORDER = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700144 static final boolean DEBUG_WALLPAPER = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean SHOW_TRANSACTIONS = false;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700146 static final boolean HIDE_STACK_CRAWLS = true;
Michael Chan53071d62009-05-13 17:29:48 -0700147 static final boolean MEASURE_LATENCY = false;
148 static private LatencyTimer lt;
149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 static final boolean PROFILE_ORIENTATION = false;
151 static final boolean BLUR = true;
Dave Bortcfe65242009-04-09 14:51:04 -0700152 static final boolean localLOGV = DEBUG;
Romain Guy06882f82009-06-10 13:36:04 -0700153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 static final int LOG_WM_NO_SURFACE_MEMORY = 31000;
Romain Guy06882f82009-06-10 13:36:04 -0700155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 /** How long to wait for subsequent key repeats, in milliseconds */
157 static final int KEY_REPEAT_DELAY = 50;
158
159 /** How much to multiply the policy's type layer, to reserve room
160 * for multiple windows of the same type and Z-ordering adjustment
161 * with TYPE_LAYER_OFFSET. */
162 static final int TYPE_LAYER_MULTIPLIER = 10000;
Romain Guy06882f82009-06-10 13:36:04 -0700163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800164 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
165 * or below others in the same layer. */
166 static final int TYPE_LAYER_OFFSET = 1000;
Romain Guy06882f82009-06-10 13:36:04 -0700167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 /** How much to increment the layer for each window, to reserve room
169 * for effect surfaces between them.
170 */
171 static final int WINDOW_LAYER_MULTIPLIER = 5;
Romain Guy06882f82009-06-10 13:36:04 -0700172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 /** The maximum length we will accept for a loaded animation duration:
174 * this is 10 seconds.
175 */
176 static final int MAX_ANIMATION_DURATION = 10*1000;
177
178 /** Amount of time (in milliseconds) to animate the dim surface from one
179 * value to another, when no window animation is driving it.
180 */
181 static final int DEFAULT_DIM_DURATION = 200;
182
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700183 /** Amount of time (in milliseconds) to animate the fade-in-out transition for
184 * compatible windows.
185 */
186 static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 /** Adjustment to time to perform a dim, to make it more dramatic.
189 */
190 static final int DIM_DURATION_MULTIPLIER = 6;
Romain Guy06882f82009-06-10 13:36:04 -0700191
Dianne Hackborncfaef692009-06-15 14:24:44 -0700192 static final int INJECT_FAILED = 0;
193 static final int INJECT_SUCCEEDED = 1;
194 static final int INJECT_NO_PERMISSION = -1;
195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 static final int UPDATE_FOCUS_NORMAL = 0;
197 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
198 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
199 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
Romain Guy06882f82009-06-10 13:36:04 -0700200
Michael Chane96440f2009-05-06 10:27:36 -0700201 /** The minimum time between dispatching touch events. */
202 int mMinWaitTimeBetweenTouchEvents = 1000 / 35;
203
204 // Last touch event time
205 long mLastTouchEventTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700206
Michael Chane96440f2009-05-06 10:27:36 -0700207 // Last touch event type
208 int mLastTouchEventType = OTHER_EVENT;
Romain Guy06882f82009-06-10 13:36:04 -0700209
Michael Chane96440f2009-05-06 10:27:36 -0700210 // Time to wait before calling useractivity again. This saves CPU usage
211 // when we get a flood of touch events.
212 static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000;
213
214 // Last time we call user activity
215 long mLastUserActivityCallTime = 0;
216
Romain Guy06882f82009-06-10 13:36:04 -0700217 // Last time we updated battery stats
Michael Chane96440f2009-05-06 10:27:36 -0700218 long mLastBatteryStatsCallTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 private static final String SYSTEM_SECURE = "ro.secure";
Romain Guy06882f82009-06-10 13:36:04 -0700221 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222
223 /**
224 * Condition waited on by {@link #reenableKeyguard} to know the call to
225 * the window policy has finished.
226 */
227 private boolean mWaitingUntilKeyguardReenabled = false;
228
229
230 final TokenWatcher mKeyguardDisabled = new TokenWatcher(
231 new Handler(), "WindowManagerService.mKeyguardDisabled") {
232 public void acquired() {
233 mPolicy.enableKeyguard(false);
234 }
235 public void released() {
236 synchronized (mKeyguardDisabled) {
237 mPolicy.enableKeyguard(true);
238 mWaitingUntilKeyguardReenabled = false;
239 mKeyguardDisabled.notifyAll();
240 }
241 }
242 };
243
244 final Context mContext;
245
246 final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 final boolean mLimitedAlphaCompositing;
Romain Guy06882f82009-06-10 13:36:04 -0700249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
251
252 final IActivityManager mActivityManager;
Romain Guy06882f82009-06-10 13:36:04 -0700253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 final IBatteryStats mBatteryStats;
Romain Guy06882f82009-06-10 13:36:04 -0700255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 /**
257 * All currently active sessions with clients.
258 */
259 final HashSet<Session> mSessions = new HashSet<Session>();
Romain Guy06882f82009-06-10 13:36:04 -0700260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 /**
262 * Mapping from an IWindow IBinder to the server's Window object.
263 * This is also used as the lock for all of our state.
264 */
265 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
266
267 /**
268 * Mapping from a token IBinder to a WindowToken object.
269 */
270 final HashMap<IBinder, WindowToken> mTokenMap =
271 new HashMap<IBinder, WindowToken>();
272
273 /**
274 * The same tokens as mTokenMap, stored in a list for efficient iteration
275 * over them.
276 */
277 final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 /**
280 * Window tokens that are in the process of exiting, but still
281 * on screen for animations.
282 */
283 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
284
285 /**
286 * Z-ordered (bottom-most first) list of all application tokens, for
287 * controlling the ordering of windows in different applications. This
288 * contains WindowToken objects.
289 */
290 final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
291
292 /**
293 * Application tokens that are in the process of exiting, but still
294 * on screen for animations.
295 */
296 final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
297
298 /**
299 * List of window tokens that have finished starting their application,
300 * and now need to have the policy remove their windows.
301 */
302 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
303
304 /**
305 * Z-ordered (bottom-most first) list of all Window objects.
306 */
307 final ArrayList mWindows = new ArrayList();
308
309 /**
310 * Windows that are being resized. Used so we can tell the client about
311 * the resize after closing the transaction in which we resized the
312 * underlying surface.
313 */
314 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
315
316 /**
317 * Windows whose animations have ended and now must be removed.
318 */
319 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
320
321 /**
322 * Windows whose surface should be destroyed.
323 */
324 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
325
326 /**
327 * Windows that have lost input focus and are waiting for the new
328 * focus window to be displayed before they are told about this.
329 */
330 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
331
332 /**
333 * This is set when we have run out of memory, and will either be an empty
334 * list or contain windows that need to be force removed.
335 */
336 ArrayList<WindowState> mForceRemoves;
Romain Guy06882f82009-06-10 13:36:04 -0700337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800338 IInputMethodManager mInputMethodManager;
Romain Guy06882f82009-06-10 13:36:04 -0700339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 SurfaceSession mFxSession;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700341 private DimAnimator mDimAnimator = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 Surface mBlurSurface;
343 boolean mBlurShown;
Romain Guy06882f82009-06-10 13:36:04 -0700344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800345 int mTransactionSequence = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 final float[] mTmpFloats = new float[9];
348
349 boolean mSafeMode;
350 boolean mDisplayEnabled = false;
351 boolean mSystemBooted = false;
352 int mRotation = 0;
353 int mRequestedRotation = 0;
354 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Dianne Hackborn321ae682009-03-27 16:16:03 -0700355 int mLastRotationFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356 ArrayList<IRotationWatcher> mRotationWatchers
357 = new ArrayList<IRotationWatcher>();
Romain Guy06882f82009-06-10 13:36:04 -0700358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800359 boolean mLayoutNeeded = true;
360 boolean mAnimationPending = false;
361 boolean mDisplayFrozen = false;
362 boolean mWindowsFreezingScreen = false;
363 long mFreezeGcPending = 0;
364 int mAppsFreezingScreen = 0;
365
366 // This is held as long as we have the screen frozen, to give us time to
367 // perform a rotation animation when turning off shows the lock screen which
368 // changes the orientation.
369 PowerManager.WakeLock mScreenFrozenLock;
Romain Guy06882f82009-06-10 13:36:04 -0700370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 // State management of app transitions. When we are preparing for a
372 // transition, mNextAppTransition will be the kind of transition to
373 // perform or TRANSIT_NONE if we are not waiting. If we are waiting,
374 // mOpeningApps and mClosingApps are the lists of tokens that will be
375 // made visible or hidden at the next transition.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700376 int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 boolean mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -0700378 boolean mAppTransitionRunning = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 boolean mAppTransitionTimeout = false;
380 boolean mStartingIconInTransition = false;
381 boolean mSkipAppTransitionAnimation = false;
382 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
383 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
Dianne Hackborna8f60182009-09-01 19:01:50 -0700384 final ArrayList<AppWindowToken> mToTopApps = new ArrayList<AppWindowToken>();
385 final ArrayList<AppWindowToken> mToBottomApps = new ArrayList<AppWindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 //flag to detect fat touch events
388 boolean mFatTouch = false;
389 Display mDisplay;
Romain Guy06882f82009-06-10 13:36:04 -0700390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 H mH = new H();
392
393 WindowState mCurrentFocus = null;
394 WindowState mLastFocus = null;
Romain Guy06882f82009-06-10 13:36:04 -0700395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 // This just indicates the window the input method is on top of, not
397 // necessarily the window its input is going to.
398 WindowState mInputMethodTarget = null;
399 WindowState mUpcomingInputMethodTarget = null;
400 boolean mInputMethodTargetWaitingAnim;
401 int mInputMethodAnimLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -0700402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 WindowState mInputMethodWindow = null;
404 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
405
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700406 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
407
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700408 // If non-null, this is the currently visible window that is associated
409 // with the wallpaper.
410 WindowState mWallpaperTarget = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700411 // If non-null, we are in the middle of animating from one wallpaper target
412 // to another, and this is the lower one in Z-order.
413 WindowState mLowerWallpaperTarget = null;
414 // If non-null, we are in the middle of animating from one wallpaper target
415 // to another, and this is the higher one in Z-order.
416 WindowState mUpperWallpaperTarget = null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700417 int mWallpaperAnimLayerAdjustment;
Dianne Hackborn284ac932009-08-28 10:34:25 -0700418 float mLastWallpaperX;
419 float mLastWallpaperY;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700420 // Lock for waiting for the wallpaper.
421 final Object mWaitingOnWallpaperLock = new Object();
422 // This is set when we are waiting for a wallpaper to tell us it is done
423 // changing its scroll position.
424 WindowState mWaitingOnWallpaper;
425 // The last time we had a timeout when waiting for a wallpaper.
426 long mLastWallpaperTimeoutTime;
427 // We give a wallpaper up to 150ms to finish scrolling.
428 static final long WALLPAPER_TIMEOUT = 150;
429 // Time we wait after a timeout before trying to wait again.
430 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800432 AppWindowToken mFocusedApp = null;
433
434 PowerManagerService mPowerManager;
Romain Guy06882f82009-06-10 13:36:04 -0700435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 float mWindowAnimationScale = 1.0f;
437 float mTransitionAnimationScale = 1.0f;
Romain Guy06882f82009-06-10 13:36:04 -0700438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 final KeyWaiter mKeyWaiter = new KeyWaiter();
440 final KeyQ mQueue;
441 final InputDispatcherThread mInputThread;
442
443 // Who is holding the screen on.
444 Session mHoldingScreenOn;
Romain Guy06882f82009-06-10 13:36:04 -0700445
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700446 boolean mTurnOnScreen;
447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 /**
449 * Whether the UI is currently running in touch mode (not showing
450 * navigational focus because the user is directly pressing the screen).
451 */
452 boolean mInTouchMode = false;
453
454 private ViewServer mViewServer;
455
456 final Rect mTempRect = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -0700457
Dianne Hackbornc485a602009-03-24 22:39:49 -0700458 final Configuration mTempConfiguration = new Configuration();
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700459 int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700460
461 // The frame use to limit the size of the app running in compatibility mode.
462 Rect mCompatibleScreenFrame = new Rect();
463 // The surface used to fill the outer rim of the app running in compatibility mode.
464 Surface mBackgroundFillerSurface = null;
465 boolean mBackgroundFillerShown = false;
466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 public static WindowManagerService main(Context context,
468 PowerManagerService pm, boolean haveInputMethods) {
469 WMThread thr = new WMThread(context, pm, haveInputMethods);
470 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800472 synchronized (thr) {
473 while (thr.mService == null) {
474 try {
475 thr.wait();
476 } catch (InterruptedException e) {
477 }
478 }
479 }
Romain Guy06882f82009-06-10 13:36:04 -0700480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 return thr.mService;
482 }
Romain Guy06882f82009-06-10 13:36:04 -0700483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 static class WMThread extends Thread {
485 WindowManagerService mService;
Romain Guy06882f82009-06-10 13:36:04 -0700486
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800487 private final Context mContext;
488 private final PowerManagerService mPM;
489 private final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491 public WMThread(Context context, PowerManagerService pm,
492 boolean haveInputMethods) {
493 super("WindowManager");
494 mContext = context;
495 mPM = pm;
496 mHaveInputMethods = haveInputMethods;
497 }
Romain Guy06882f82009-06-10 13:36:04 -0700498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 public void run() {
500 Looper.prepare();
501 WindowManagerService s = new WindowManagerService(mContext, mPM,
502 mHaveInputMethods);
503 android.os.Process.setThreadPriority(
504 android.os.Process.THREAD_PRIORITY_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -0700505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800506 synchronized (this) {
507 mService = s;
508 notifyAll();
509 }
Romain Guy06882f82009-06-10 13:36:04 -0700510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 Looper.loop();
512 }
513 }
514
515 static class PolicyThread extends Thread {
516 private final WindowManagerPolicy mPolicy;
517 private final WindowManagerService mService;
518 private final Context mContext;
519 private final PowerManagerService mPM;
520 boolean mRunning = false;
Romain Guy06882f82009-06-10 13:36:04 -0700521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 public PolicyThread(WindowManagerPolicy policy,
523 WindowManagerService service, Context context,
524 PowerManagerService pm) {
525 super("WindowManagerPolicy");
526 mPolicy = policy;
527 mService = service;
528 mContext = context;
529 mPM = pm;
530 }
Romain Guy06882f82009-06-10 13:36:04 -0700531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 public void run() {
533 Looper.prepare();
534 //Looper.myLooper().setMessageLogging(new LogPrinter(
535 // Log.VERBOSE, "WindowManagerPolicy"));
536 android.os.Process.setThreadPriority(
537 android.os.Process.THREAD_PRIORITY_FOREGROUND);
538 mPolicy.init(mContext, mService, mPM);
Romain Guy06882f82009-06-10 13:36:04 -0700539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 synchronized (this) {
541 mRunning = true;
542 notifyAll();
543 }
Romain Guy06882f82009-06-10 13:36:04 -0700544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 Looper.loop();
546 }
547 }
548
549 private WindowManagerService(Context context, PowerManagerService pm,
550 boolean haveInputMethods) {
Michael Chan53071d62009-05-13 17:29:48 -0700551 if (MEASURE_LATENCY) {
552 lt = new LatencyTimer(100, 1000);
553 }
554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800555 mContext = context;
556 mHaveInputMethods = haveInputMethods;
557 mLimitedAlphaCompositing = context.getResources().getBoolean(
558 com.android.internal.R.bool.config_sf_limitedAlpha);
Romain Guy06882f82009-06-10 13:36:04 -0700559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 mPowerManager = pm;
561 mPowerManager.setPolicy(mPolicy);
562 PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
563 mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
564 "SCREEN_FROZEN");
565 mScreenFrozenLock.setReferenceCounted(false);
566
567 mActivityManager = ActivityManagerNative.getDefault();
568 mBatteryStats = BatteryStatsService.getService();
569
570 // Get persisted window scale setting
571 mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
572 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
573 mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
574 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
Romain Guy06882f82009-06-10 13:36:04 -0700575
Michael Chan9f028e62009-08-04 17:37:46 -0700576 int max_events_per_sec = 35;
577 try {
578 max_events_per_sec = Integer.parseInt(SystemProperties
579 .get("windowsmgr.max_events_per_sec"));
580 if (max_events_per_sec < 1) {
581 max_events_per_sec = 35;
582 }
583 } catch (NumberFormatException e) {
584 }
585 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800587 mQueue = new KeyQ();
588
589 mInputThread = new InputDispatcherThread();
Romain Guy06882f82009-06-10 13:36:04 -0700590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
592 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 synchronized (thr) {
595 while (!thr.mRunning) {
596 try {
597 thr.wait();
598 } catch (InterruptedException e) {
599 }
600 }
601 }
Romain Guy06882f82009-06-10 13:36:04 -0700602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 mInputThread.start();
Romain Guy06882f82009-06-10 13:36:04 -0700604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 // Add ourself to the Watchdog monitors.
606 Watchdog.getInstance().addMonitor(this);
607 }
608
609 @Override
610 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
611 throws RemoteException {
612 try {
613 return super.onTransact(code, data, reply, flags);
614 } catch (RuntimeException e) {
615 // The window manager only throws security exceptions, so let's
616 // log all others.
617 if (!(e instanceof SecurityException)) {
618 Log.e(TAG, "Window Manager Crash", e);
619 }
620 throw e;
621 }
622 }
623
624 private void placeWindowAfter(Object pos, WindowState window) {
625 final int i = mWindows.indexOf(pos);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700626 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 TAG, "Adding window " + window + " at "
628 + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
629 mWindows.add(i+1, window);
630 }
631
632 private void placeWindowBefore(Object pos, WindowState window) {
633 final int i = mWindows.indexOf(pos);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700634 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800635 TAG, "Adding window " + window + " at "
636 + i + " of " + mWindows.size() + " (before " + pos + ")");
637 mWindows.add(i, window);
638 }
639
640 //This method finds out the index of a window that has the same app token as
641 //win. used for z ordering the windows in mWindows
642 private int findIdxBasedOnAppTokens(WindowState win) {
643 //use a local variable to cache mWindows
644 ArrayList localmWindows = mWindows;
645 int jmax = localmWindows.size();
646 if(jmax == 0) {
647 return -1;
648 }
649 for(int j = (jmax-1); j >= 0; j--) {
650 WindowState wentry = (WindowState)localmWindows.get(j);
651 if(wentry.mAppToken == win.mAppToken) {
652 return j;
653 }
654 }
655 return -1;
656 }
Romain Guy06882f82009-06-10 13:36:04 -0700657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800658 private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
659 final IWindow client = win.mClient;
660 final WindowToken token = win.mToken;
661 final ArrayList localmWindows = mWindows;
Romain Guy06882f82009-06-10 13:36:04 -0700662
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 final int N = localmWindows.size();
664 final WindowState attached = win.mAttachedWindow;
665 int i;
666 if (attached == null) {
667 int tokenWindowsPos = token.windows.size();
668 if (token.appWindowToken != null) {
669 int index = tokenWindowsPos-1;
670 if (index >= 0) {
671 // If this application has existing windows, we
672 // simply place the new window on top of them... but
673 // keep the starting window on top.
674 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
675 // Base windows go behind everything else.
676 placeWindowBefore(token.windows.get(0), win);
677 tokenWindowsPos = 0;
678 } else {
679 AppWindowToken atoken = win.mAppToken;
680 if (atoken != null &&
681 token.windows.get(index) == atoken.startingWindow) {
682 placeWindowBefore(token.windows.get(index), win);
683 tokenWindowsPos--;
684 } else {
685 int newIdx = findIdxBasedOnAppTokens(win);
686 if(newIdx != -1) {
Romain Guy06882f82009-06-10 13:36:04 -0700687 //there is a window above this one associated with the same
688 //apptoken note that the window could be a floating window
689 //that was created later or a window at the top of the list of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 //windows associated with this token.
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700691 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
692 TAG, "Adding window " + win + " at "
693 + (newIdx+1) + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 localmWindows.add(newIdx+1, win);
Romain Guy06882f82009-06-10 13:36:04 -0700695 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 }
697 }
698 } else {
699 if (localLOGV) Log.v(
700 TAG, "Figuring out where to add app window "
701 + client.asBinder() + " (token=" + token + ")");
702 // Figure out where the window should go, based on the
703 // order of applications.
704 final int NA = mAppTokens.size();
705 Object pos = null;
706 for (i=NA-1; i>=0; i--) {
707 AppWindowToken t = mAppTokens.get(i);
708 if (t == token) {
709 i--;
710 break;
711 }
Dianne Hackborna8f60182009-09-01 19:01:50 -0700712
713 // We haven't reached the token yet; if this token
714 // is not going to the bottom and has windows, we can
715 // use it as an anchor for when we do reach the token.
716 if (!t.sendingToBottom && t.windows.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 pos = t.windows.get(0);
718 }
719 }
720 // We now know the index into the apps. If we found
721 // an app window above, that gives us the position; else
722 // we need to look some more.
723 if (pos != null) {
724 // Move behind any windows attached to this one.
Romain Guy06882f82009-06-10 13:36:04 -0700725 WindowToken atoken =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 mTokenMap.get(((WindowState)pos).mClient.asBinder());
727 if (atoken != null) {
728 final int NC = atoken.windows.size();
729 if (NC > 0) {
730 WindowState bottom = atoken.windows.get(0);
731 if (bottom.mSubLayer < 0) {
732 pos = bottom;
733 }
734 }
735 }
736 placeWindowBefore(pos, win);
737 } else {
Dianne Hackborna8f60182009-09-01 19:01:50 -0700738 // Continue looking down until we find the first
739 // token that has windows.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 while (i >= 0) {
741 AppWindowToken t = mAppTokens.get(i);
742 final int NW = t.windows.size();
743 if (NW > 0) {
744 pos = t.windows.get(NW-1);
745 break;
746 }
747 i--;
748 }
749 if (pos != null) {
750 // Move in front of any windows attached to this
751 // one.
752 WindowToken atoken =
753 mTokenMap.get(((WindowState)pos).mClient.asBinder());
754 if (atoken != null) {
755 final int NC = atoken.windows.size();
756 if (NC > 0) {
757 WindowState top = atoken.windows.get(NC-1);
758 if (top.mSubLayer >= 0) {
759 pos = top;
760 }
761 }
762 }
763 placeWindowAfter(pos, win);
764 } else {
765 // Just search for the start of this layer.
766 final int myLayer = win.mBaseLayer;
767 for (i=0; i<N; i++) {
768 WindowState w = (WindowState)localmWindows.get(i);
769 if (w.mBaseLayer > myLayer) {
770 break;
771 }
772 }
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700773 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
774 TAG, "Adding window " + win + " at "
775 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 localmWindows.add(i, win);
777 }
778 }
779 }
780 } else {
781 // Figure out where window should go, based on layer.
782 final int myLayer = win.mBaseLayer;
783 for (i=N-1; i>=0; i--) {
784 if (((WindowState)localmWindows.get(i)).mBaseLayer <= myLayer) {
785 i++;
786 break;
787 }
788 }
789 if (i < 0) i = 0;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700790 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
791 TAG, "Adding window " + win + " at "
792 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800793 localmWindows.add(i, win);
794 }
795 if (addToToken) {
796 token.windows.add(tokenWindowsPos, win);
797 }
798
799 } else {
800 // Figure out this window's ordering relative to the window
801 // it is attached to.
802 final int NA = token.windows.size();
803 final int sublayer = win.mSubLayer;
804 int largestSublayer = Integer.MIN_VALUE;
805 WindowState windowWithLargestSublayer = null;
806 for (i=0; i<NA; i++) {
807 WindowState w = token.windows.get(i);
808 final int wSublayer = w.mSubLayer;
809 if (wSublayer >= largestSublayer) {
810 largestSublayer = wSublayer;
811 windowWithLargestSublayer = w;
812 }
813 if (sublayer < 0) {
814 // For negative sublayers, we go below all windows
815 // in the same sublayer.
816 if (wSublayer >= sublayer) {
817 if (addToToken) {
818 token.windows.add(i, win);
819 }
820 placeWindowBefore(
821 wSublayer >= 0 ? attached : w, win);
822 break;
823 }
824 } else {
825 // For positive sublayers, we go above all windows
826 // in the same sublayer.
827 if (wSublayer > sublayer) {
828 if (addToToken) {
829 token.windows.add(i, win);
830 }
831 placeWindowBefore(w, win);
832 break;
833 }
834 }
835 }
836 if (i >= NA) {
837 if (addToToken) {
838 token.windows.add(win);
839 }
840 if (sublayer < 0) {
841 placeWindowBefore(attached, win);
842 } else {
843 placeWindowAfter(largestSublayer >= 0
844 ? windowWithLargestSublayer
845 : attached,
846 win);
847 }
848 }
849 }
Romain Guy06882f82009-06-10 13:36:04 -0700850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800851 if (win.mAppToken != null && addToToken) {
852 win.mAppToken.allAppWindows.add(win);
853 }
854 }
Romain Guy06882f82009-06-10 13:36:04 -0700855
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 static boolean canBeImeTarget(WindowState w) {
857 final int fl = w.mAttrs.flags
858 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
859 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
860 return w.isVisibleOrAdding();
861 }
862 return false;
863 }
Romain Guy06882f82009-06-10 13:36:04 -0700864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
866 final ArrayList localmWindows = mWindows;
867 final int N = localmWindows.size();
868 WindowState w = null;
869 int i = N;
870 while (i > 0) {
871 i--;
872 w = (WindowState)localmWindows.get(i);
Romain Guy06882f82009-06-10 13:36:04 -0700873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 //Log.i(TAG, "Checking window @" + i + " " + w + " fl=0x"
875 // + Integer.toHexString(w.mAttrs.flags));
876 if (canBeImeTarget(w)) {
877 //Log.i(TAG, "Putting input method here!");
Romain Guy06882f82009-06-10 13:36:04 -0700878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 // Yet more tricksyness! If this window is a "starting"
880 // window, we do actually want to be on top of it, but
881 // it is not -really- where input will go. So if the caller
882 // is not actually looking to move the IME, look down below
883 // for a real window to target...
884 if (!willMove
885 && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
886 && i > 0) {
887 WindowState wb = (WindowState)localmWindows.get(i-1);
888 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
889 i--;
890 w = wb;
891 }
892 }
893 break;
894 }
895 }
Romain Guy06882f82009-06-10 13:36:04 -0700896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 mUpcomingInputMethodTarget = w;
Romain Guy06882f82009-06-10 13:36:04 -0700898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800899 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Desired input method target="
900 + w + " willMove=" + willMove);
Romain Guy06882f82009-06-10 13:36:04 -0700901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 if (willMove && w != null) {
903 final WindowState curTarget = mInputMethodTarget;
904 if (curTarget != null && curTarget.mAppToken != null) {
Romain Guy06882f82009-06-10 13:36:04 -0700905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 // Now some fun for dealing with window animations that
907 // modify the Z order. We need to look at all windows below
908 // the current target that are in this app, finding the highest
909 // visible one in layering.
910 AppWindowToken token = curTarget.mAppToken;
911 WindowState highestTarget = null;
912 int highestPos = 0;
913 if (token.animating || token.animation != null) {
914 int pos = 0;
915 pos = localmWindows.indexOf(curTarget);
916 while (pos >= 0) {
917 WindowState win = (WindowState)localmWindows.get(pos);
918 if (win.mAppToken != token) {
919 break;
920 }
921 if (!win.mRemoved) {
922 if (highestTarget == null || win.mAnimLayer >
923 highestTarget.mAnimLayer) {
924 highestTarget = win;
925 highestPos = pos;
926 }
927 }
928 pos--;
929 }
930 }
Romain Guy06882f82009-06-10 13:36:04 -0700931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800932 if (highestTarget != null) {
Romain Guy06882f82009-06-10 13:36:04 -0700933 if (DEBUG_INPUT_METHOD) Log.v(TAG, "mNextAppTransition="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 + mNextAppTransition + " " + highestTarget
935 + " animating=" + highestTarget.isAnimating()
936 + " layer=" + highestTarget.mAnimLayer
937 + " new layer=" + w.mAnimLayer);
Romain Guy06882f82009-06-10 13:36:04 -0700938
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700939 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 // If we are currently setting up for an animation,
941 // hold everything until we can find out what will happen.
942 mInputMethodTargetWaitingAnim = true;
943 mInputMethodTarget = highestTarget;
944 return highestPos + 1;
945 } else if (highestTarget.isAnimating() &&
946 highestTarget.mAnimLayer > w.mAnimLayer) {
947 // If the window we are currently targeting is involved
948 // with an animation, and it is on top of the next target
949 // we will be over, then hold off on moving until
950 // that is done.
951 mInputMethodTarget = highestTarget;
952 return highestPos + 1;
953 }
954 }
955 }
956 }
Romain Guy06882f82009-06-10 13:36:04 -0700957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 //Log.i(TAG, "Placing input method @" + (i+1));
959 if (w != null) {
960 if (willMove) {
961 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700962 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963 if (DEBUG_INPUT_METHOD) Log.w(TAG, "Moving IM target from "
964 + mInputMethodTarget + " to " + w, e);
965 mInputMethodTarget = w;
966 if (w.mAppToken != null) {
967 setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
968 } else {
969 setInputMethodAnimLayerAdjustment(0);
970 }
971 }
972 return i+1;
973 }
974 if (willMove) {
975 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700976 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800977 if (DEBUG_INPUT_METHOD) Log.w(TAG, "Moving IM target from "
978 + mInputMethodTarget + " to null", e);
979 mInputMethodTarget = null;
980 setInputMethodAnimLayerAdjustment(0);
981 }
982 return -1;
983 }
Romain Guy06882f82009-06-10 13:36:04 -0700984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800985 void addInputMethodWindowToListLocked(WindowState win) {
986 int pos = findDesiredInputMethodWindowIndexLocked(true);
987 if (pos >= 0) {
988 win.mTargetAppToken = mInputMethodTarget.mAppToken;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700989 if (DEBUG_WINDOW_MOVEMENT) Log.v(
990 TAG, "Adding input method window " + win + " at " + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 mWindows.add(pos, win);
992 moveInputMethodDialogsLocked(pos+1);
993 return;
994 }
995 win.mTargetAppToken = null;
996 addWindowToListInOrderLocked(win, true);
997 moveInputMethodDialogsLocked(pos);
998 }
Romain Guy06882f82009-06-10 13:36:04 -0700999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 void setInputMethodAnimLayerAdjustment(int adj) {
1001 if (DEBUG_LAYERS) Log.v(TAG, "Setting im layer adj to " + adj);
1002 mInputMethodAnimLayerAdjustment = adj;
1003 WindowState imw = mInputMethodWindow;
1004 if (imw != null) {
1005 imw.mAnimLayer = imw.mLayer + adj;
1006 if (DEBUG_LAYERS) Log.v(TAG, "IM win " + imw
1007 + " anim layer: " + imw.mAnimLayer);
1008 int wi = imw.mChildWindows.size();
1009 while (wi > 0) {
1010 wi--;
1011 WindowState cw = (WindowState)imw.mChildWindows.get(wi);
1012 cw.mAnimLayer = cw.mLayer + adj;
1013 if (DEBUG_LAYERS) Log.v(TAG, "IM win " + cw
1014 + " anim layer: " + cw.mAnimLayer);
1015 }
1016 }
1017 int di = mInputMethodDialogs.size();
1018 while (di > 0) {
1019 di --;
1020 imw = mInputMethodDialogs.get(di);
1021 imw.mAnimLayer = imw.mLayer + adj;
1022 if (DEBUG_LAYERS) Log.v(TAG, "IM win " + imw
1023 + " anim layer: " + imw.mAnimLayer);
1024 }
1025 }
Romain Guy06882f82009-06-10 13:36:04 -07001026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001027 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1028 int wpos = mWindows.indexOf(win);
1029 if (wpos >= 0) {
1030 if (wpos < interestingPos) interestingPos--;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001031 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Temp removing at " + wpos + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 mWindows.remove(wpos);
1033 int NC = win.mChildWindows.size();
1034 while (NC > 0) {
1035 NC--;
1036 WindowState cw = (WindowState)win.mChildWindows.get(NC);
1037 int cpos = mWindows.indexOf(cw);
1038 if (cpos >= 0) {
1039 if (cpos < interestingPos) interestingPos--;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001040 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Temp removing child at "
1041 + cpos + ": " + cw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 mWindows.remove(cpos);
1043 }
1044 }
1045 }
1046 return interestingPos;
1047 }
Romain Guy06882f82009-06-10 13:36:04 -07001048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001049 private void reAddWindowToListInOrderLocked(WindowState win) {
1050 addWindowToListInOrderLocked(win, false);
1051 // This is a hack to get all of the child windows added as well
1052 // at the right position. Child windows should be rare and
1053 // this case should be rare, so it shouldn't be that big a deal.
1054 int wpos = mWindows.indexOf(win);
1055 if (wpos >= 0) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001056 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "ReAdd removing from " + wpos
1057 + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 mWindows.remove(wpos);
1059 reAddWindowLocked(wpos, win);
1060 }
1061 }
Romain Guy06882f82009-06-10 13:36:04 -07001062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 void logWindowList(String prefix) {
1064 int N = mWindows.size();
1065 while (N > 0) {
1066 N--;
1067 Log.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
1068 }
1069 }
Romain Guy06882f82009-06-10 13:36:04 -07001070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 void moveInputMethodDialogsLocked(int pos) {
1072 ArrayList<WindowState> dialogs = mInputMethodDialogs;
Romain Guy06882f82009-06-10 13:36:04 -07001073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 final int N = dialogs.size();
1075 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
1076 for (int i=0; i<N; i++) {
1077 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1078 }
1079 if (DEBUG_INPUT_METHOD) {
1080 Log.v(TAG, "Window list w/pos=" + pos);
1081 logWindowList(" ");
1082 }
Romain Guy06882f82009-06-10 13:36:04 -07001083
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 if (pos >= 0) {
1085 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1086 if (pos < mWindows.size()) {
1087 WindowState wp = (WindowState)mWindows.get(pos);
1088 if (wp == mInputMethodWindow) {
1089 pos++;
1090 }
1091 }
1092 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
1093 for (int i=0; i<N; i++) {
1094 WindowState win = dialogs.get(i);
1095 win.mTargetAppToken = targetAppToken;
1096 pos = reAddWindowLocked(pos, win);
1097 }
1098 if (DEBUG_INPUT_METHOD) {
1099 Log.v(TAG, "Final window list:");
1100 logWindowList(" ");
1101 }
1102 return;
1103 }
1104 for (int i=0; i<N; i++) {
1105 WindowState win = dialogs.get(i);
1106 win.mTargetAppToken = null;
1107 reAddWindowToListInOrderLocked(win);
1108 if (DEBUG_INPUT_METHOD) {
1109 Log.v(TAG, "No IM target, final list:");
1110 logWindowList(" ");
1111 }
1112 }
1113 }
Romain Guy06882f82009-06-10 13:36:04 -07001114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1116 final WindowState imWin = mInputMethodWindow;
1117 final int DN = mInputMethodDialogs.size();
1118 if (imWin == null && DN == 0) {
1119 return false;
1120 }
Romain Guy06882f82009-06-10 13:36:04 -07001121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1123 if (imPos >= 0) {
1124 // In this case, the input method windows are to be placed
1125 // immediately above the window they are targeting.
Romain Guy06882f82009-06-10 13:36:04 -07001126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 // First check to see if the input method windows are already
1128 // located here, and contiguous.
1129 final int N = mWindows.size();
1130 WindowState firstImWin = imPos < N
1131 ? (WindowState)mWindows.get(imPos) : null;
Romain Guy06882f82009-06-10 13:36:04 -07001132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 // Figure out the actual input method window that should be
1134 // at the bottom of their stack.
1135 WindowState baseImWin = imWin != null
1136 ? imWin : mInputMethodDialogs.get(0);
1137 if (baseImWin.mChildWindows.size() > 0) {
1138 WindowState cw = (WindowState)baseImWin.mChildWindows.get(0);
1139 if (cw.mSubLayer < 0) baseImWin = cw;
1140 }
Romain Guy06882f82009-06-10 13:36:04 -07001141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142 if (firstImWin == baseImWin) {
1143 // The windows haven't moved... but are they still contiguous?
1144 // First find the top IM window.
1145 int pos = imPos+1;
1146 while (pos < N) {
1147 if (!((WindowState)mWindows.get(pos)).mIsImWindow) {
1148 break;
1149 }
1150 pos++;
1151 }
1152 pos++;
1153 // Now there should be no more input method windows above.
1154 while (pos < N) {
1155 if (((WindowState)mWindows.get(pos)).mIsImWindow) {
1156 break;
1157 }
1158 pos++;
1159 }
1160 if (pos >= N) {
1161 // All is good!
1162 return false;
1163 }
1164 }
Romain Guy06882f82009-06-10 13:36:04 -07001165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 if (imWin != null) {
1167 if (DEBUG_INPUT_METHOD) {
1168 Log.v(TAG, "Moving IM from " + imPos);
1169 logWindowList(" ");
1170 }
1171 imPos = tmpRemoveWindowLocked(imPos, imWin);
1172 if (DEBUG_INPUT_METHOD) {
1173 Log.v(TAG, "List after moving with new pos " + imPos + ":");
1174 logWindowList(" ");
1175 }
1176 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1177 reAddWindowLocked(imPos, imWin);
1178 if (DEBUG_INPUT_METHOD) {
1179 Log.v(TAG, "List after moving IM to " + imPos + ":");
1180 logWindowList(" ");
1181 }
1182 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1183 } else {
1184 moveInputMethodDialogsLocked(imPos);
1185 }
Romain Guy06882f82009-06-10 13:36:04 -07001186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 } else {
1188 // In this case, the input method windows go in a fixed layer,
1189 // because they aren't currently associated with a focus window.
Romain Guy06882f82009-06-10 13:36:04 -07001190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 if (imWin != null) {
1192 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Moving IM from " + imPos);
1193 tmpRemoveWindowLocked(0, imWin);
1194 imWin.mTargetAppToken = null;
1195 reAddWindowToListInOrderLocked(imWin);
1196 if (DEBUG_INPUT_METHOD) {
1197 Log.v(TAG, "List with no IM target:");
1198 logWindowList(" ");
1199 }
1200 if (DN > 0) moveInputMethodDialogsLocked(-1);;
1201 } else {
1202 moveInputMethodDialogsLocked(-1);;
1203 }
Romain Guy06882f82009-06-10 13:36:04 -07001204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 }
Romain Guy06882f82009-06-10 13:36:04 -07001206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 if (needAssignLayers) {
1208 assignLayersLocked();
1209 }
Romain Guy06882f82009-06-10 13:36:04 -07001210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 return true;
1212 }
Romain Guy06882f82009-06-10 13:36:04 -07001213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001214 void adjustInputMethodDialogsLocked() {
1215 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
1216 }
Romain Guy06882f82009-06-10 13:36:04 -07001217
Dianne Hackborn25994b42009-09-04 14:21:19 -07001218 final boolean isWallpaperVisible(WindowState wallpaperTarget) {
1219 if (DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper vis: target obscured="
1220 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1221 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1222 ? wallpaperTarget.mAppToken.animation : null)
1223 + " upper=" + mUpperWallpaperTarget
1224 + " lower=" + mLowerWallpaperTarget);
1225 return (wallpaperTarget != null
1226 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1227 && wallpaperTarget.mAppToken.animation != null)))
1228 || mUpperWallpaperTarget != null
1229 || mLowerWallpaperTarget != null;
1230 }
1231
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001232 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1233 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
1234
1235 int adjustWallpaperWindowsLocked() {
1236 int changed = 0;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001237
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001238 final int dw = mDisplay.getWidth();
1239 final int dh = mDisplay.getHeight();
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001240
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001241 // First find top-most window that has asked to be on top of the
1242 // wallpaper; all wallpapers go behind it.
1243 final ArrayList localmWindows = mWindows;
1244 int N = localmWindows.size();
1245 WindowState w = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001246 WindowState foundW = null;
1247 int foundI = 0;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001248 int i = N;
1249 while (i > 0) {
1250 i--;
1251 w = (WindowState)localmWindows.get(i);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001252 if (w.mAppToken != null) {
1253 // If this window's app token is hidden and not animating,
1254 // it is of no interest to us.
1255 if (w.mAppToken.hidden && w.mAppToken.animation == null) {
1256 if (DEBUG_WALLPAPER) Log.v(TAG,
1257 "Skipping hidden or animating token: " + w);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001258 continue;
1259 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001260 }
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001261 if (DEBUG_WALLPAPER) Log.v(TAG, "Win " + w + ": readyfordisplay="
1262 + w.isReadyForDisplay() + " drawpending=" + w.mDrawPending
1263 + " commitdrawpending=" + w.mCommitDrawPending);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001264 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07001265 && (mWallpaperTarget == w
1266 || (!w.mDrawPending && !w.mCommitDrawPending))) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001267 if (DEBUG_WALLPAPER) Log.v(TAG,
1268 "Found wallpaper activity: #" + i + "=" + w);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001269 foundW = w;
1270 foundI = i;
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001271 if (w == mWallpaperTarget && w.mAppToken != null
1272 && w.mAppToken.animation != null) {
1273 // The current wallpaper target is animating, so we'll
1274 // look behind it for another possible target and figure
1275 // out what is going on below.
1276 if (DEBUG_WALLPAPER) Log.v(TAG, "Win " + w
1277 + ": token animating, looking behind.");
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001278 continue;
1279 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001280 break;
1281 }
1282 }
1283
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001284 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001285 // If we are currently waiting for an app transition, and either
1286 // the current target or the next target are involved with it,
1287 // then hold off on doing anything with the wallpaper.
1288 // Note that we are checking here for just whether the target
1289 // is part of an app token... which is potentially overly aggressive
1290 // (the app token may not be involved in the transition), but good
1291 // enough (we'll just wait until whatever transition is pending
1292 // executes).
1293 if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001294 if (DEBUG_WALLPAPER) Log.v(TAG,
1295 "Wallpaper not changing: waiting for app anim in current target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001296 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001297 }
1298 if (foundW != null && foundW.mAppToken != null) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001299 if (DEBUG_WALLPAPER) Log.v(TAG,
1300 "Wallpaper not changing: waiting for app anim in found target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001301 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001302 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001303 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001304
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001305 if (mWallpaperTarget != foundW) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001306 if (DEBUG_WALLPAPER) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001307 Log.v(TAG, "New wallpaper target: " + foundW
1308 + " oldTarget: " + mWallpaperTarget);
1309 }
1310
1311 mLowerWallpaperTarget = null;
1312 mUpperWallpaperTarget = null;
1313
1314 WindowState oldW = mWallpaperTarget;
1315 mWallpaperTarget = foundW;
1316
1317 // Now what is happening... if the current and new targets are
1318 // animating, then we are in our super special mode!
1319 if (foundW != null && foundW.mAppToken != null && oldW != null
1320 && oldW.mAppToken != null) {
1321 if (DEBUG_WALLPAPER) {
1322 Log.v(TAG, "New animation: " + foundW.mAppToken.animation
1323 + " old animation: " + oldW.mAppToken.animation);
1324 }
1325 if (foundW.mAppToken.animation != null
1326 && oldW.mAppToken.animation != null) {
1327 int oldI = localmWindows.indexOf(oldW);
1328 if (DEBUG_WALLPAPER) {
1329 Log.v(TAG, "New i: " + foundI + " old i: " + oldI);
1330 }
1331 if (oldI >= 0) {
1332 if (DEBUG_WALLPAPER) {
1333 Log.v(TAG, "Animating wallpapers: old#" + oldI
1334 + "=" + oldW + "; new#" + foundI
1335 + "=" + foundW);
1336 }
1337
1338 // Set the new target correctly.
1339 if (foundW.mAppToken.hiddenRequested) {
1340 if (DEBUG_WALLPAPER) {
1341 Log.v(TAG, "Old wallpaper still the target.");
1342 }
1343 mWallpaperTarget = oldW;
1344 }
1345
1346 // Now set the upper and lower wallpaper targets
1347 // correctly, and make sure that we are positioning
1348 // the wallpaper below the lower.
1349 if (foundI > oldI) {
1350 // The new target is on top of the old one.
1351 if (DEBUG_WALLPAPER) {
1352 Log.v(TAG, "Found target above old target.");
1353 }
1354 mUpperWallpaperTarget = foundW;
1355 mLowerWallpaperTarget = oldW;
1356 foundW = oldW;
1357 foundI = oldI;
1358 } else {
1359 // The new target is below the old one.
1360 if (DEBUG_WALLPAPER) {
1361 Log.v(TAG, "Found target below old target.");
1362 }
1363 mUpperWallpaperTarget = oldW;
1364 mLowerWallpaperTarget = foundW;
1365 }
1366 }
1367 }
1368 }
1369
1370 } else {
1371 // Is it time to stop animating?
1372 if (mLowerWallpaperTarget == null
1373 || mLowerWallpaperTarget.mAppToken.animation == null
1374 || mUpperWallpaperTarget == null
1375 || mUpperWallpaperTarget.mAppToken.animation == null) {
1376 if (DEBUG_WALLPAPER) {
1377 Log.v(TAG, "No longer animating wallpaper targets!");
1378 }
1379 mLowerWallpaperTarget = null;
1380 mUpperWallpaperTarget = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001381 }
1382 }
1383
1384 boolean visible = foundW != null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001385 if (visible) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001386 // The window is visible to the compositor... but is it visible
1387 // to the user? That is what the wallpaper cares about.
Dianne Hackborn25994b42009-09-04 14:21:19 -07001388 visible = isWallpaperVisible(foundW);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001389 if (DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper visibility: " + visible);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001390
1391 // If the wallpaper target is animating, we may need to copy
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001392 // its layer adjustment. Only do this if we are not transfering
1393 // between two wallpaper targets.
1394 mWallpaperAnimLayerAdjustment =
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001395 (mLowerWallpaperTarget == null && foundW.mAppToken != null)
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001396 ? foundW.mAppToken.animLayerAdjustment : 0;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001397
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001398 final int maxLayer = mPolicy.getMaxWallpaperLayer()
1399 * TYPE_LAYER_MULTIPLIER
1400 + TYPE_LAYER_OFFSET;
1401
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001402 // Now w is the window we are supposed to be behind... but we
1403 // need to be sure to also be behind any of its attached windows,
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001404 // AND any starting window associated with it, AND below the
1405 // maximum layer the policy allows for wallpapers.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001406 while (foundI > 0) {
1407 WindowState wb = (WindowState)localmWindows.get(foundI-1);
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001408 if (wb.mBaseLayer < maxLayer &&
1409 wb.mAttachedWindow != foundW &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001410 (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001411 wb.mToken != foundW.mToken)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001412 // This window is not related to the previous one in any
1413 // interesting way, so stop here.
1414 break;
1415 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001416 foundW = wb;
1417 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001418 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07001419 } else {
1420 if (DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper not visible");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001421 }
1422
1423 // Okay i is the position immediately above the wallpaper. Look at
1424 // what is below it for later.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001425 foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001426
Dianne Hackborn284ac932009-08-28 10:34:25 -07001427 if (visible) {
1428 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
1429 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
1430 }
1431
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001432 // Start stepping backwards from here, ensuring that our wallpaper windows
1433 // are correctly placed.
1434 int curTokenIndex = mWallpaperTokens.size();
1435 while (curTokenIndex > 0) {
1436 curTokenIndex--;
1437 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001438 if (token.hidden == visible) {
1439 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1440 token.hidden = !visible;
1441 // Need to do a layout to ensure the wallpaper now has the
1442 // correct size.
1443 mLayoutNeeded = true;
1444 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07001445
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001446 int curWallpaperIndex = token.windows.size();
1447 while (curWallpaperIndex > 0) {
1448 curWallpaperIndex--;
1449 WindowState wallpaper = token.windows.get(curWallpaperIndex);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001450
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001451 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001452 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001453 }
1454
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001455 // First, make sure the client has the current visibility
1456 // state.
1457 if (wallpaper.mWallpaperVisible != visible) {
1458 wallpaper.mWallpaperVisible = visible;
1459 try {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001460 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Log.v(TAG,
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001461 "Setting visibility of wallpaper " + wallpaper
1462 + ": " + visible);
1463 wallpaper.mClient.dispatchAppVisibility(visible);
1464 } catch (RemoteException e) {
1465 }
1466 }
1467
1468 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001469 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper win "
1470 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001471
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001472 // First, if this window is at the current index, then all
1473 // is well.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001474 if (wallpaper == foundW) {
1475 foundI--;
1476 foundW = foundI > 0
1477 ? (WindowState)localmWindows.get(foundI-1) : null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001478 continue;
1479 }
1480
1481 // The window didn't match... the current wallpaper window,
1482 // wherever it is, is in the wrong place, so make sure it is
1483 // not in the list.
1484 int oldIndex = localmWindows.indexOf(wallpaper);
1485 if (oldIndex >= 0) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001486 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Wallpaper removing at "
1487 + oldIndex + ": " + wallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001488 localmWindows.remove(oldIndex);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001489 if (oldIndex < foundI) {
1490 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001491 }
1492 }
1493
1494 // Now stick it in.
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001495 if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
1496 "Moving wallpaper " + wallpaper
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001497 + " from " + oldIndex + " to " + foundI);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001498
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001499 localmWindows.add(foundI, wallpaper);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001500 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001501 }
1502 }
1503
1504 return changed;
1505 }
1506
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001507 void setWallpaperAnimLayerAdjustmentLocked(int adj) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001508 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Log.v(TAG,
1509 "Setting wallpaper layer adj to " + adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001510 mWallpaperAnimLayerAdjustment = adj;
1511 int curTokenIndex = mWallpaperTokens.size();
1512 while (curTokenIndex > 0) {
1513 curTokenIndex--;
1514 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1515 int curWallpaperIndex = token.windows.size();
1516 while (curWallpaperIndex > 0) {
1517 curWallpaperIndex--;
1518 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1519 wallpaper.mAnimLayer = wallpaper.mLayer + adj;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001520 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper win "
1521 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001522 }
1523 }
1524 }
1525
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001526 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1527 boolean sync) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001528 boolean changed = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001529 boolean rawChanged = false;
Dianne Hackborn284ac932009-08-28 10:34:25 -07001530 if (mLastWallpaperX >= 0) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001531 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
Dianne Hackborn284ac932009-08-28 10:34:25 -07001532 int offset = availw > 0 ? -(int)(availw*mLastWallpaperX+.5f) : 0;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001533 changed = wallpaperWin.mXOffset != offset;
1534 if (changed) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001535 if (DEBUG_WALLPAPER) Log.v(TAG, "Update wallpaper "
1536 + wallpaperWin + " x: " + offset);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001537 wallpaperWin.mXOffset = offset;
1538 }
Dianne Hackborn284ac932009-08-28 10:34:25 -07001539 if (wallpaperWin.mWallpaperX != mLastWallpaperX) {
1540 wallpaperWin.mWallpaperX = mLastWallpaperX;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001541 rawChanged = true;
1542 }
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001543 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001544
Dianne Hackborn284ac932009-08-28 10:34:25 -07001545 if (mLastWallpaperY >= 0) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001546 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
Dianne Hackborn284ac932009-08-28 10:34:25 -07001547 int offset = availh > 0 ? -(int)(availh*mLastWallpaperY+.5f) : 0;
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001548 if (wallpaperWin.mYOffset != offset) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001549 if (DEBUG_WALLPAPER) Log.v(TAG, "Update wallpaper "
1550 + wallpaperWin + " y: " + offset);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001551 changed = true;
1552 wallpaperWin.mYOffset = offset;
1553 }
Dianne Hackborn284ac932009-08-28 10:34:25 -07001554 if (wallpaperWin.mWallpaperY != mLastWallpaperY) {
1555 wallpaperWin.mWallpaperY = mLastWallpaperY;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001556 rawChanged = true;
1557 }
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001558 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001559
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001560 if (rawChanged) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001561 try {
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001562 if (DEBUG_WALLPAPER) Log.v(TAG, "Report new wp offset "
1563 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1564 + " y=" + wallpaperWin.mWallpaperY);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001565 if (sync) {
1566 synchronized (mWaitingOnWallpaperLock) {
1567 mWaitingOnWallpaper = wallpaperWin;
1568 }
1569 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001570 wallpaperWin.mClient.dispatchWallpaperOffsets(
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001571 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, sync);
1572 if (sync) {
1573 synchronized (mWaitingOnWallpaperLock) {
1574 if (mWaitingOnWallpaper != null) {
1575 long start = SystemClock.uptimeMillis();
1576 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
1577 < start) {
1578 try {
1579 if (DEBUG_WALLPAPER) Log.v(TAG,
1580 "Waiting for offset complete...");
1581 mWaitingOnWallpaperLock.wait(WALLPAPER_TIMEOUT);
1582 } catch (InterruptedException e) {
1583 }
1584 if (DEBUG_WALLPAPER) Log.v(TAG, "Offset complete!");
1585 if ((start+WALLPAPER_TIMEOUT)
1586 < SystemClock.uptimeMillis()) {
1587 Log.i(TAG, "Timeout waiting for wallpaper to offset: "
1588 + wallpaperWin);
1589 mLastWallpaperTimeoutTime = start;
1590 }
1591 }
1592 mWaitingOnWallpaper = null;
1593 }
1594 }
1595 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001596 } catch (RemoteException e) {
1597 }
1598 }
1599
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001600 return changed;
1601 }
1602
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001603 void wallpaperOffsetsComplete(IBinder window) {
1604 synchronized (mWaitingOnWallpaperLock) {
1605 if (mWaitingOnWallpaper != null &&
1606 mWaitingOnWallpaper.mClient.asBinder() == window) {
1607 mWaitingOnWallpaper = null;
1608 mWaitingOnWallpaperLock.notifyAll();
1609 }
1610 }
1611 }
1612
1613 boolean updateWallpaperOffsetLocked(boolean sync) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001614 final int dw = mDisplay.getWidth();
1615 final int dh = mDisplay.getHeight();
1616
1617 boolean changed = false;
1618
1619 WindowState target = mWallpaperTarget;
1620 if (target != null) {
Dianne Hackborn284ac932009-08-28 10:34:25 -07001621 mLastWallpaperX = target.mWallpaperX;
1622 mLastWallpaperY = target.mWallpaperY;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001623 int curTokenIndex = mWallpaperTokens.size();
1624 while (curTokenIndex > 0) {
1625 curTokenIndex--;
1626 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1627 int curWallpaperIndex = token.windows.size();
1628 while (curWallpaperIndex > 0) {
1629 curWallpaperIndex--;
1630 WindowState wallpaper = token.windows.get(curWallpaperIndex);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001631 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001632 wallpaper.computeShownFrameLocked();
1633 changed = true;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001634 // We only want to be synchronous with one wallpaper.
1635 sync = false;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001636 }
1637 }
1638 }
1639 }
1640
1641 return changed;
1642 }
1643
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001644 void updateWallpaperVisibilityLocked() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07001645 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001646 final int dw = mDisplay.getWidth();
1647 final int dh = mDisplay.getHeight();
1648
1649 int curTokenIndex = mWallpaperTokens.size();
1650 while (curTokenIndex > 0) {
1651 curTokenIndex--;
1652 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001653 if (token.hidden == visible) {
1654 token.hidden = !visible;
1655 // Need to do a layout to ensure the wallpaper now has the
1656 // correct size.
1657 mLayoutNeeded = true;
1658 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07001659
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001660 int curWallpaperIndex = token.windows.size();
1661 while (curWallpaperIndex > 0) {
1662 curWallpaperIndex--;
1663 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1664 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001665 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001666 }
1667
1668 if (wallpaper.mWallpaperVisible != visible) {
1669 wallpaper.mWallpaperVisible = visible;
1670 try {
1671 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Log.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07001672 "Updating visibility of wallpaper " + wallpaper
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001673 + ": " + visible);
1674 wallpaper.mClient.dispatchAppVisibility(visible);
1675 } catch (RemoteException e) {
1676 }
1677 }
1678 }
1679 }
1680 }
1681
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001682 void sendPointerToWallpaperLocked(WindowState srcWin,
1683 MotionEvent pointer, long eventTime) {
1684 int curTokenIndex = mWallpaperTokens.size();
1685 while (curTokenIndex > 0) {
1686 curTokenIndex--;
1687 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1688 int curWallpaperIndex = token.windows.size();
1689 while (curWallpaperIndex > 0) {
1690 curWallpaperIndex--;
1691 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1692 if ((wallpaper.mAttrs.flags &
1693 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
1694 continue;
1695 }
1696 try {
1697 MotionEvent ev = MotionEvent.obtainNoHistory(pointer);
1698 ev.offsetLocation(srcWin.mFrame.left-wallpaper.mFrame.left,
1699 srcWin.mFrame.top-wallpaper.mFrame.top);
1700 wallpaper.mClient.dispatchPointer(ev, eventTime, false);
1701 } catch (RemoteException e) {
1702 Log.w(TAG, "Failure sending pointer to wallpaper", e);
1703 }
1704 }
1705 }
1706 }
1707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 public int addWindow(Session session, IWindow client,
1709 WindowManager.LayoutParams attrs, int viewVisibility,
1710 Rect outContentInsets) {
1711 int res = mPolicy.checkAddPermission(attrs);
1712 if (res != WindowManagerImpl.ADD_OKAY) {
1713 return res;
1714 }
Romain Guy06882f82009-06-10 13:36:04 -07001715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001716 boolean reportNewConfig = false;
1717 WindowState attachedWindow = null;
1718 WindowState win = null;
Romain Guy06882f82009-06-10 13:36:04 -07001719
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720 synchronized(mWindowMap) {
1721 // Instantiating a Display requires talking with the simulator,
1722 // so don't do it until we know the system is mostly up and
1723 // running.
1724 if (mDisplay == null) {
1725 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1726 mDisplay = wm.getDefaultDisplay();
1727 mQueue.setDisplay(mDisplay);
1728 reportNewConfig = true;
1729 }
Romain Guy06882f82009-06-10 13:36:04 -07001730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 if (mWindowMap.containsKey(client.asBinder())) {
1732 Log.w(TAG, "Window " + client + " is already added");
1733 return WindowManagerImpl.ADD_DUPLICATE_ADD;
1734 }
1735
1736 if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
Romain Guy06882f82009-06-10 13:36:04 -07001737 attachedWindow = windowForClientLocked(null, attrs.token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001738 if (attachedWindow == null) {
1739 Log.w(TAG, "Attempted to add window with token that is not a window: "
1740 + attrs.token + ". Aborting.");
1741 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1742 }
1743 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1744 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1745 Log.w(TAG, "Attempted to add window with token that is a sub-window: "
1746 + attrs.token + ". Aborting.");
1747 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1748 }
1749 }
1750
1751 boolean addToken = false;
1752 WindowToken token = mTokenMap.get(attrs.token);
1753 if (token == null) {
1754 if (attrs.type >= FIRST_APPLICATION_WINDOW
1755 && attrs.type <= LAST_APPLICATION_WINDOW) {
1756 Log.w(TAG, "Attempted to add application window with unknown token "
1757 + attrs.token + ". Aborting.");
1758 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1759 }
1760 if (attrs.type == TYPE_INPUT_METHOD) {
1761 Log.w(TAG, "Attempted to add input method window with unknown token "
1762 + attrs.token + ". Aborting.");
1763 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1764 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001765 if (attrs.type == TYPE_WALLPAPER) {
1766 Log.w(TAG, "Attempted to add wallpaper window with unknown token "
1767 + attrs.token + ". Aborting.");
1768 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1769 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 token = new WindowToken(attrs.token, -1, false);
1771 addToken = true;
1772 } else if (attrs.type >= FIRST_APPLICATION_WINDOW
1773 && attrs.type <= LAST_APPLICATION_WINDOW) {
1774 AppWindowToken atoken = token.appWindowToken;
1775 if (atoken == null) {
1776 Log.w(TAG, "Attempted to add window with non-application token "
1777 + token + ". Aborting.");
1778 return WindowManagerImpl.ADD_NOT_APP_TOKEN;
1779 } else if (atoken.removed) {
1780 Log.w(TAG, "Attempted to add window with exiting application token "
1781 + token + ". Aborting.");
1782 return WindowManagerImpl.ADD_APP_EXITING;
1783 }
1784 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1785 // No need for this guy!
1786 if (localLOGV) Log.v(
1787 TAG, "**** NO NEED TO START: " + attrs.getTitle());
1788 return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
1789 }
1790 } else if (attrs.type == TYPE_INPUT_METHOD) {
1791 if (token.windowType != TYPE_INPUT_METHOD) {
1792 Log.w(TAG, "Attempted to add input method window with bad token "
1793 + attrs.token + ". Aborting.");
1794 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1795 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001796 } else if (attrs.type == TYPE_WALLPAPER) {
1797 if (token.windowType != TYPE_WALLPAPER) {
1798 Log.w(TAG, "Attempted to add wallpaper window with bad token "
1799 + attrs.token + ". Aborting.");
1800 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1801 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 }
1803
1804 win = new WindowState(session, client, token,
1805 attachedWindow, attrs, viewVisibility);
1806 if (win.mDeathRecipient == null) {
1807 // Client has apparently died, so there is no reason to
1808 // continue.
1809 Log.w(TAG, "Adding window client " + client.asBinder()
1810 + " that is dead, aborting.");
1811 return WindowManagerImpl.ADD_APP_EXITING;
1812 }
1813
1814 mPolicy.adjustWindowParamsLw(win.mAttrs);
Romain Guy06882f82009-06-10 13:36:04 -07001815
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001816 res = mPolicy.prepareAddWindowLw(win, attrs);
1817 if (res != WindowManagerImpl.ADD_OKAY) {
1818 return res;
1819 }
1820
1821 // From now on, no exceptions or errors allowed!
1822
1823 res = WindowManagerImpl.ADD_OKAY;
Romain Guy06882f82009-06-10 13:36:04 -07001824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001825 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07001826
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001827 if (addToken) {
1828 mTokenMap.put(attrs.token, token);
1829 mTokenList.add(token);
1830 }
1831 win.attach();
1832 mWindowMap.put(client.asBinder(), win);
1833
1834 if (attrs.type == TYPE_APPLICATION_STARTING &&
1835 token.appWindowToken != null) {
1836 token.appWindowToken.startingWindow = win;
1837 }
1838
1839 boolean imMayMove = true;
Romain Guy06882f82009-06-10 13:36:04 -07001840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001841 if (attrs.type == TYPE_INPUT_METHOD) {
1842 mInputMethodWindow = win;
1843 addInputMethodWindowToListLocked(win);
1844 imMayMove = false;
1845 } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
1846 mInputMethodDialogs.add(win);
1847 addWindowToListInOrderLocked(win, true);
1848 adjustInputMethodDialogsLocked();
1849 imMayMove = false;
1850 } else {
1851 addWindowToListInOrderLocked(win, true);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001852 if (attrs.type == TYPE_WALLPAPER) {
1853 mLastWallpaperTimeoutTime = 0;
1854 adjustWallpaperWindowsLocked();
1855 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001856 adjustWallpaperWindowsLocked();
1857 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858 }
Romain Guy06882f82009-06-10 13:36:04 -07001859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 win.mEnterAnimationPending = true;
Romain Guy06882f82009-06-10 13:36:04 -07001861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
Romain Guy06882f82009-06-10 13:36:04 -07001863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001864 if (mInTouchMode) {
1865 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
1866 }
1867 if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
1868 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
1869 }
Romain Guy06882f82009-06-10 13:36:04 -07001870
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08001871 boolean focusChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 if (win.canReceiveKeys()) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08001873 if ((focusChanged=updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS))
1874 == true) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001875 imMayMove = false;
1876 }
1877 }
Romain Guy06882f82009-06-10 13:36:04 -07001878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 if (imMayMove) {
Romain Guy06882f82009-06-10 13:36:04 -07001880 moveInputMethodWindowsIfNeededLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 }
Romain Guy06882f82009-06-10 13:36:04 -07001882
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 assignLayersLocked();
1884 // Don't do layout here, the window must call
1885 // relayout to be displayed, so we'll do it there.
Romain Guy06882f82009-06-10 13:36:04 -07001886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 //dump();
1888
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08001889 if (focusChanged) {
1890 if (mCurrentFocus != null) {
1891 mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
1892 }
1893 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 if (localLOGV) Log.v(
1895 TAG, "New client " + client.asBinder()
1896 + ": window=" + win);
1897 }
1898
1899 // sendNewConfiguration() checks caller permissions so we must call it with
1900 // privilege. updateOrientationFromAppTokens() clears and resets the caller
1901 // identity anyway, so it's safe to just clear & restore around this whole
1902 // block.
1903 final long origId = Binder.clearCallingIdentity();
1904 if (reportNewConfig) {
1905 sendNewConfiguration();
1906 } else {
1907 // Update Orientation after adding a window, only if the window needs to be
1908 // displayed right away
1909 if (win.isVisibleOrAdding()) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07001910 if (updateOrientationFromAppTokensUnchecked(null, null) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911 sendNewConfiguration();
1912 }
1913 }
1914 }
1915 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07001916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 return res;
1918 }
Romain Guy06882f82009-06-10 13:36:04 -07001919
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001920 public void removeWindow(Session session, IWindow client) {
1921 synchronized(mWindowMap) {
1922 WindowState win = windowForClientLocked(session, client);
1923 if (win == null) {
1924 return;
1925 }
1926 removeWindowLocked(session, win);
1927 }
1928 }
Romain Guy06882f82009-06-10 13:36:04 -07001929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 public void removeWindowLocked(Session session, WindowState win) {
1931
1932 if (localLOGV || DEBUG_FOCUS) Log.v(
1933 TAG, "Remove " + win + " client="
1934 + Integer.toHexString(System.identityHashCode(
1935 win.mClient.asBinder()))
1936 + ", surface=" + win.mSurface);
1937
1938 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07001939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001940 if (DEBUG_APP_TRANSITIONS) Log.v(
1941 TAG, "Remove " + win + ": mSurface=" + win.mSurface
1942 + " mExiting=" + win.mExiting
1943 + " isAnimating=" + win.isAnimating()
1944 + " app-animation="
1945 + (win.mAppToken != null ? win.mAppToken.animation : null)
1946 + " inPendingTransaction="
1947 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
1948 + " mDisplayFrozen=" + mDisplayFrozen);
1949 // Visibility of the removed window. Will be used later to update orientation later on.
1950 boolean wasVisible = false;
1951 // First, see if we need to run an animation. If we do, we have
1952 // to hold off on removing the window until the animation is done.
1953 // If the display is frozen, just remove immediately, since the
1954 // animation wouldn't be seen.
1955 if (win.mSurface != null && !mDisplayFrozen) {
1956 // If we are not currently running the exit animation, we
1957 // need to see about starting one.
1958 if (wasVisible=win.isWinVisibleLw()) {
Romain Guy06882f82009-06-10 13:36:04 -07001959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001960 int transit = WindowManagerPolicy.TRANSIT_EXIT;
1961 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
1962 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
1963 }
1964 // Try starting an animation.
1965 if (applyAnimationLocked(win, transit, false)) {
1966 win.mExiting = true;
1967 }
1968 }
1969 if (win.mExiting || win.isAnimating()) {
1970 // The exit animation is running... wait for it!
1971 //Log.i(TAG, "*** Running exit animation...");
1972 win.mExiting = true;
1973 win.mRemoveOnExit = true;
1974 mLayoutNeeded = true;
1975 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
1976 performLayoutAndPlaceSurfacesLocked();
1977 if (win.mAppToken != null) {
1978 win.mAppToken.updateReportedVisibilityLocked();
1979 }
1980 //dump();
1981 Binder.restoreCallingIdentity(origId);
1982 return;
1983 }
1984 }
1985
1986 removeWindowInnerLocked(session, win);
1987 // Removing a visible window will effect the computed orientation
1988 // So just update orientation if needed.
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07001989 if (wasVisible && computeForcedAppOrientationLocked()
1990 != mForcedAppOrientation) {
1991 mH.sendMessage(mH.obtainMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001992 }
1993 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
1994 Binder.restoreCallingIdentity(origId);
1995 }
Romain Guy06882f82009-06-10 13:36:04 -07001996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 private void removeWindowInnerLocked(Session session, WindowState win) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001998 mKeyWaiter.finishedKey(session, win.mClient, true,
1999 KeyWaiter.RETURN_NOTHING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 mKeyWaiter.releasePendingPointerLocked(win.mSession);
2001 mKeyWaiter.releasePendingTrackballLocked(win.mSession);
Romain Guy06882f82009-06-10 13:36:04 -07002002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002003 win.mRemoved = true;
Romain Guy06882f82009-06-10 13:36:04 -07002004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002005 if (mInputMethodTarget == win) {
2006 moveInputMethodWindowsIfNeededLocked(false);
2007 }
Romain Guy06882f82009-06-10 13:36:04 -07002008
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002009 if (false) {
2010 RuntimeException e = new RuntimeException("here");
2011 e.fillInStackTrace();
2012 Log.w(TAG, "Removing window " + win, e);
2013 }
2014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 mPolicy.removeWindowLw(win);
2016 win.removeLocked();
2017
2018 mWindowMap.remove(win.mClient.asBinder());
2019 mWindows.remove(win);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07002020 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Final remove of window: " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021
2022 if (mInputMethodWindow == win) {
2023 mInputMethodWindow = null;
2024 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2025 mInputMethodDialogs.remove(win);
2026 }
Romain Guy06882f82009-06-10 13:36:04 -07002027
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028 final WindowToken token = win.mToken;
2029 final AppWindowToken atoken = win.mAppToken;
2030 token.windows.remove(win);
2031 if (atoken != null) {
2032 atoken.allAppWindows.remove(win);
2033 }
2034 if (localLOGV) Log.v(
2035 TAG, "**** Removing window " + win + ": count="
2036 + token.windows.size());
2037 if (token.windows.size() == 0) {
2038 if (!token.explicit) {
2039 mTokenMap.remove(token.token);
2040 mTokenList.remove(token);
2041 } else if (atoken != null) {
2042 atoken.firstWindowDrawn = false;
2043 }
2044 }
2045
2046 if (atoken != null) {
2047 if (atoken.startingWindow == win) {
2048 atoken.startingWindow = null;
2049 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2050 // If this is the last window and we had requested a starting
2051 // transition window, well there is no point now.
2052 atoken.startingData = null;
2053 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2054 // If this is the last window except for a starting transition
2055 // window, we need to get rid of the starting transition.
2056 if (DEBUG_STARTING_WINDOW) {
2057 Log.v(TAG, "Schedule remove starting " + token
2058 + ": no more real windows");
2059 }
2060 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
2061 mH.sendMessage(m);
2062 }
2063 }
Romain Guy06882f82009-06-10 13:36:04 -07002064
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002065 if (win.mAttrs.type == TYPE_WALLPAPER) {
2066 mLastWallpaperTimeoutTime = 0;
2067 adjustWallpaperWindowsLocked();
2068 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07002069 adjustWallpaperWindowsLocked();
2070 }
2071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 if (!mInLayout) {
2073 assignLayersLocked();
2074 mLayoutNeeded = true;
2075 performLayoutAndPlaceSurfacesLocked();
2076 if (win.mAppToken != null) {
2077 win.mAppToken.updateReportedVisibilityLocked();
2078 }
2079 }
2080 }
2081
2082 private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2083 long origId = Binder.clearCallingIdentity();
2084 try {
2085 synchronized (mWindowMap) {
2086 WindowState w = windowForClientLocked(session, client);
2087 if ((w != null) && (w.mSurface != null)) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002088 if (SHOW_TRANSACTIONS) Log.i(TAG, ">>> OPEN TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002089 Surface.openTransaction();
2090 try {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002091 if (SHOW_TRANSACTIONS) Log.i(
2092 TAG, " SURFACE " + w.mSurface
2093 + ": transparentRegionHint=" + region);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002094 w.mSurface.setTransparentRegionHint(region);
2095 } finally {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002096 if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002097 Surface.closeTransaction();
2098 }
2099 }
2100 }
2101 } finally {
2102 Binder.restoreCallingIdentity(origId);
2103 }
2104 }
2105
2106 void setInsetsWindow(Session session, IWindow client,
Romain Guy06882f82009-06-10 13:36:04 -07002107 int touchableInsets, Rect contentInsets,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002108 Rect visibleInsets) {
2109 long origId = Binder.clearCallingIdentity();
2110 try {
2111 synchronized (mWindowMap) {
2112 WindowState w = windowForClientLocked(session, client);
2113 if (w != null) {
2114 w.mGivenInsetsPending = false;
2115 w.mGivenContentInsets.set(contentInsets);
2116 w.mGivenVisibleInsets.set(visibleInsets);
2117 w.mTouchableInsets = touchableInsets;
2118 mLayoutNeeded = true;
2119 performLayoutAndPlaceSurfacesLocked();
2120 }
2121 }
2122 } finally {
2123 Binder.restoreCallingIdentity(origId);
2124 }
2125 }
Romain Guy06882f82009-06-10 13:36:04 -07002126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 public void getWindowDisplayFrame(Session session, IWindow client,
2128 Rect outDisplayFrame) {
2129 synchronized(mWindowMap) {
2130 WindowState win = windowForClientLocked(session, client);
2131 if (win == null) {
2132 outDisplayFrame.setEmpty();
2133 return;
2134 }
2135 outDisplayFrame.set(win.mDisplayFrame);
2136 }
2137 }
2138
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002139 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y) {
2140 if (window.mWallpaperX != x || window.mWallpaperY != y) {
2141 window.mWallpaperX = x;
2142 window.mWallpaperY = y;
2143
2144 if (mWallpaperTarget == window) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002145 if (updateWallpaperOffsetLocked(true)) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002146 performLayoutAndPlaceSurfacesLocked();
2147 }
2148 }
2149 }
2150 }
2151
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 public int relayoutWindow(Session session, IWindow client,
2153 WindowManager.LayoutParams attrs, int requestedWidth,
2154 int requestedHeight, int viewVisibility, boolean insetsPending,
2155 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
2156 Surface outSurface) {
2157 boolean displayed = false;
2158 boolean inTouchMode;
2159 Configuration newConfig = null;
2160 long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 synchronized(mWindowMap) {
2163 WindowState win = windowForClientLocked(session, client);
2164 if (win == null) {
2165 return 0;
2166 }
2167 win.mRequestedWidth = requestedWidth;
2168 win.mRequestedHeight = requestedHeight;
2169
2170 if (attrs != null) {
2171 mPolicy.adjustWindowParamsLw(attrs);
2172 }
Romain Guy06882f82009-06-10 13:36:04 -07002173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 int attrChanges = 0;
2175 int flagChanges = 0;
2176 if (attrs != null) {
2177 flagChanges = win.mAttrs.flags ^= attrs.flags;
2178 attrChanges = win.mAttrs.copyFrom(attrs);
2179 }
2180
2181 if (localLOGV) Log.v(
2182 TAG, "Relayout given client " + client.asBinder()
2183 + " (" + win.mAttrs.getTitle() + ")");
2184
2185
2186 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2187 win.mAlpha = attrs.alpha;
2188 }
2189
2190 final boolean scaledWindow =
2191 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2192
2193 if (scaledWindow) {
2194 // requested{Width|Height} Surface's physical size
2195 // attrs.{width|height} Size on screen
2196 win.mHScale = (attrs.width != requestedWidth) ?
2197 (attrs.width / (float)requestedWidth) : 1.0f;
2198 win.mVScale = (attrs.height != requestedHeight) ?
2199 (attrs.height / (float)requestedHeight) : 1.0f;
2200 }
2201
2202 boolean imMayMove = (flagChanges&(
2203 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
2204 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07002205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002206 boolean focusMayChange = win.mViewVisibility != viewVisibility
2207 || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
2208 || (!win.mRelayoutCalled);
Romain Guy06882f82009-06-10 13:36:04 -07002209
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002210 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2211 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002213 win.mRelayoutCalled = true;
2214 final int oldVisibility = win.mViewVisibility;
2215 win.mViewVisibility = viewVisibility;
2216 if (viewVisibility == View.VISIBLE &&
2217 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2218 displayed = !win.isVisibleLw();
2219 if (win.mExiting) {
2220 win.mExiting = false;
2221 win.mAnimation = null;
2222 }
2223 if (win.mDestroying) {
2224 win.mDestroying = false;
2225 mDestroySurface.remove(win);
2226 }
2227 if (oldVisibility == View.GONE) {
2228 win.mEnterAnimationPending = true;
2229 }
2230 if (displayed && win.mSurface != null && !win.mDrawPending
2231 && !win.mCommitDrawPending && !mDisplayFrozen) {
2232 applyEnterAnimationLocked(win);
2233 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07002234 if (displayed && (win.mAttrs.flags
2235 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2236 win.mTurnOnScreen = true;
2237 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002238 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2239 // To change the format, we need to re-build the surface.
2240 win.destroySurfaceLocked();
2241 displayed = true;
2242 }
2243 try {
2244 Surface surface = win.createSurfaceLocked();
2245 if (surface != null) {
2246 outSurface.copyFrom(surface);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002247 if (SHOW_TRANSACTIONS) Log.i(TAG,
2248 " OUT SURFACE " + outSurface + ": copied");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 } else {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002250 // For some reason there isn't a surface. Clear the
2251 // caller's object so they see the same state.
2252 outSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 }
2254 } catch (Exception e) {
2255 Log.w(TAG, "Exception thrown when creating surface for client "
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002256 + client + " (" + win.mAttrs.getTitle() + ")",
2257 e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002258 Binder.restoreCallingIdentity(origId);
2259 return 0;
2260 }
2261 if (displayed) {
2262 focusMayChange = true;
2263 }
2264 if (win.mAttrs.type == TYPE_INPUT_METHOD
2265 && mInputMethodWindow == null) {
2266 mInputMethodWindow = win;
2267 imMayMove = true;
2268 }
2269 } else {
2270 win.mEnterAnimationPending = false;
2271 if (win.mSurface != null) {
2272 // If we are not currently running the exit animation, we
2273 // need to see about starting one.
2274 if (!win.mExiting) {
2275 // Try starting an animation; if there isn't one, we
2276 // can destroy the surface right away.
2277 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2278 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2279 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2280 }
2281 if (win.isWinVisibleLw() &&
2282 applyAnimationLocked(win, transit, false)) {
2283 win.mExiting = true;
2284 mKeyWaiter.finishedKey(session, client, true,
2285 KeyWaiter.RETURN_NOTHING);
2286 } else if (win.isAnimating()) {
2287 // Currently in a hide animation... turn this into
2288 // an exit.
2289 win.mExiting = true;
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07002290 } else if (win == mWallpaperTarget) {
2291 // If the wallpaper is currently behind this
2292 // window, we need to change both of them inside
2293 // of a transaction to avoid artifacts.
2294 win.mExiting = true;
2295 win.mAnimating = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002296 } else {
2297 if (mInputMethodWindow == win) {
2298 mInputMethodWindow = null;
2299 }
2300 win.destroySurfaceLocked();
2301 }
2302 }
2303 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002304 // We are being called from a local process, which
2305 // means outSurface holds its current surface. Ensure the
2306 // surface object is cleared, but we don't want it actually
2307 // destroyed at this point.
2308 outSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 }
2310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002311 if (focusMayChange) {
2312 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2313 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002314 imMayMove = false;
2315 }
2316 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2317 }
Romain Guy06882f82009-06-10 13:36:04 -07002318
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002319 // updateFocusedWindowLocked() already assigned layers so we only need to
2320 // reassign them at this point if the IM window state gets shuffled
2321 boolean assignLayers = false;
Romain Guy06882f82009-06-10 13:36:04 -07002322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 if (imMayMove) {
2324 if (moveInputMethodWindowsIfNeededLocked(false)) {
2325 assignLayers = true;
2326 }
2327 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002328 if (wallpaperMayMove) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002329 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002330 assignLayers = true;
2331 }
2332 }
Romain Guy06882f82009-06-10 13:36:04 -07002333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002334 mLayoutNeeded = true;
2335 win.mGivenInsetsPending = insetsPending;
2336 if (assignLayers) {
2337 assignLayersLocked();
2338 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002339 newConfig = updateOrientationFromAppTokensLocked(null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002340 performLayoutAndPlaceSurfacesLocked();
Dianne Hackborn284ac932009-08-28 10:34:25 -07002341 if (displayed && win.mIsWallpaper) {
2342 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002343 mDisplay.getHeight(), false);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002344 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002345 if (win.mAppToken != null) {
2346 win.mAppToken.updateReportedVisibilityLocked();
2347 }
2348 outFrame.set(win.mFrame);
2349 outContentInsets.set(win.mContentInsets);
2350 outVisibleInsets.set(win.mVisibleInsets);
2351 if (localLOGV) Log.v(
2352 TAG, "Relayout given client " + client.asBinder()
Romain Guy06882f82009-06-10 13:36:04 -07002353 + ", requestedWidth=" + requestedWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002354 + ", requestedHeight=" + requestedHeight
2355 + ", viewVisibility=" + viewVisibility
2356 + "\nRelayout returning frame=" + outFrame
2357 + ", surface=" + outSurface);
2358
2359 if (localLOGV || DEBUG_FOCUS) Log.v(
2360 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2361
2362 inTouchMode = mInTouchMode;
2363 }
2364
2365 if (newConfig != null) {
2366 sendNewConfiguration();
2367 }
Romain Guy06882f82009-06-10 13:36:04 -07002368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002369 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07002370
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
2372 | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
2373 }
2374
2375 public void finishDrawingWindow(Session session, IWindow client) {
2376 final long origId = Binder.clearCallingIdentity();
2377 synchronized(mWindowMap) {
2378 WindowState win = windowForClientLocked(session, client);
2379 if (win != null && win.finishDrawingLocked()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07002380 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2381 adjustWallpaperWindowsLocked();
2382 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383 mLayoutNeeded = true;
2384 performLayoutAndPlaceSurfacesLocked();
2385 }
2386 }
2387 Binder.restoreCallingIdentity(origId);
2388 }
2389
2390 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
2391 if (DEBUG_ANIM) Log.v(TAG, "Loading animations: params package="
2392 + (lp != null ? lp.packageName : null)
2393 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
2394 if (lp != null && lp.windowAnimations != 0) {
2395 // If this is a system resource, don't try to load it from the
2396 // application resources. It is nice to avoid loading application
2397 // resources if we can.
2398 String packageName = lp.packageName != null ? lp.packageName : "android";
2399 int resId = lp.windowAnimations;
2400 if ((resId&0xFF000000) == 0x01000000) {
2401 packageName = "android";
2402 }
2403 if (DEBUG_ANIM) Log.v(TAG, "Loading animations: picked package="
2404 + packageName);
2405 return AttributeCache.instance().get(packageName, resId,
2406 com.android.internal.R.styleable.WindowAnimation);
2407 }
2408 return null;
2409 }
Romain Guy06882f82009-06-10 13:36:04 -07002410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002411 private void applyEnterAnimationLocked(WindowState win) {
2412 int transit = WindowManagerPolicy.TRANSIT_SHOW;
2413 if (win.mEnterAnimationPending) {
2414 win.mEnterAnimationPending = false;
2415 transit = WindowManagerPolicy.TRANSIT_ENTER;
2416 }
2417
2418 applyAnimationLocked(win, transit, true);
2419 }
2420
2421 private boolean applyAnimationLocked(WindowState win,
2422 int transit, boolean isEntrance) {
2423 if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
2424 // If we are trying to apply an animation, but already running
2425 // an animation of the same type, then just leave that one alone.
2426 return true;
2427 }
Romain Guy06882f82009-06-10 13:36:04 -07002428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002429 // Only apply an animation if the display isn't frozen. If it is
2430 // frozen, there is no reason to animate and it can cause strange
2431 // artifacts when we unfreeze the display if some different animation
2432 // is running.
2433 if (!mDisplayFrozen) {
2434 int anim = mPolicy.selectAnimationLw(win, transit);
2435 int attr = -1;
2436 Animation a = null;
2437 if (anim != 0) {
2438 a = AnimationUtils.loadAnimation(mContext, anim);
2439 } else {
2440 switch (transit) {
2441 case WindowManagerPolicy.TRANSIT_ENTER:
2442 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
2443 break;
2444 case WindowManagerPolicy.TRANSIT_EXIT:
2445 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
2446 break;
2447 case WindowManagerPolicy.TRANSIT_SHOW:
2448 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
2449 break;
2450 case WindowManagerPolicy.TRANSIT_HIDE:
2451 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
2452 break;
2453 }
2454 if (attr >= 0) {
2455 a = loadAnimation(win.mAttrs, attr);
2456 }
2457 }
2458 if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: win=" + win
2459 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
2460 + " mAnimation=" + win.mAnimation
2461 + " isEntrance=" + isEntrance);
2462 if (a != null) {
2463 if (DEBUG_ANIM) {
2464 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07002465 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002466 Log.v(TAG, "Loaded animation " + a + " for " + win, e);
2467 }
2468 win.setAnimation(a);
2469 win.mAnimationIsEntrance = isEntrance;
2470 }
2471 } else {
2472 win.clearAnimation();
2473 }
2474
2475 return win.mAnimation != null;
2476 }
2477
2478 private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
2479 int anim = 0;
2480 Context context = mContext;
2481 if (animAttr >= 0) {
2482 AttributeCache.Entry ent = getCachedAnimations(lp);
2483 if (ent != null) {
2484 context = ent.context;
2485 anim = ent.array.getResourceId(animAttr, 0);
2486 }
2487 }
2488 if (anim != 0) {
2489 return AnimationUtils.loadAnimation(context, anim);
2490 }
2491 return null;
2492 }
Romain Guy06882f82009-06-10 13:36:04 -07002493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002494 private boolean applyAnimationLocked(AppWindowToken wtoken,
2495 WindowManager.LayoutParams lp, int transit, boolean enter) {
2496 // Only apply an animation if the display isn't frozen. If it is
2497 // frozen, there is no reason to animate and it can cause strange
2498 // artifacts when we unfreeze the display if some different animation
2499 // is running.
2500 if (!mDisplayFrozen) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002501 Animation a;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07002502 if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002503 a = new FadeInOutAnimation(enter);
2504 if (DEBUG_ANIM) Log.v(TAG,
2505 "applying FadeInOutAnimation for a window in compatibility mode");
2506 } else {
2507 int animAttr = 0;
2508 switch (transit) {
2509 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
2510 animAttr = enter
2511 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
2512 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
2513 break;
2514 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
2515 animAttr = enter
2516 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
2517 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
2518 break;
2519 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
2520 animAttr = enter
2521 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
2522 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
2523 break;
2524 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
2525 animAttr = enter
2526 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
2527 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
2528 break;
2529 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
2530 animAttr = enter
2531 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
2532 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
2533 break;
2534 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
2535 animAttr = enter
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07002536 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002537 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
2538 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002539 case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002540 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002541 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation
2542 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002543 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002544 case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002545 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002546 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation
2547 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
2548 break;
2549 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN:
2550 animAttr = enter
2551 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation
2552 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
2553 break;
2554 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE:
2555 animAttr = enter
2556 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation
2557 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002558 break;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002559 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002560 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002561 if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: wtoken=" + wtoken
2562 + " anim=" + a
2563 + " animAttr=0x" + Integer.toHexString(animAttr)
2564 + " transit=" + transit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002565 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002566 if (a != null) {
2567 if (DEBUG_ANIM) {
2568 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07002569 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 Log.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
2571 }
2572 wtoken.setAnimation(a);
2573 }
2574 } else {
2575 wtoken.clearAnimation();
2576 }
2577
2578 return wtoken.animation != null;
2579 }
2580
2581 // -------------------------------------------------------------
2582 // Application Window Tokens
2583 // -------------------------------------------------------------
2584
2585 public void validateAppTokens(List tokens) {
2586 int v = tokens.size()-1;
2587 int m = mAppTokens.size()-1;
2588 while (v >= 0 && m >= 0) {
2589 AppWindowToken wtoken = mAppTokens.get(m);
2590 if (wtoken.removed) {
2591 m--;
2592 continue;
2593 }
2594 if (tokens.get(v) != wtoken.token) {
2595 Log.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
2596 + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
2597 }
2598 v--;
2599 m--;
2600 }
2601 while (v >= 0) {
2602 Log.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
2603 v--;
2604 }
2605 while (m >= 0) {
2606 AppWindowToken wtoken = mAppTokens.get(m);
2607 if (!wtoken.removed) {
2608 Log.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
2609 }
2610 m--;
2611 }
2612 }
2613
2614 boolean checkCallingPermission(String permission, String func) {
2615 // Quick check: if the calling permission is me, it's all okay.
2616 if (Binder.getCallingPid() == Process.myPid()) {
2617 return true;
2618 }
Romain Guy06882f82009-06-10 13:36:04 -07002619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002620 if (mContext.checkCallingPermission(permission)
2621 == PackageManager.PERMISSION_GRANTED) {
2622 return true;
2623 }
2624 String msg = "Permission Denial: " + func + " from pid="
2625 + Binder.getCallingPid()
2626 + ", uid=" + Binder.getCallingUid()
2627 + " requires " + permission;
2628 Log.w(TAG, msg);
2629 return false;
2630 }
Romain Guy06882f82009-06-10 13:36:04 -07002631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 AppWindowToken findAppWindowToken(IBinder token) {
2633 WindowToken wtoken = mTokenMap.get(token);
2634 if (wtoken == null) {
2635 return null;
2636 }
2637 return wtoken.appWindowToken;
2638 }
Romain Guy06882f82009-06-10 13:36:04 -07002639
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002640 public void addWindowToken(IBinder token, int type) {
2641 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2642 "addWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002643 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 }
Romain Guy06882f82009-06-10 13:36:04 -07002645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002646 synchronized(mWindowMap) {
2647 WindowToken wtoken = mTokenMap.get(token);
2648 if (wtoken != null) {
2649 Log.w(TAG, "Attempted to add existing input method token: " + token);
2650 return;
2651 }
2652 wtoken = new WindowToken(token, type, true);
2653 mTokenMap.put(token, wtoken);
2654 mTokenList.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002655 if (type == TYPE_WALLPAPER) {
2656 mWallpaperTokens.add(wtoken);
2657 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002658 }
2659 }
Romain Guy06882f82009-06-10 13:36:04 -07002660
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002661 public void removeWindowToken(IBinder token) {
2662 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2663 "removeWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002664 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002665 }
2666
2667 final long origId = Binder.clearCallingIdentity();
2668 synchronized(mWindowMap) {
2669 WindowToken wtoken = mTokenMap.remove(token);
2670 mTokenList.remove(wtoken);
2671 if (wtoken != null) {
2672 boolean delayed = false;
2673 if (!wtoken.hidden) {
2674 wtoken.hidden = true;
Romain Guy06882f82009-06-10 13:36:04 -07002675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002676 final int N = wtoken.windows.size();
2677 boolean changed = false;
Romain Guy06882f82009-06-10 13:36:04 -07002678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 for (int i=0; i<N; i++) {
2680 WindowState win = wtoken.windows.get(i);
2681
2682 if (win.isAnimating()) {
2683 delayed = true;
2684 }
Romain Guy06882f82009-06-10 13:36:04 -07002685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002686 if (win.isVisibleNow()) {
2687 applyAnimationLocked(win,
2688 WindowManagerPolicy.TRANSIT_EXIT, false);
2689 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
2690 KeyWaiter.RETURN_NOTHING);
2691 changed = true;
2692 }
2693 }
2694
2695 if (changed) {
2696 mLayoutNeeded = true;
2697 performLayoutAndPlaceSurfacesLocked();
2698 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2699 }
Romain Guy06882f82009-06-10 13:36:04 -07002700
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 if (delayed) {
2702 mExitingTokens.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002703 } else if (wtoken.windowType == TYPE_WALLPAPER) {
2704 mWallpaperTokens.remove(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 }
2706 }
Romain Guy06882f82009-06-10 13:36:04 -07002707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002708 } else {
2709 Log.w(TAG, "Attempted to remove non-existing token: " + token);
2710 }
2711 }
2712 Binder.restoreCallingIdentity(origId);
2713 }
2714
2715 public void addAppToken(int addPos, IApplicationToken token,
2716 int groupId, int requestedOrientation, boolean fullscreen) {
2717 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2718 "addAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002719 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720 }
Romain Guy06882f82009-06-10 13:36:04 -07002721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002722 synchronized(mWindowMap) {
2723 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
2724 if (wtoken != null) {
2725 Log.w(TAG, "Attempted to add existing app token: " + token);
2726 return;
2727 }
2728 wtoken = new AppWindowToken(token);
2729 wtoken.groupId = groupId;
2730 wtoken.appFullscreen = fullscreen;
2731 wtoken.requestedOrientation = requestedOrientation;
2732 mAppTokens.add(addPos, wtoken);
Dave Bortcfe65242009-04-09 14:51:04 -07002733 if (localLOGV) Log.v(TAG, "Adding new app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 mTokenMap.put(token.asBinder(), wtoken);
2735 mTokenList.add(wtoken);
Romain Guy06882f82009-06-10 13:36:04 -07002736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 // Application tokens start out hidden.
2738 wtoken.hidden = true;
2739 wtoken.hiddenRequested = true;
Romain Guy06882f82009-06-10 13:36:04 -07002740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 //dump();
2742 }
2743 }
Romain Guy06882f82009-06-10 13:36:04 -07002744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002745 public void setAppGroupId(IBinder token, int groupId) {
2746 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2747 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002748 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 }
2750
2751 synchronized(mWindowMap) {
2752 AppWindowToken wtoken = findAppWindowToken(token);
2753 if (wtoken == null) {
2754 Log.w(TAG, "Attempted to set group id of non-existing app token: " + token);
2755 return;
2756 }
2757 wtoken.groupId = groupId;
2758 }
2759 }
Romain Guy06882f82009-06-10 13:36:04 -07002760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002761 public int getOrientationFromWindowsLocked() {
2762 int pos = mWindows.size() - 1;
2763 while (pos >= 0) {
2764 WindowState wtoken = (WindowState) mWindows.get(pos);
2765 pos--;
2766 if (wtoken.mAppToken != null) {
2767 // We hit an application window. so the orientation will be determined by the
2768 // app window. No point in continuing further.
2769 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2770 }
2771 if (!wtoken.isVisibleLw()) {
2772 continue;
2773 }
2774 int req = wtoken.mAttrs.screenOrientation;
2775 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
2776 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
2777 continue;
2778 } else {
2779 return req;
2780 }
2781 }
2782 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2783 }
Romain Guy06882f82009-06-10 13:36:04 -07002784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002785 public int getOrientationFromAppTokensLocked() {
2786 int pos = mAppTokens.size() - 1;
2787 int curGroup = 0;
2788 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Owen Lin3413b892009-05-01 17:12:32 -07002789 boolean findingBehind = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002790 boolean haveGroup = false;
The Android Open Source Project4df24232009-03-05 14:34:35 -08002791 boolean lastFullscreen = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002792 while (pos >= 0) {
2793 AppWindowToken wtoken = mAppTokens.get(pos);
2794 pos--;
Owen Lin3413b892009-05-01 17:12:32 -07002795 // if we're about to tear down this window and not seek for
2796 // the behind activity, don't use it for orientation
2797 if (!findingBehind
2798 && (!wtoken.hidden && wtoken.hiddenRequested)) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002799 continue;
2800 }
2801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002802 if (!haveGroup) {
2803 // We ignore any hidden applications on the top.
2804 if (wtoken.hiddenRequested || wtoken.willBeHidden) {
2805 continue;
2806 }
2807 haveGroup = true;
2808 curGroup = wtoken.groupId;
2809 lastOrientation = wtoken.requestedOrientation;
2810 } else if (curGroup != wtoken.groupId) {
2811 // If we have hit a new application group, and the bottom
2812 // of the previous group didn't explicitly say to use
The Android Open Source Project4df24232009-03-05 14:34:35 -08002813 // the orientation behind it, and the last app was
2814 // full screen, then we'll stick with the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002815 // user's orientation.
The Android Open Source Project4df24232009-03-05 14:34:35 -08002816 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
2817 && lastFullscreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002818 return lastOrientation;
2819 }
2820 }
2821 int or = wtoken.requestedOrientation;
Owen Lin3413b892009-05-01 17:12:32 -07002822 // If this application is fullscreen, and didn't explicitly say
2823 // to use the orientation behind it, then just take whatever
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002824 // orientation it has and ignores whatever is under it.
The Android Open Source Project4df24232009-03-05 14:34:35 -08002825 lastFullscreen = wtoken.appFullscreen;
Romain Guy06882f82009-06-10 13:36:04 -07002826 if (lastFullscreen
Owen Lin3413b892009-05-01 17:12:32 -07002827 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828 return or;
2829 }
2830 // If this application has requested an explicit orientation,
2831 // then use it.
2832 if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
2833 or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
2834 or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
2835 or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
2836 or == ActivityInfo.SCREEN_ORIENTATION_USER) {
2837 return or;
2838 }
Owen Lin3413b892009-05-01 17:12:32 -07002839 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002840 }
2841 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2842 }
Romain Guy06882f82009-06-10 13:36:04 -07002843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002844 public Configuration updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002845 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002846 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2847 "updateOrientationFromAppTokens()")) {
2848 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2849 }
2850
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002851 Configuration config;
2852 long ident = Binder.clearCallingIdentity();
Dianne Hackborncfaef692009-06-15 14:24:44 -07002853 config = updateOrientationFromAppTokensUnchecked(currentConfig,
2854 freezeThisOneIfNeeded);
2855 Binder.restoreCallingIdentity(ident);
2856 return config;
2857 }
2858
2859 Configuration updateOrientationFromAppTokensUnchecked(
2860 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
2861 Configuration config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002862 synchronized(mWindowMap) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002863 config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded);
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002864 if (config != null) {
2865 mLayoutNeeded = true;
2866 performLayoutAndPlaceSurfacesLocked();
2867 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002868 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 return config;
2870 }
Romain Guy06882f82009-06-10 13:36:04 -07002871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872 /*
2873 * The orientation is computed from non-application windows first. If none of
2874 * the non-application windows specify orientation, the orientation is computed from
Romain Guy06882f82009-06-10 13:36:04 -07002875 * application tokens.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002876 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
2877 * android.os.IBinder)
2878 */
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002879 Configuration updateOrientationFromAppTokensLocked(
The Android Open Source Project10592532009-03-18 17:39:46 -07002880 Configuration appConfig, IBinder freezeThisOneIfNeeded) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002881 boolean changed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002882 long ident = Binder.clearCallingIdentity();
2883 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002884 int req = computeForcedAppOrientationLocked();
Romain Guy06882f82009-06-10 13:36:04 -07002885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 if (req != mForcedAppOrientation) {
2887 changed = true;
2888 mForcedAppOrientation = req;
2889 //send a message to Policy indicating orientation change to take
2890 //action like disabling/enabling sensors etc.,
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002891 mPolicy.setCurrentOrientationLw(req);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 }
Romain Guy06882f82009-06-10 13:36:04 -07002893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002894 if (changed) {
2895 changed = setRotationUncheckedLocked(
Dianne Hackborn321ae682009-03-27 16:16:03 -07002896 WindowManagerPolicy.USE_LAST_ROTATION,
2897 mLastRotationFlags & (~Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002898 if (changed) {
2899 if (freezeThisOneIfNeeded != null) {
2900 AppWindowToken wtoken = findAppWindowToken(
2901 freezeThisOneIfNeeded);
2902 if (wtoken != null) {
2903 startAppFreezingScreenLocked(wtoken,
2904 ActivityInfo.CONFIG_ORIENTATION);
2905 }
2906 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07002907 return computeNewConfigurationLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 }
2909 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002910
2911 // No obvious action we need to take, but if our current
2912 // state mismatches the activity maanager's, update it
2913 if (appConfig != null) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07002914 mTempConfiguration.setToDefaults();
2915 if (computeNewConfigurationLocked(mTempConfiguration)) {
2916 if (appConfig.diff(mTempConfiguration) != 0) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07002917 return new Configuration(mTempConfiguration);
2918 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002919 }
2920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921 } finally {
2922 Binder.restoreCallingIdentity(ident);
2923 }
Romain Guy06882f82009-06-10 13:36:04 -07002924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 return null;
2926 }
Romain Guy06882f82009-06-10 13:36:04 -07002927
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002928 int computeForcedAppOrientationLocked() {
2929 int req = getOrientationFromWindowsLocked();
2930 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
2931 req = getOrientationFromAppTokensLocked();
2932 }
2933 return req;
2934 }
Romain Guy06882f82009-06-10 13:36:04 -07002935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
2937 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2938 "setAppOrientation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002939 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002940 }
Romain Guy06882f82009-06-10 13:36:04 -07002941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 synchronized(mWindowMap) {
2943 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
2944 if (wtoken == null) {
2945 Log.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
2946 return;
2947 }
Romain Guy06882f82009-06-10 13:36:04 -07002948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 wtoken.requestedOrientation = requestedOrientation;
2950 }
2951 }
Romain Guy06882f82009-06-10 13:36:04 -07002952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 public int getAppOrientation(IApplicationToken token) {
2954 synchronized(mWindowMap) {
2955 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
2956 if (wtoken == null) {
2957 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2958 }
Romain Guy06882f82009-06-10 13:36:04 -07002959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002960 return wtoken.requestedOrientation;
2961 }
2962 }
Romain Guy06882f82009-06-10 13:36:04 -07002963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002964 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
2965 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2966 "setFocusedApp()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002967 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 }
2969
2970 synchronized(mWindowMap) {
2971 boolean changed = false;
2972 if (token == null) {
2973 if (DEBUG_FOCUS) Log.v(TAG, "Clearing focused app, was " + mFocusedApp);
2974 changed = mFocusedApp != null;
2975 mFocusedApp = null;
2976 mKeyWaiter.tickle();
2977 } else {
2978 AppWindowToken newFocus = findAppWindowToken(token);
2979 if (newFocus == null) {
2980 Log.w(TAG, "Attempted to set focus to non-existing app token: " + token);
2981 return;
2982 }
2983 changed = mFocusedApp != newFocus;
2984 mFocusedApp = newFocus;
2985 if (DEBUG_FOCUS) Log.v(TAG, "Set focused app to: " + mFocusedApp);
2986 mKeyWaiter.tickle();
2987 }
2988
2989 if (moveFocusNow && changed) {
2990 final long origId = Binder.clearCallingIdentity();
2991 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2992 Binder.restoreCallingIdentity(origId);
2993 }
2994 }
2995 }
2996
2997 public void prepareAppTransition(int transit) {
2998 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2999 "prepareAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003000 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 }
Romain Guy06882f82009-06-10 13:36:04 -07003002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 synchronized(mWindowMap) {
3004 if (DEBUG_APP_TRANSITIONS) Log.v(
3005 TAG, "Prepare app transition: transit=" + transit
3006 + " mNextAppTransition=" + mNextAppTransition);
3007 if (!mDisplayFrozen) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003008 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
3009 || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003010 mNextAppTransition = transit;
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07003011 } else if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
3012 && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) {
3013 // Opening a new task always supersedes a close for the anim.
3014 mNextAppTransition = transit;
3015 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
3016 && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) {
3017 // Opening a new activity always supersedes a close for the anim.
3018 mNextAppTransition = transit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 }
3020 mAppTransitionReady = false;
3021 mAppTransitionTimeout = false;
3022 mStartingIconInTransition = false;
3023 mSkipAppTransitionAnimation = false;
3024 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3025 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT),
3026 5000);
3027 }
3028 }
3029 }
3030
3031 public int getPendingAppTransition() {
3032 return mNextAppTransition;
3033 }
Romain Guy06882f82009-06-10 13:36:04 -07003034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003035 public void executeAppTransition() {
3036 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3037 "executeAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003038 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003039 }
Romain Guy06882f82009-06-10 13:36:04 -07003040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 synchronized(mWindowMap) {
3042 if (DEBUG_APP_TRANSITIONS) Log.v(
3043 TAG, "Execute app transition: mNextAppTransition=" + mNextAppTransition);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003044 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 mAppTransitionReady = true;
3046 final long origId = Binder.clearCallingIdentity();
3047 performLayoutAndPlaceSurfacesLocked();
3048 Binder.restoreCallingIdentity(origId);
3049 }
3050 }
3051 }
3052
3053 public void setAppStartingWindow(IBinder token, String pkg,
3054 int theme, CharSequence nonLocalizedLabel, int labelRes, int icon,
3055 IBinder transferFrom, boolean createIfNeeded) {
3056 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3057 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003058 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003059 }
3060
3061 synchronized(mWindowMap) {
3062 if (DEBUG_STARTING_WINDOW) Log.v(
3063 TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
3064 + " transferFrom=" + transferFrom);
Romain Guy06882f82009-06-10 13:36:04 -07003065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 AppWindowToken wtoken = findAppWindowToken(token);
3067 if (wtoken == null) {
3068 Log.w(TAG, "Attempted to set icon of non-existing app token: " + token);
3069 return;
3070 }
3071
3072 // If the display is frozen, we won't do anything until the
3073 // actual window is displayed so there is no reason to put in
3074 // the starting window.
3075 if (mDisplayFrozen) {
3076 return;
3077 }
Romain Guy06882f82009-06-10 13:36:04 -07003078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003079 if (wtoken.startingData != null) {
3080 return;
3081 }
Romain Guy06882f82009-06-10 13:36:04 -07003082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 if (transferFrom != null) {
3084 AppWindowToken ttoken = findAppWindowToken(transferFrom);
3085 if (ttoken != null) {
3086 WindowState startingWindow = ttoken.startingWindow;
3087 if (startingWindow != null) {
3088 if (mStartingIconInTransition) {
3089 // In this case, the starting icon has already
3090 // been displayed, so start letting windows get
3091 // shown immediately without any more transitions.
3092 mSkipAppTransitionAnimation = true;
3093 }
3094 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
3095 "Moving existing starting from " + ttoken
3096 + " to " + wtoken);
3097 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07003098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003099 // Transfer the starting window over to the new
3100 // token.
3101 wtoken.startingData = ttoken.startingData;
3102 wtoken.startingView = ttoken.startingView;
3103 wtoken.startingWindow = startingWindow;
3104 ttoken.startingData = null;
3105 ttoken.startingView = null;
3106 ttoken.startingWindow = null;
3107 ttoken.startingMoved = true;
3108 startingWindow.mToken = wtoken;
Dianne Hackbornef49c572009-03-24 19:27:32 -07003109 startingWindow.mRootToken = wtoken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003110 startingWindow.mAppToken = wtoken;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003111 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
3112 "Removing starting window: " + startingWindow);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 mWindows.remove(startingWindow);
3114 ttoken.windows.remove(startingWindow);
3115 ttoken.allAppWindows.remove(startingWindow);
3116 addWindowToListInOrderLocked(startingWindow, true);
3117 wtoken.allAppWindows.add(startingWindow);
Romain Guy06882f82009-06-10 13:36:04 -07003118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003119 // Propagate other interesting state between the
3120 // tokens. If the old token is displayed, we should
3121 // immediately force the new one to be displayed. If
3122 // it is animating, we need to move that animation to
3123 // the new one.
3124 if (ttoken.allDrawn) {
3125 wtoken.allDrawn = true;
3126 }
3127 if (ttoken.firstWindowDrawn) {
3128 wtoken.firstWindowDrawn = true;
3129 }
3130 if (!ttoken.hidden) {
3131 wtoken.hidden = false;
3132 wtoken.hiddenRequested = false;
3133 wtoken.willBeHidden = false;
3134 }
3135 if (wtoken.clientHidden != ttoken.clientHidden) {
3136 wtoken.clientHidden = ttoken.clientHidden;
3137 wtoken.sendAppVisibilityToClients();
3138 }
3139 if (ttoken.animation != null) {
3140 wtoken.animation = ttoken.animation;
3141 wtoken.animating = ttoken.animating;
3142 wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
3143 ttoken.animation = null;
3144 ttoken.animLayerAdjustment = 0;
3145 wtoken.updateLayers();
3146 ttoken.updateLayers();
3147 }
Romain Guy06882f82009-06-10 13:36:04 -07003148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150 mLayoutNeeded = true;
3151 performLayoutAndPlaceSurfacesLocked();
3152 Binder.restoreCallingIdentity(origId);
3153 return;
3154 } else if (ttoken.startingData != null) {
3155 // The previous app was getting ready to show a
3156 // starting window, but hasn't yet done so. Steal it!
3157 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
3158 "Moving pending starting from " + ttoken
3159 + " to " + wtoken);
3160 wtoken.startingData = ttoken.startingData;
3161 ttoken.startingData = null;
3162 ttoken.startingMoved = true;
3163 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3164 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3165 // want to process the message ASAP, before any other queued
3166 // messages.
3167 mH.sendMessageAtFrontOfQueue(m);
3168 return;
3169 }
3170 }
3171 }
3172
3173 // There is no existing starting window, and the caller doesn't
3174 // want us to create one, so that's it!
3175 if (!createIfNeeded) {
3176 return;
3177 }
Romain Guy06882f82009-06-10 13:36:04 -07003178
Dianne Hackborn284ac932009-08-28 10:34:25 -07003179 // If this is a translucent or wallpaper window, then don't
3180 // show a starting window -- the current effect (a full-screen
3181 // opaque starting window that fades away to the real contents
3182 // when it is ready) does not work for this.
3183 if (theme != 0) {
3184 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
3185 com.android.internal.R.styleable.Window);
3186 if (ent.array.getBoolean(
3187 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
3188 return;
3189 }
3190 if (ent.array.getBoolean(
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07003191 com.android.internal.R.styleable.Window_windowIsFloating, false)) {
3192 return;
3193 }
3194 if (ent.array.getBoolean(
Dianne Hackborn284ac932009-08-28 10:34:25 -07003195 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
3196 return;
3197 }
3198 }
3199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003200 mStartingIconInTransition = true;
3201 wtoken.startingData = new StartingData(
3202 pkg, theme, nonLocalizedLabel,
3203 labelRes, icon);
3204 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3205 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3206 // want to process the message ASAP, before any other queued
3207 // messages.
3208 mH.sendMessageAtFrontOfQueue(m);
3209 }
3210 }
3211
3212 public void setAppWillBeHidden(IBinder token) {
3213 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3214 "setAppWillBeHidden()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003215 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003216 }
3217
3218 AppWindowToken wtoken;
3219
3220 synchronized(mWindowMap) {
3221 wtoken = findAppWindowToken(token);
3222 if (wtoken == null) {
3223 Log.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
3224 return;
3225 }
3226 wtoken.willBeHidden = true;
3227 }
3228 }
Romain Guy06882f82009-06-10 13:36:04 -07003229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003230 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
3231 boolean visible, int transit, boolean performLayout) {
3232 boolean delayed = false;
3233
3234 if (wtoken.clientHidden == visible) {
3235 wtoken.clientHidden = !visible;
3236 wtoken.sendAppVisibilityToClients();
3237 }
Romain Guy06882f82009-06-10 13:36:04 -07003238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003239 wtoken.willBeHidden = false;
3240 if (wtoken.hidden == visible) {
3241 final int N = wtoken.allAppWindows.size();
3242 boolean changed = false;
3243 if (DEBUG_APP_TRANSITIONS) Log.v(
3244 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
3245 + " performLayout=" + performLayout);
Romain Guy06882f82009-06-10 13:36:04 -07003246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003247 boolean runningAppAnimation = false;
Romain Guy06882f82009-06-10 13:36:04 -07003248
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003249 if (transit != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 if (wtoken.animation == sDummyAnimation) {
3251 wtoken.animation = null;
3252 }
3253 applyAnimationLocked(wtoken, lp, transit, visible);
3254 changed = true;
3255 if (wtoken.animation != null) {
3256 delayed = runningAppAnimation = true;
3257 }
3258 }
Romain Guy06882f82009-06-10 13:36:04 -07003259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003260 for (int i=0; i<N; i++) {
3261 WindowState win = wtoken.allAppWindows.get(i);
3262 if (win == wtoken.startingWindow) {
3263 continue;
3264 }
3265
3266 if (win.isAnimating()) {
3267 delayed = true;
3268 }
Romain Guy06882f82009-06-10 13:36:04 -07003269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 //Log.i(TAG, "Window " + win + ": vis=" + win.isVisible());
3271 //win.dump(" ");
3272 if (visible) {
3273 if (!win.isVisibleNow()) {
3274 if (!runningAppAnimation) {
3275 applyAnimationLocked(win,
3276 WindowManagerPolicy.TRANSIT_ENTER, true);
3277 }
3278 changed = true;
3279 }
3280 } else if (win.isVisibleNow()) {
3281 if (!runningAppAnimation) {
3282 applyAnimationLocked(win,
3283 WindowManagerPolicy.TRANSIT_EXIT, false);
3284 }
3285 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
3286 KeyWaiter.RETURN_NOTHING);
3287 changed = true;
3288 }
3289 }
3290
3291 wtoken.hidden = wtoken.hiddenRequested = !visible;
3292 if (!visible) {
3293 unsetAppFreezingScreenLocked(wtoken, true, true);
3294 } else {
3295 // If we are being set visible, and the starting window is
3296 // not yet displayed, then make sure it doesn't get displayed.
3297 WindowState swin = wtoken.startingWindow;
3298 if (swin != null && (swin.mDrawPending
3299 || swin.mCommitDrawPending)) {
3300 swin.mPolicyVisibility = false;
3301 swin.mPolicyVisibilityAfterAnim = false;
3302 }
3303 }
Romain Guy06882f82009-06-10 13:36:04 -07003304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "setTokenVisibilityLocked: " + wtoken
3306 + ": hidden=" + wtoken.hidden + " hiddenRequested="
3307 + wtoken.hiddenRequested);
Romain Guy06882f82009-06-10 13:36:04 -07003308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 if (changed && performLayout) {
3310 mLayoutNeeded = true;
3311 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 performLayoutAndPlaceSurfacesLocked();
3313 }
3314 }
3315
3316 if (wtoken.animation != null) {
3317 delayed = true;
3318 }
Romain Guy06882f82009-06-10 13:36:04 -07003319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003320 return delayed;
3321 }
3322
3323 public void setAppVisibility(IBinder token, boolean visible) {
3324 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3325 "setAppVisibility()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003326 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003327 }
3328
3329 AppWindowToken wtoken;
3330
3331 synchronized(mWindowMap) {
3332 wtoken = findAppWindowToken(token);
3333 if (wtoken == null) {
3334 Log.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
3335 return;
3336 }
3337
3338 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
3339 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003340 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003341 Log.v(TAG, "setAppVisibility(" + token + ", " + visible
3342 + "): mNextAppTransition=" + mNextAppTransition
3343 + " hidden=" + wtoken.hidden
3344 + " hiddenRequested=" + wtoken.hiddenRequested, e);
3345 }
Romain Guy06882f82009-06-10 13:36:04 -07003346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003347 // If we are preparing an app transition, then delay changing
3348 // the visibility of this token until we execute that transition.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003349 if (!mDisplayFrozen && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003350 // Already in requested state, don't do anything more.
3351 if (wtoken.hiddenRequested != visible) {
3352 return;
3353 }
3354 wtoken.hiddenRequested = !visible;
Romain Guy06882f82009-06-10 13:36:04 -07003355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003356 if (DEBUG_APP_TRANSITIONS) Log.v(
3357 TAG, "Setting dummy animation on: " + wtoken);
3358 wtoken.setDummyAnimation();
3359 mOpeningApps.remove(wtoken);
3360 mClosingApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003361 wtoken.waitingToShow = wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003362 wtoken.inPendingTransaction = true;
3363 if (visible) {
3364 mOpeningApps.add(wtoken);
3365 wtoken.allDrawn = false;
3366 wtoken.startingDisplayed = false;
3367 wtoken.startingMoved = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -07003368 wtoken.waitingToShow = true;
Romain Guy06882f82009-06-10 13:36:04 -07003369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003370 if (wtoken.clientHidden) {
3371 // In the case where we are making an app visible
3372 // but holding off for a transition, we still need
3373 // to tell the client to make its windows visible so
3374 // they get drawn. Otherwise, we will wait on
3375 // performing the transition until all windows have
3376 // been drawn, they never will be, and we are sad.
3377 wtoken.clientHidden = false;
3378 wtoken.sendAppVisibilityToClients();
3379 }
3380 } else {
3381 mClosingApps.add(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003382 wtoken.waitingToHide = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003383 }
3384 return;
3385 }
Romain Guy06882f82009-06-10 13:36:04 -07003386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003387 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003388 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 wtoken.updateReportedVisibilityLocked();
3390 Binder.restoreCallingIdentity(origId);
3391 }
3392 }
3393
3394 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
3395 boolean unfreezeSurfaceNow, boolean force) {
3396 if (wtoken.freezingScreen) {
3397 if (DEBUG_ORIENTATION) Log.v(TAG, "Clear freezing of " + wtoken
3398 + " force=" + force);
3399 final int N = wtoken.allAppWindows.size();
3400 boolean unfrozeWindows = false;
3401 for (int i=0; i<N; i++) {
3402 WindowState w = wtoken.allAppWindows.get(i);
3403 if (w.mAppFreezing) {
3404 w.mAppFreezing = false;
3405 if (w.mSurface != null && !w.mOrientationChanging) {
3406 w.mOrientationChanging = true;
3407 }
3408 unfrozeWindows = true;
3409 }
3410 }
3411 if (force || unfrozeWindows) {
3412 if (DEBUG_ORIENTATION) Log.v(TAG, "No longer freezing: " + wtoken);
3413 wtoken.freezingScreen = false;
3414 mAppsFreezingScreen--;
3415 }
3416 if (unfreezeSurfaceNow) {
3417 if (unfrozeWindows) {
3418 mLayoutNeeded = true;
3419 performLayoutAndPlaceSurfacesLocked();
3420 }
3421 if (mAppsFreezingScreen == 0 && !mWindowsFreezingScreen) {
3422 stopFreezingDisplayLocked();
3423 }
3424 }
3425 }
3426 }
Romain Guy06882f82009-06-10 13:36:04 -07003427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003428 public void startAppFreezingScreenLocked(AppWindowToken wtoken,
3429 int configChanges) {
3430 if (DEBUG_ORIENTATION) {
3431 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003432 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003433 Log.i(TAG, "Set freezing of " + wtoken.appToken
3434 + ": hidden=" + wtoken.hidden + " freezing="
3435 + wtoken.freezingScreen, e);
3436 }
3437 if (!wtoken.hiddenRequested) {
3438 if (!wtoken.freezingScreen) {
3439 wtoken.freezingScreen = true;
3440 mAppsFreezingScreen++;
3441 if (mAppsFreezingScreen == 1) {
3442 startFreezingDisplayLocked();
3443 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
3444 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
3445 5000);
3446 }
3447 }
3448 final int N = wtoken.allAppWindows.size();
3449 for (int i=0; i<N; i++) {
3450 WindowState w = wtoken.allAppWindows.get(i);
3451 w.mAppFreezing = true;
3452 }
3453 }
3454 }
Romain Guy06882f82009-06-10 13:36:04 -07003455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003456 public void startAppFreezingScreen(IBinder token, int configChanges) {
3457 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3458 "setAppFreezingScreen()")) {
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) {
3463 if (configChanges == 0 && !mDisplayFrozen) {
3464 if (DEBUG_ORIENTATION) Log.v(TAG, "Skipping set freeze of " + token);
3465 return;
3466 }
Romain Guy06882f82009-06-10 13:36:04 -07003467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 AppWindowToken wtoken = findAppWindowToken(token);
3469 if (wtoken == null || wtoken.appToken == null) {
3470 Log.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
3471 return;
3472 }
3473 final long origId = Binder.clearCallingIdentity();
3474 startAppFreezingScreenLocked(wtoken, configChanges);
3475 Binder.restoreCallingIdentity(origId);
3476 }
3477 }
Romain Guy06882f82009-06-10 13:36:04 -07003478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 public void stopAppFreezingScreen(IBinder token, boolean force) {
3480 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3481 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003482 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003483 }
3484
3485 synchronized(mWindowMap) {
3486 AppWindowToken wtoken = findAppWindowToken(token);
3487 if (wtoken == null || wtoken.appToken == null) {
3488 return;
3489 }
3490 final long origId = Binder.clearCallingIdentity();
3491 if (DEBUG_ORIENTATION) Log.v(TAG, "Clear freezing of " + token
3492 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
3493 unsetAppFreezingScreenLocked(wtoken, true, force);
3494 Binder.restoreCallingIdentity(origId);
3495 }
3496 }
Romain Guy06882f82009-06-10 13:36:04 -07003497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003498 public void removeAppToken(IBinder token) {
3499 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3500 "removeAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003501 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003502 }
3503
3504 AppWindowToken wtoken = null;
3505 AppWindowToken startingToken = null;
3506 boolean delayed = false;
3507
3508 final long origId = Binder.clearCallingIdentity();
3509 synchronized(mWindowMap) {
3510 WindowToken basewtoken = mTokenMap.remove(token);
3511 mTokenList.remove(basewtoken);
3512 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
3513 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "Removing app token: " + wtoken);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003514 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 wtoken.inPendingTransaction = false;
3516 mOpeningApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003517 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003518 if (mClosingApps.contains(wtoken)) {
3519 delayed = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003520 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 mClosingApps.add(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003522 wtoken.waitingToHide = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003523 delayed = true;
3524 }
3525 if (DEBUG_APP_TRANSITIONS) Log.v(
3526 TAG, "Removing app " + wtoken + " delayed=" + delayed
3527 + " animation=" + wtoken.animation
3528 + " animating=" + wtoken.animating);
3529 if (delayed) {
3530 // set the token aside because it has an active animation to be finished
3531 mExitingAppTokens.add(wtoken);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003532 } else {
3533 // Make sure there is no animation running on this token,
3534 // so any windows associated with it will be removed as
3535 // soon as their animations are complete
3536 wtoken.animation = null;
3537 wtoken.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003538 }
3539 mAppTokens.remove(wtoken);
3540 wtoken.removed = true;
3541 if (wtoken.startingData != null) {
3542 startingToken = wtoken;
3543 }
3544 unsetAppFreezingScreenLocked(wtoken, true, true);
3545 if (mFocusedApp == wtoken) {
3546 if (DEBUG_FOCUS) Log.v(TAG, "Removing focused app token:" + wtoken);
3547 mFocusedApp = null;
3548 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3549 mKeyWaiter.tickle();
3550 }
3551 } else {
3552 Log.w(TAG, "Attempted to remove non-existing app token: " + token);
3553 }
Romain Guy06882f82009-06-10 13:36:04 -07003554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003555 if (!delayed && wtoken != null) {
3556 wtoken.updateReportedVisibilityLocked();
3557 }
3558 }
3559 Binder.restoreCallingIdentity(origId);
3560
3561 if (startingToken != null) {
3562 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Schedule remove starting "
3563 + startingToken + ": app token removed");
3564 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
3565 mH.sendMessage(m);
3566 }
3567 }
3568
3569 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
3570 final int NW = token.windows.size();
3571 for (int i=0; i<NW; i++) {
3572 WindowState win = token.windows.get(i);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003573 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Tmp removing app window " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003574 mWindows.remove(win);
3575 int j = win.mChildWindows.size();
3576 while (j > 0) {
3577 j--;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003578 WindowState cwin = (WindowState)win.mChildWindows.get(j);
3579 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
3580 "Tmp removing child window " + cwin);
3581 mWindows.remove(cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003582 }
3583 }
3584 return NW > 0;
3585 }
3586
3587 void dumpAppTokensLocked() {
3588 for (int i=mAppTokens.size()-1; i>=0; i--) {
3589 Log.v(TAG, " #" + i + ": " + mAppTokens.get(i).token);
3590 }
3591 }
Romain Guy06882f82009-06-10 13:36:04 -07003592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003593 void dumpWindowsLocked() {
3594 for (int i=mWindows.size()-1; i>=0; i--) {
3595 Log.v(TAG, " #" + i + ": " + mWindows.get(i));
3596 }
3597 }
Romain Guy06882f82009-06-10 13:36:04 -07003598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003599 private int findWindowOffsetLocked(int tokenPos) {
3600 final int NW = mWindows.size();
3601
3602 if (tokenPos >= mAppTokens.size()) {
3603 int i = NW;
3604 while (i > 0) {
3605 i--;
3606 WindowState win = (WindowState)mWindows.get(i);
3607 if (win.getAppToken() != null) {
3608 return i+1;
3609 }
3610 }
3611 }
3612
3613 while (tokenPos > 0) {
3614 // Find the first app token below the new position that has
3615 // a window displayed.
3616 final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
3617 if (DEBUG_REORDER) Log.v(TAG, "Looking for lower windows @ "
3618 + tokenPos + " -- " + wtoken.token);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003619 if (wtoken.sendingToBottom) {
3620 if (DEBUG_REORDER) Log.v(TAG,
3621 "Skipping token -- currently sending to bottom");
3622 tokenPos--;
3623 continue;
3624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003625 int i = wtoken.windows.size();
3626 while (i > 0) {
3627 i--;
3628 WindowState win = wtoken.windows.get(i);
3629 int j = win.mChildWindows.size();
3630 while (j > 0) {
3631 j--;
3632 WindowState cwin = (WindowState)win.mChildWindows.get(j);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003633 if (cwin.mSubLayer >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003634 for (int pos=NW-1; pos>=0; pos--) {
3635 if (mWindows.get(pos) == cwin) {
3636 if (DEBUG_REORDER) Log.v(TAG,
3637 "Found child win @" + (pos+1));
3638 return pos+1;
3639 }
3640 }
3641 }
3642 }
3643 for (int pos=NW-1; pos>=0; pos--) {
3644 if (mWindows.get(pos) == win) {
3645 if (DEBUG_REORDER) Log.v(TAG, "Found win @" + (pos+1));
3646 return pos+1;
3647 }
3648 }
3649 }
3650 tokenPos--;
3651 }
3652
3653 return 0;
3654 }
3655
3656 private final int reAddWindowLocked(int index, WindowState win) {
3657 final int NCW = win.mChildWindows.size();
3658 boolean added = false;
3659 for (int j=0; j<NCW; j++) {
3660 WindowState cwin = (WindowState)win.mChildWindows.get(j);
3661 if (!added && cwin.mSubLayer >= 0) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003662 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Re-adding child window at "
3663 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003664 mWindows.add(index, win);
3665 index++;
3666 added = true;
3667 }
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003668 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Re-adding window at "
3669 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003670 mWindows.add(index, cwin);
3671 index++;
3672 }
3673 if (!added) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003674 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Re-adding window at "
3675 + index + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 mWindows.add(index, win);
3677 index++;
3678 }
3679 return index;
3680 }
Romain Guy06882f82009-06-10 13:36:04 -07003681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 private final int reAddAppWindowsLocked(int index, WindowToken token) {
3683 final int NW = token.windows.size();
3684 for (int i=0; i<NW; i++) {
3685 index = reAddWindowLocked(index, token.windows.get(i));
3686 }
3687 return index;
3688 }
3689
3690 public void moveAppToken(int index, IBinder token) {
3691 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3692 "moveAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003693 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 }
3695
3696 synchronized(mWindowMap) {
3697 if (DEBUG_REORDER) Log.v(TAG, "Initial app tokens:");
3698 if (DEBUG_REORDER) dumpAppTokensLocked();
3699 final AppWindowToken wtoken = findAppWindowToken(token);
3700 if (wtoken == null || !mAppTokens.remove(wtoken)) {
3701 Log.w(TAG, "Attempting to reorder token that doesn't exist: "
3702 + token + " (" + wtoken + ")");
3703 return;
3704 }
3705 mAppTokens.add(index, wtoken);
3706 if (DEBUG_REORDER) Log.v(TAG, "Moved " + token + " to " + index + ":");
3707 if (DEBUG_REORDER) dumpAppTokensLocked();
Romain Guy06882f82009-06-10 13:36:04 -07003708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003709 final long origId = Binder.clearCallingIdentity();
3710 if (DEBUG_REORDER) Log.v(TAG, "Removing windows in " + token + ":");
3711 if (DEBUG_REORDER) dumpWindowsLocked();
3712 if (tmpRemoveAppWindowsLocked(wtoken)) {
3713 if (DEBUG_REORDER) Log.v(TAG, "Adding windows back in:");
3714 if (DEBUG_REORDER) dumpWindowsLocked();
3715 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
3716 if (DEBUG_REORDER) Log.v(TAG, "Final window list:");
3717 if (DEBUG_REORDER) dumpWindowsLocked();
3718 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003719 mLayoutNeeded = true;
3720 performLayoutAndPlaceSurfacesLocked();
3721 }
3722 Binder.restoreCallingIdentity(origId);
3723 }
3724 }
3725
3726 private void removeAppTokensLocked(List<IBinder> tokens) {
3727 // XXX This should be done more efficiently!
3728 // (take advantage of the fact that both lists should be
3729 // ordered in the same way.)
3730 int N = tokens.size();
3731 for (int i=0; i<N; i++) {
3732 IBinder token = tokens.get(i);
3733 final AppWindowToken wtoken = findAppWindowToken(token);
3734 if (!mAppTokens.remove(wtoken)) {
3735 Log.w(TAG, "Attempting to reorder token that doesn't exist: "
3736 + token + " (" + wtoken + ")");
3737 i--;
3738 N--;
3739 }
3740 }
3741 }
3742
Dianne Hackborna8f60182009-09-01 19:01:50 -07003743 private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos,
3744 boolean updateFocusAndLayout) {
3745 // First remove all of the windows from the list.
3746 tmpRemoveAppWindowsLocked(wtoken);
3747
3748 // Where to start adding?
3749 int pos = findWindowOffsetLocked(tokenPos);
3750
3751 // And now add them back at the correct place.
3752 pos = reAddAppWindowsLocked(pos, wtoken);
3753
3754 if (updateFocusAndLayout) {
3755 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
3756 assignLayersLocked();
3757 }
3758 mLayoutNeeded = true;
3759 performLayoutAndPlaceSurfacesLocked();
3760 }
3761 }
3762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
3764 // First remove all of the windows from the list.
3765 final int N = tokens.size();
3766 int i;
3767 for (i=0; i<N; i++) {
3768 WindowToken token = mTokenMap.get(tokens.get(i));
3769 if (token != null) {
3770 tmpRemoveAppWindowsLocked(token);
3771 }
3772 }
3773
3774 // Where to start adding?
3775 int pos = findWindowOffsetLocked(tokenPos);
3776
3777 // And now add them back at the correct place.
3778 for (i=0; i<N; i++) {
3779 WindowToken token = mTokenMap.get(tokens.get(i));
3780 if (token != null) {
3781 pos = reAddAppWindowsLocked(pos, token);
3782 }
3783 }
3784
Dianne Hackborna8f60182009-09-01 19:01:50 -07003785 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
3786 assignLayersLocked();
3787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003788 mLayoutNeeded = true;
3789 performLayoutAndPlaceSurfacesLocked();
3790
3791 //dump();
3792 }
3793
3794 public void moveAppTokensToTop(List<IBinder> tokens) {
3795 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3796 "moveAppTokensToTop()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003797 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 }
3799
3800 final long origId = Binder.clearCallingIdentity();
3801 synchronized(mWindowMap) {
3802 removeAppTokensLocked(tokens);
3803 final int N = tokens.size();
3804 for (int i=0; i<N; i++) {
3805 AppWindowToken wt = findAppWindowToken(tokens.get(i));
3806 if (wt != null) {
3807 mAppTokens.add(wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003808 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07003809 mToTopApps.remove(wt);
3810 mToBottomApps.remove(wt);
3811 mToTopApps.add(wt);
3812 wt.sendingToBottom = false;
3813 wt.sendingToTop = true;
3814 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003815 }
3816 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07003817
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003818 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07003819 moveAppWindowsLocked(tokens, mAppTokens.size());
3820 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 }
3822 Binder.restoreCallingIdentity(origId);
3823 }
3824
3825 public void moveAppTokensToBottom(List<IBinder> tokens) {
3826 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3827 "moveAppTokensToBottom()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003828 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003829 }
3830
3831 final long origId = Binder.clearCallingIdentity();
3832 synchronized(mWindowMap) {
3833 removeAppTokensLocked(tokens);
3834 final int N = tokens.size();
3835 int pos = 0;
3836 for (int i=0; i<N; i++) {
3837 AppWindowToken wt = findAppWindowToken(tokens.get(i));
3838 if (wt != null) {
3839 mAppTokens.add(pos, wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003840 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07003841 mToTopApps.remove(wt);
3842 mToBottomApps.remove(wt);
3843 mToBottomApps.add(i, wt);
3844 wt.sendingToTop = false;
3845 wt.sendingToBottom = true;
3846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003847 pos++;
3848 }
3849 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07003850
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003851 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07003852 moveAppWindowsLocked(tokens, 0);
3853 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 }
3855 Binder.restoreCallingIdentity(origId);
3856 }
3857
3858 // -------------------------------------------------------------
3859 // Misc IWindowSession methods
3860 // -------------------------------------------------------------
Romain Guy06882f82009-06-10 13:36:04 -07003861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 public void disableKeyguard(IBinder token, String tag) {
3863 if (mContext.checkCallingPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3864 != PackageManager.PERMISSION_GRANTED) {
3865 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3866 }
3867 mKeyguardDisabled.acquire(token, tag);
3868 }
3869
3870 public void reenableKeyguard(IBinder token) {
3871 if (mContext.checkCallingPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3872 != PackageManager.PERMISSION_GRANTED) {
3873 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3874 }
3875 synchronized (mKeyguardDisabled) {
3876 mKeyguardDisabled.release(token);
3877
3878 if (!mKeyguardDisabled.isAcquired()) {
3879 // if we are the last one to reenable the keyguard wait until
3880 // we have actaully finished reenabling until returning
3881 mWaitingUntilKeyguardReenabled = true;
3882 while (mWaitingUntilKeyguardReenabled) {
3883 try {
3884 mKeyguardDisabled.wait();
3885 } catch (InterruptedException e) {
3886 Thread.currentThread().interrupt();
3887 }
3888 }
3889 }
3890 }
3891 }
3892
3893 /**
3894 * @see android.app.KeyguardManager#exitKeyguardSecurely
3895 */
3896 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
3897 if (mContext.checkCallingPermission(android.Manifest.permission.DISABLE_KEYGUARD)
3898 != PackageManager.PERMISSION_GRANTED) {
3899 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
3900 }
3901 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
3902 public void onKeyguardExitResult(boolean success) {
3903 try {
3904 callback.onKeyguardExitResult(success);
3905 } catch (RemoteException e) {
3906 // Client has died, we don't care.
3907 }
3908 }
3909 });
3910 }
3911
3912 public boolean inKeyguardRestrictedInputMode() {
3913 return mPolicy.inKeyguardRestrictedKeyInputMode();
3914 }
Romain Guy06882f82009-06-10 13:36:04 -07003915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 static float fixScale(float scale) {
3917 if (scale < 0) scale = 0;
3918 else if (scale > 20) scale = 20;
3919 return Math.abs(scale);
3920 }
Romain Guy06882f82009-06-10 13:36:04 -07003921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003922 public void setAnimationScale(int which, float scale) {
3923 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3924 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003925 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 }
3927
3928 if (scale < 0) scale = 0;
3929 else if (scale > 20) scale = 20;
3930 scale = Math.abs(scale);
3931 switch (which) {
3932 case 0: mWindowAnimationScale = fixScale(scale); break;
3933 case 1: mTransitionAnimationScale = fixScale(scale); break;
3934 }
Romain Guy06882f82009-06-10 13:36:04 -07003935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003936 // Persist setting
3937 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
3938 }
Romain Guy06882f82009-06-10 13:36:04 -07003939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003940 public void setAnimationScales(float[] scales) {
3941 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
3942 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003943 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003944 }
3945
3946 if (scales != null) {
3947 if (scales.length >= 1) {
3948 mWindowAnimationScale = fixScale(scales[0]);
3949 }
3950 if (scales.length >= 2) {
3951 mTransitionAnimationScale = fixScale(scales[1]);
3952 }
3953 }
Romain Guy06882f82009-06-10 13:36:04 -07003954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003955 // Persist setting
3956 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
3957 }
Romain Guy06882f82009-06-10 13:36:04 -07003958
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003959 public float getAnimationScale(int which) {
3960 switch (which) {
3961 case 0: return mWindowAnimationScale;
3962 case 1: return mTransitionAnimationScale;
3963 }
3964 return 0;
3965 }
Romain Guy06882f82009-06-10 13:36:04 -07003966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967 public float[] getAnimationScales() {
3968 return new float[] { mWindowAnimationScale, mTransitionAnimationScale };
3969 }
Romain Guy06882f82009-06-10 13:36:04 -07003970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003971 public int getSwitchState(int sw) {
3972 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
3973 "getSwitchState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003974 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003975 }
3976 return KeyInputQueue.getSwitchState(sw);
3977 }
Romain Guy06882f82009-06-10 13:36:04 -07003978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 public int getSwitchStateForDevice(int devid, int sw) {
3980 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
3981 "getSwitchStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003982 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003983 }
3984 return KeyInputQueue.getSwitchState(devid, sw);
3985 }
Romain Guy06882f82009-06-10 13:36:04 -07003986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003987 public int getScancodeState(int sw) {
3988 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
3989 "getScancodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003990 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003991 }
3992 return KeyInputQueue.getScancodeState(sw);
3993 }
Romain Guy06882f82009-06-10 13:36:04 -07003994
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 public int getScancodeStateForDevice(int devid, int sw) {
3996 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
3997 "getScancodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003998 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003999 }
4000 return KeyInputQueue.getScancodeState(devid, sw);
4001 }
Romain Guy06882f82009-06-10 13:36:04 -07004002
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004003 public int getKeycodeState(int sw) {
4004 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4005 "getKeycodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004006 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004007 }
4008 return KeyInputQueue.getKeycodeState(sw);
4009 }
Romain Guy06882f82009-06-10 13:36:04 -07004010
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004011 public int getKeycodeStateForDevice(int devid, int sw) {
4012 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4013 "getKeycodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004014 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004015 }
4016 return KeyInputQueue.getKeycodeState(devid, sw);
4017 }
Romain Guy06882f82009-06-10 13:36:04 -07004018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
4020 return KeyInputQueue.hasKeys(keycodes, keyExists);
4021 }
Romain Guy06882f82009-06-10 13:36:04 -07004022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004023 public void enableScreenAfterBoot() {
4024 synchronized(mWindowMap) {
4025 if (mSystemBooted) {
4026 return;
4027 }
4028 mSystemBooted = true;
4029 }
Romain Guy06882f82009-06-10 13:36:04 -07004030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004031 performEnableScreen();
4032 }
Romain Guy06882f82009-06-10 13:36:04 -07004033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 public void enableScreenIfNeededLocked() {
4035 if (mDisplayEnabled) {
4036 return;
4037 }
4038 if (!mSystemBooted) {
4039 return;
4040 }
4041 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
4042 }
Romain Guy06882f82009-06-10 13:36:04 -07004043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004044 public void performEnableScreen() {
4045 synchronized(mWindowMap) {
4046 if (mDisplayEnabled) {
4047 return;
4048 }
4049 if (!mSystemBooted) {
4050 return;
4051 }
Romain Guy06882f82009-06-10 13:36:04 -07004052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004053 // Don't enable the screen until all existing windows
4054 // have been drawn.
4055 final int N = mWindows.size();
4056 for (int i=0; i<N; i++) {
4057 WindowState w = (WindowState)mWindows.get(i);
4058 if (w.isVisibleLw() && !w.isDisplayedLw()) {
4059 return;
4060 }
4061 }
Romain Guy06882f82009-06-10 13:36:04 -07004062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 mDisplayEnabled = true;
4064 if (false) {
4065 Log.i(TAG, "ENABLING SCREEN!");
4066 StringWriter sw = new StringWriter();
4067 PrintWriter pw = new PrintWriter(sw);
4068 this.dump(null, pw, null);
4069 Log.i(TAG, sw.toString());
4070 }
4071 try {
4072 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
4073 if (surfaceFlinger != null) {
4074 //Log.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
4075 Parcel data = Parcel.obtain();
4076 data.writeInterfaceToken("android.ui.ISurfaceComposer");
4077 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
4078 data, null, 0);
4079 data.recycle();
4080 }
4081 } catch (RemoteException ex) {
4082 Log.e(TAG, "Boot completed: SurfaceFlinger is dead!");
4083 }
4084 }
Romain Guy06882f82009-06-10 13:36:04 -07004085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086 mPolicy.enableScreenAfterBoot();
Romain Guy06882f82009-06-10 13:36:04 -07004087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 // Make sure the last requested orientation has been applied.
Dianne Hackborn321ae682009-03-27 16:16:03 -07004089 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
4090 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 }
Romain Guy06882f82009-06-10 13:36:04 -07004092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 public void setInTouchMode(boolean mode) {
4094 synchronized(mWindowMap) {
4095 mInTouchMode = mode;
4096 }
4097 }
4098
Romain Guy06882f82009-06-10 13:36:04 -07004099 public void setRotation(int rotation,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004100 boolean alwaysSendConfiguration, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004102 "setRotation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004103 throw new SecurityException("Requires SET_ORIENTATION permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004104 }
4105
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004106 setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004107 }
Romain Guy06882f82009-06-10 13:36:04 -07004108
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004109 public void setRotationUnchecked(int rotation,
4110 boolean alwaysSendConfiguration, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004111 if(DEBUG_ORIENTATION) Log.v(TAG,
4112 "alwaysSendConfiguration set to "+alwaysSendConfiguration);
Romain Guy06882f82009-06-10 13:36:04 -07004113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004114 long origId = Binder.clearCallingIdentity();
4115 boolean changed;
4116 synchronized(mWindowMap) {
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004117 changed = setRotationUncheckedLocked(rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004118 }
Romain Guy06882f82009-06-10 13:36:04 -07004119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004120 if (changed) {
4121 sendNewConfiguration();
4122 synchronized(mWindowMap) {
4123 mLayoutNeeded = true;
4124 performLayoutAndPlaceSurfacesLocked();
4125 }
4126 } else if (alwaysSendConfiguration) {
4127 //update configuration ignoring orientation change
4128 sendNewConfiguration();
4129 }
Romain Guy06882f82009-06-10 13:36:04 -07004130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131 Binder.restoreCallingIdentity(origId);
4132 }
Romain Guy06882f82009-06-10 13:36:04 -07004133
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004134 public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004135 boolean changed;
4136 if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
4137 rotation = mRequestedRotation;
4138 } else {
4139 mRequestedRotation = rotation;
Dianne Hackborn321ae682009-03-27 16:16:03 -07004140 mLastRotationFlags = animFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004141 }
4142 if (DEBUG_ORIENTATION) Log.v(TAG, "Overwriting rotation value from " + rotation);
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07004143 rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004144 mRotation, mDisplayEnabled);
4145 if (DEBUG_ORIENTATION) Log.v(TAG, "new rotation is set to " + rotation);
4146 changed = mDisplayEnabled && mRotation != rotation;
Romain Guy06882f82009-06-10 13:36:04 -07004147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004148 if (changed) {
Romain Guy06882f82009-06-10 13:36:04 -07004149 if (DEBUG_ORIENTATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 "Rotation changed to " + rotation
4151 + " from " + mRotation
4152 + " (forceApp=" + mForcedAppOrientation
4153 + ", req=" + mRequestedRotation + ")");
4154 mRotation = rotation;
4155 mWindowsFreezingScreen = true;
4156 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
4157 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
4158 2000);
4159 startFreezingDisplayLocked();
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004160 Log.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004161 mQueue.setOrientation(rotation);
4162 if (mDisplayEnabled) {
Dianne Hackborn321ae682009-03-27 16:16:03 -07004163 Surface.setOrientation(0, rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004164 }
4165 for (int i=mWindows.size()-1; i>=0; i--) {
4166 WindowState w = (WindowState)mWindows.get(i);
4167 if (w.mSurface != null) {
4168 w.mOrientationChanging = true;
4169 }
4170 }
4171 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
4172 try {
4173 mRotationWatchers.get(i).onRotationChanged(rotation);
4174 } catch (RemoteException e) {
4175 }
4176 }
4177 } //end if changed
Romain Guy06882f82009-06-10 13:36:04 -07004178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004179 return changed;
4180 }
Romain Guy06882f82009-06-10 13:36:04 -07004181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004182 public int getRotation() {
4183 return mRotation;
4184 }
4185
4186 public int watchRotation(IRotationWatcher watcher) {
4187 final IBinder watcherBinder = watcher.asBinder();
4188 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4189 public void binderDied() {
4190 synchronized (mWindowMap) {
4191 for (int i=0; i<mRotationWatchers.size(); i++) {
4192 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004193 IRotationWatcher removed = mRotationWatchers.remove(i);
4194 if (removed != null) {
4195 removed.asBinder().unlinkToDeath(this, 0);
4196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 i--;
4198 }
4199 }
4200 }
4201 }
4202 };
Romain Guy06882f82009-06-10 13:36:04 -07004203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004204 synchronized (mWindowMap) {
4205 try {
4206 watcher.asBinder().linkToDeath(dr, 0);
4207 mRotationWatchers.add(watcher);
4208 } catch (RemoteException e) {
4209 // Client died, no cleanup needed.
4210 }
Romain Guy06882f82009-06-10 13:36:04 -07004211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004212 return mRotation;
4213 }
4214 }
4215
4216 /**
4217 * Starts the view server on the specified port.
4218 *
4219 * @param port The port to listener to.
4220 *
4221 * @return True if the server was successfully started, false otherwise.
4222 *
4223 * @see com.android.server.ViewServer
4224 * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT
4225 */
4226 public boolean startViewServer(int port) {
Romain Guy06882f82009-06-10 13:36:04 -07004227 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004228 return false;
4229 }
4230
4231 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4232 return false;
4233 }
4234
4235 if (port < 1024) {
4236 return false;
4237 }
4238
4239 if (mViewServer != null) {
4240 if (!mViewServer.isRunning()) {
4241 try {
4242 return mViewServer.start();
4243 } catch (IOException e) {
Romain Guy06882f82009-06-10 13:36:04 -07004244 Log.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004245 }
4246 }
4247 return false;
4248 }
4249
4250 try {
4251 mViewServer = new ViewServer(this, port);
4252 return mViewServer.start();
4253 } catch (IOException e) {
4254 Log.w(TAG, "View server did not start");
4255 }
4256 return false;
4257 }
4258
Romain Guy06882f82009-06-10 13:36:04 -07004259 private boolean isSystemSecure() {
4260 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4261 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4262 }
4263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004264 /**
4265 * Stops the view server if it exists.
4266 *
4267 * @return True if the server stopped, false if it wasn't started or
4268 * couldn't be stopped.
4269 *
4270 * @see com.android.server.ViewServer
4271 */
4272 public boolean stopViewServer() {
Romain Guy06882f82009-06-10 13:36:04 -07004273 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004274 return false;
4275 }
4276
4277 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4278 return false;
4279 }
4280
4281 if (mViewServer != null) {
4282 return mViewServer.stop();
4283 }
4284 return false;
4285 }
4286
4287 /**
4288 * Indicates whether the view server is running.
4289 *
4290 * @return True if the server is running, false otherwise.
4291 *
4292 * @see com.android.server.ViewServer
4293 */
4294 public boolean isViewServerRunning() {
Romain Guy06882f82009-06-10 13:36:04 -07004295 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004296 return false;
4297 }
4298
4299 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4300 return false;
4301 }
4302
4303 return mViewServer != null && mViewServer.isRunning();
4304 }
4305
4306 /**
4307 * Lists all availble windows in the system. The listing is written in the
4308 * specified Socket's output stream with the following syntax:
4309 * windowHashCodeInHexadecimal windowName
4310 * Each line of the ouput represents a different window.
4311 *
4312 * @param client The remote client to send the listing to.
4313 * @return False if an error occured, true otherwise.
4314 */
4315 boolean viewServerListWindows(Socket client) {
Romain Guy06882f82009-06-10 13:36:04 -07004316 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 return false;
4318 }
4319
4320 boolean result = true;
4321
4322 Object[] windows;
4323 synchronized (mWindowMap) {
4324 windows = new Object[mWindows.size()];
4325 //noinspection unchecked
4326 windows = mWindows.toArray(windows);
4327 }
4328
4329 BufferedWriter out = null;
4330
4331 // Any uncaught exception will crash the system process
4332 try {
4333 OutputStream clientStream = client.getOutputStream();
4334 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4335
4336 final int count = windows.length;
4337 for (int i = 0; i < count; i++) {
4338 final WindowState w = (WindowState) windows[i];
4339 out.write(Integer.toHexString(System.identityHashCode(w)));
4340 out.write(' ');
4341 out.append(w.mAttrs.getTitle());
4342 out.write('\n');
4343 }
4344
4345 out.write("DONE.\n");
4346 out.flush();
4347 } catch (Exception e) {
4348 result = false;
4349 } finally {
4350 if (out != null) {
4351 try {
4352 out.close();
4353 } catch (IOException e) {
4354 result = false;
4355 }
4356 }
4357 }
4358
4359 return result;
4360 }
4361
4362 /**
4363 * Sends a command to a target window. The result of the command, if any, will be
4364 * written in the output stream of the specified socket.
4365 *
4366 * The parameters must follow this syntax:
4367 * windowHashcode extra
4368 *
4369 * Where XX is the length in characeters of the windowTitle.
4370 *
4371 * The first parameter is the target window. The window with the specified hashcode
4372 * will be the target. If no target can be found, nothing happens. The extra parameters
4373 * will be delivered to the target window and as parameters to the command itself.
4374 *
4375 * @param client The remote client to sent the result, if any, to.
4376 * @param command The command to execute.
4377 * @param parameters The command parameters.
4378 *
4379 * @return True if the command was successfully delivered, false otherwise. This does
4380 * not indicate whether the command itself was successful.
4381 */
4382 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
Romain Guy06882f82009-06-10 13:36:04 -07004383 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 return false;
4385 }
4386
4387 boolean success = true;
4388 Parcel data = null;
4389 Parcel reply = null;
4390
4391 // Any uncaught exception will crash the system process
4392 try {
4393 // Find the hashcode of the window
4394 int index = parameters.indexOf(' ');
4395 if (index == -1) {
4396 index = parameters.length();
4397 }
4398 final String code = parameters.substring(0, index);
4399 int hashCode = "ffffffff".equals(code) ? -1 : Integer.parseInt(code, 16);
4400
4401 // Extract the command's parameter after the window description
4402 if (index < parameters.length()) {
4403 parameters = parameters.substring(index + 1);
4404 } else {
4405 parameters = "";
4406 }
4407
4408 final WindowManagerService.WindowState window = findWindow(hashCode);
4409 if (window == null) {
4410 return false;
4411 }
4412
4413 data = Parcel.obtain();
4414 data.writeInterfaceToken("android.view.IWindow");
4415 data.writeString(command);
4416 data.writeString(parameters);
4417 data.writeInt(1);
4418 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4419
4420 reply = Parcel.obtain();
4421
4422 final IBinder binder = window.mClient.asBinder();
4423 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4424 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4425
4426 reply.readException();
4427
4428 } catch (Exception e) {
4429 Log.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
4430 success = false;
4431 } finally {
4432 if (data != null) {
4433 data.recycle();
4434 }
4435 if (reply != null) {
4436 reply.recycle();
4437 }
4438 }
4439
4440 return success;
4441 }
4442
4443 private WindowState findWindow(int hashCode) {
4444 if (hashCode == -1) {
4445 return getFocusedWindow();
4446 }
4447
4448 synchronized (mWindowMap) {
4449 final ArrayList windows = mWindows;
4450 final int count = windows.size();
4451
4452 for (int i = 0; i < count; i++) {
4453 WindowState w = (WindowState) windows.get(i);
4454 if (System.identityHashCode(w) == hashCode) {
4455 return w;
4456 }
4457 }
4458 }
4459
4460 return null;
4461 }
4462
4463 /*
4464 * Instruct the Activity Manager to fetch the current configuration and broadcast
4465 * that to config-changed listeners if appropriate.
4466 */
4467 void sendNewConfiguration() {
4468 try {
4469 mActivityManager.updateConfiguration(null);
4470 } catch (RemoteException e) {
4471 }
4472 }
Romain Guy06882f82009-06-10 13:36:04 -07004473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004474 public Configuration computeNewConfiguration() {
4475 synchronized (mWindowMap) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07004476 return computeNewConfigurationLocked();
4477 }
4478 }
Romain Guy06882f82009-06-10 13:36:04 -07004479
Dianne Hackbornc485a602009-03-24 22:39:49 -07004480 Configuration computeNewConfigurationLocked() {
4481 Configuration config = new Configuration();
4482 if (!computeNewConfigurationLocked(config)) {
4483 return null;
4484 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07004485 return config;
4486 }
Romain Guy06882f82009-06-10 13:36:04 -07004487
Dianne Hackbornc485a602009-03-24 22:39:49 -07004488 boolean computeNewConfigurationLocked(Configuration config) {
4489 if (mDisplay == null) {
4490 return false;
4491 }
4492 mQueue.getInputConfiguration(config);
4493 final int dw = mDisplay.getWidth();
4494 final int dh = mDisplay.getHeight();
4495 int orientation = Configuration.ORIENTATION_SQUARE;
4496 if (dw < dh) {
4497 orientation = Configuration.ORIENTATION_PORTRAIT;
4498 } else if (dw > dh) {
4499 orientation = Configuration.ORIENTATION_LANDSCAPE;
4500 }
4501 config.orientation = orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004502
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07004503 DisplayMetrics dm = new DisplayMetrics();
4504 mDisplay.getMetrics(dm);
4505 CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
4506
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004507 if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07004508 // Note we only do this once because at this point we don't
4509 // expect the screen to change in this way at runtime, and want
4510 // to avoid all of this computation for every config change.
Dianne Hackborn723738c2009-06-25 19:48:04 -07004511 int longSize = dw;
4512 int shortSize = dh;
4513 if (longSize < shortSize) {
4514 int tmp = longSize;
4515 longSize = shortSize;
4516 shortSize = tmp;
4517 }
4518 longSize = (int)(longSize/dm.density);
4519 shortSize = (int)(shortSize/dm.density);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07004520
Dianne Hackborn723738c2009-06-25 19:48:04 -07004521 // These semi-magic numbers define our compatibility modes for
4522 // applications with different screens. Don't change unless you
4523 // make sure to test lots and lots of apps!
4524 if (longSize < 470) {
4525 // This is shorter than an HVGA normal density screen (which
4526 // is 480 pixels on its long side).
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004527 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
4528 | Configuration.SCREENLAYOUT_LONG_NO;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004529 } else {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004530 // Is this a large screen?
4531 if (longSize > 640 && shortSize >= 480) {
4532 // VGA or larger screens at medium density are the point
4533 // at which we consider it to be a large screen.
4534 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
4535 } else {
4536 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
4537
4538 // If this screen is wider than normal HVGA, or taller
4539 // than FWVGA, then for old apps we want to run in size
4540 // compatibility mode.
4541 if (shortSize > 321 || longSize > 570) {
4542 mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
4543 }
4544 }
4545
4546 // Is this a long screen?
4547 if (((longSize*3)/5) >= (shortSize-1)) {
4548 // Anything wider than WVGA (5:3) is considering to be long.
4549 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
4550 } else {
4551 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
4552 }
Dianne Hackborn723738c2009-06-25 19:48:04 -07004553 }
4554 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004555 config.screenLayout = mScreenLayout;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004556
Dianne Hackbornc485a602009-03-24 22:39:49 -07004557 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
4558 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
4559 mPolicy.adjustConfigurationLw(config);
4560 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 }
Romain Guy06882f82009-06-10 13:36:04 -07004562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004563 // -------------------------------------------------------------
4564 // Input Events and Focus Management
4565 // -------------------------------------------------------------
4566
4567 private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
Michael Chane96440f2009-05-06 10:27:36 -07004568 long curTime = SystemClock.uptimeMillis();
4569
Michael Chane10de972009-05-18 11:24:50 -07004570 if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
Michael Chane96440f2009-05-06 10:27:36 -07004571 if (mLastTouchEventType == eventType &&
4572 (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
4573 return;
4574 }
4575 mLastUserActivityCallTime = curTime;
4576 mLastTouchEventType = eventType;
4577 }
4578
4579 if (targetWin == null
4580 || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
4581 mPowerManager.userActivity(curTime, false, eventType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004582 }
4583 }
4584
4585 // tells if it's a cheek event or not -- this function is stateful
4586 private static final int EVENT_NONE = 0;
4587 private static final int EVENT_UNKNOWN = 0;
4588 private static final int EVENT_CHEEK = 0;
4589 private static final int EVENT_IGNORE_DURATION = 300; // ms
4590 private static final float CHEEK_THRESHOLD = 0.6f;
4591 private int mEventState = EVENT_NONE;
4592 private float mEventSize;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07004593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 private int eventType(MotionEvent ev) {
4595 float size = ev.getSize();
4596 switch (ev.getAction()) {
4597 case MotionEvent.ACTION_DOWN:
4598 mEventSize = size;
4599 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT;
4600 case MotionEvent.ACTION_UP:
4601 if (size > mEventSize) mEventSize = size;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07004602 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004603 case MotionEvent.ACTION_MOVE:
4604 final int N = ev.getHistorySize();
4605 if (size > mEventSize) mEventSize = size;
4606 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
4607 for (int i=0; i<N; i++) {
4608 size = ev.getHistoricalSize(i);
4609 if (size > mEventSize) mEventSize = size;
4610 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
4611 }
4612 if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) {
4613 return TOUCH_EVENT;
4614 } else {
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07004615 return LONG_TOUCH_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004616 }
4617 default:
4618 // not good
4619 return OTHER_EVENT;
4620 }
4621 }
4622
4623 /**
4624 * @return Returns true if event was dispatched, false if it was dropped for any reason
4625 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07004626 private int dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Log.v(TAG,
4628 "dispatchPointer " + ev);
4629
Michael Chan53071d62009-05-13 17:29:48 -07004630 if (MEASURE_LATENCY) {
4631 lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
4632 }
4633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004634 Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004635 ev, true, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004636
Michael Chan53071d62009-05-13 17:29:48 -07004637 if (MEASURE_LATENCY) {
4638 lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
4639 }
4640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004641 int action = ev.getAction();
Romain Guy06882f82009-06-10 13:36:04 -07004642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 if (action == MotionEvent.ACTION_UP) {
4644 // let go of our target
4645 mKeyWaiter.mMotionTarget = null;
4646 mPowerManager.logPointerUpEvent();
4647 } else if (action == MotionEvent.ACTION_DOWN) {
4648 mPowerManager.logPointerDownEvent();
4649 }
4650
4651 if (targetObj == null) {
4652 // In this case we are either dropping the event, or have received
4653 // a move or up without a down. It is common to receive move
4654 // events in such a way, since this means the user is moving the
4655 // pointer without actually pressing down. All other cases should
4656 // be atypical, so let's log them.
Michael Chane96440f2009-05-06 10:27:36 -07004657 if (action != MotionEvent.ACTION_MOVE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004658 Log.w(TAG, "No window to dispatch pointer action " + ev.getAction());
4659 }
4660 if (qev != null) {
4661 mQueue.recycleEvent(qev);
4662 }
4663 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004664 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004665 }
4666 if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
4667 if (qev != null) {
4668 mQueue.recycleEvent(qev);
4669 }
4670 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004671 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004672 }
Romain Guy06882f82009-06-10 13:36:04 -07004673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004674 WindowState target = (WindowState)targetObj;
Romain Guy06882f82009-06-10 13:36:04 -07004675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004676 final long eventTime = ev.getEventTime();
Michael Chan53071d62009-05-13 17:29:48 -07004677 final long eventTimeNano = ev.getEventTimeNano();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004678
4679 //Log.i(TAG, "Sending " + ev + " to " + target);
4680
4681 if (uid != 0 && uid != target.mSession.mUid) {
4682 if (mContext.checkPermission(
4683 android.Manifest.permission.INJECT_EVENTS, pid, uid)
4684 != PackageManager.PERMISSION_GRANTED) {
4685 Log.w(TAG, "Permission denied: injecting pointer event from pid "
4686 + pid + " uid " + uid + " to window " + target
4687 + " owned by uid " + target.mSession.mUid);
4688 if (qev != null) {
4689 mQueue.recycleEvent(qev);
4690 }
4691 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004692 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004693 }
4694 }
4695
Michael Chan53071d62009-05-13 17:29:48 -07004696 if (MEASURE_LATENCY) {
4697 lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano);
4698 }
4699
Romain Guy06882f82009-06-10 13:36:04 -07004700 if ((target.mAttrs.flags &
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004701 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
4702 //target wants to ignore fat touch events
4703 boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev);
4704 //explicit flag to return without processing event further
4705 boolean returnFlag = false;
4706 if((action == MotionEvent.ACTION_DOWN)) {
4707 mFatTouch = false;
4708 if(cheekPress) {
4709 mFatTouch = true;
4710 returnFlag = true;
4711 }
4712 } else {
4713 if(action == MotionEvent.ACTION_UP) {
4714 if(mFatTouch) {
4715 //earlier even was invalid doesnt matter if current up is cheekpress or not
4716 mFatTouch = false;
4717 returnFlag = true;
4718 } else if(cheekPress) {
4719 //cancel the earlier event
4720 ev.setAction(MotionEvent.ACTION_CANCEL);
4721 action = MotionEvent.ACTION_CANCEL;
4722 }
4723 } else if(action == MotionEvent.ACTION_MOVE) {
4724 if(mFatTouch) {
4725 //two cases here
4726 //an invalid down followed by 0 or moves(valid or invalid)
Romain Guy06882f82009-06-10 13:36:04 -07004727 //a valid down, invalid move, more moves. want to ignore till up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004728 returnFlag = true;
4729 } else if(cheekPress) {
4730 //valid down followed by invalid moves
4731 //an invalid move have to cancel earlier action
4732 ev.setAction(MotionEvent.ACTION_CANCEL);
4733 action = MotionEvent.ACTION_CANCEL;
4734 if (DEBUG_INPUT) Log.v(TAG, "Sending cancel for invalid ACTION_MOVE");
4735 //note that the subsequent invalid moves will not get here
4736 mFatTouch = true;
4737 }
4738 }
4739 } //else if action
4740 if(returnFlag) {
4741 //recycle que, ev
4742 if (qev != null) {
4743 mQueue.recycleEvent(qev);
4744 }
4745 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004746 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004747 }
4748 } //end if target
Michael Chane96440f2009-05-06 10:27:36 -07004749
Michael Chan9f028e62009-08-04 17:37:46 -07004750 // Enable this for testing the "right" value
4751 if (false && action == MotionEvent.ACTION_DOWN) {
Michael Chane96440f2009-05-06 10:27:36 -07004752 int max_events_per_sec = 35;
4753 try {
4754 max_events_per_sec = Integer.parseInt(SystemProperties
4755 .get("windowsmgr.max_events_per_sec"));
4756 if (max_events_per_sec < 1) {
4757 max_events_per_sec = 35;
4758 }
4759 } catch (NumberFormatException e) {
4760 }
4761 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
4762 }
4763
4764 /*
4765 * Throttle events to minimize CPU usage when there's a flood of events
4766 * e.g. constant contact with the screen
4767 */
4768 if (action == MotionEvent.ACTION_MOVE) {
4769 long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents;
4770 long now = SystemClock.uptimeMillis();
4771 if (now < nextEventTime) {
4772 try {
4773 Thread.sleep(nextEventTime - now);
4774 } catch (InterruptedException e) {
4775 }
4776 mLastTouchEventTime = nextEventTime;
4777 } else {
4778 mLastTouchEventTime = now;
4779 }
4780 }
4781
Michael Chan53071d62009-05-13 17:29:48 -07004782 if (MEASURE_LATENCY) {
4783 lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano);
4784 }
4785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004786 synchronized(mWindowMap) {
4787 if (qev != null && action == MotionEvent.ACTION_MOVE) {
4788 mKeyWaiter.bindTargetWindowLocked(target,
4789 KeyWaiter.RETURN_PENDING_POINTER, qev);
4790 ev = null;
4791 } else {
4792 if (action == MotionEvent.ACTION_DOWN) {
4793 WindowState out = mKeyWaiter.mOutsideTouchTargets;
4794 if (out != null) {
4795 MotionEvent oev = MotionEvent.obtain(ev);
4796 oev.setAction(MotionEvent.ACTION_OUTSIDE);
4797 do {
4798 final Rect frame = out.mFrame;
4799 oev.offsetLocation(-(float)frame.left, -(float)frame.top);
4800 try {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07004801 out.mClient.dispatchPointer(oev, eventTime, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004802 } catch (android.os.RemoteException e) {
4803 Log.i(TAG, "WINDOW DIED during outside motion dispatch: " + out);
4804 }
4805 oev.offsetLocation((float)frame.left, (float)frame.top);
4806 out = out.mNextOutsideTouch;
4807 } while (out != null);
4808 mKeyWaiter.mOutsideTouchTargets = null;
4809 }
4810 }
4811 final Rect frame = target.mFrame;
4812 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
4813 mKeyWaiter.bindTargetWindowLocked(target);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07004814
4815 // If we are on top of the wallpaper, then the wallpaper also
4816 // gets to see this movement.
4817 if (mWallpaperTarget == target) {
4818 sendPointerToWallpaperLocked(target, ev, eventTime);
4819 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004820 }
4821 }
Romain Guy06882f82009-06-10 13:36:04 -07004822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004823 // finally offset the event to the target's coordinate system and
4824 // dispatch the event.
4825 try {
4826 if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
4827 Log.v(TAG, "Delivering pointer " + qev + " to " + target);
4828 }
Michael Chan53071d62009-05-13 17:29:48 -07004829
4830 if (MEASURE_LATENCY) {
4831 lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
4832 }
4833
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07004834 target.mClient.dispatchPointer(ev, eventTime, true);
Michael Chan53071d62009-05-13 17:29:48 -07004835
4836 if (MEASURE_LATENCY) {
4837 lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
4838 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07004839 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004840 } catch (android.os.RemoteException e) {
4841 Log.i(TAG, "WINDOW DIED during motion dispatch: " + target);
4842 mKeyWaiter.mMotionTarget = null;
4843 try {
4844 removeWindow(target.mSession, target.mClient);
4845 } catch (java.util.NoSuchElementException ex) {
4846 // This will happen if the window has already been
4847 // removed.
4848 }
4849 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07004850 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004851 }
Romain Guy06882f82009-06-10 13:36:04 -07004852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004853 /**
4854 * @return Returns true if event was dispatched, false if it was dropped for any reason
4855 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07004856 private int dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857 if (DEBUG_INPUT) Log.v(
4858 TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">");
Romain Guy06882f82009-06-10 13:36:04 -07004859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004860 Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004861 ev, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004862 if (focusObj == null) {
4863 Log.w(TAG, "No focus window, dropping trackball: " + ev);
4864 if (qev != null) {
4865 mQueue.recycleEvent(qev);
4866 }
4867 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004868 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004869 }
4870 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
4871 if (qev != null) {
4872 mQueue.recycleEvent(qev);
4873 }
4874 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004875 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004876 }
Romain Guy06882f82009-06-10 13:36:04 -07004877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004878 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07004879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 if (uid != 0 && uid != focus.mSession.mUid) {
4881 if (mContext.checkPermission(
4882 android.Manifest.permission.INJECT_EVENTS, pid, uid)
4883 != PackageManager.PERMISSION_GRANTED) {
4884 Log.w(TAG, "Permission denied: injecting key event from pid "
4885 + pid + " uid " + uid + " to window " + focus
4886 + " owned by uid " + focus.mSession.mUid);
4887 if (qev != null) {
4888 mQueue.recycleEvent(qev);
4889 }
4890 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004891 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004892 }
4893 }
Romain Guy06882f82009-06-10 13:36:04 -07004894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004895 final long eventTime = ev.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07004896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004897 synchronized(mWindowMap) {
4898 if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) {
4899 mKeyWaiter.bindTargetWindowLocked(focus,
4900 KeyWaiter.RETURN_PENDING_TRACKBALL, qev);
4901 // We don't deliver movement events to the client, we hold
4902 // them and wait for them to call back.
4903 ev = null;
4904 } else {
4905 mKeyWaiter.bindTargetWindowLocked(focus);
4906 }
4907 }
Romain Guy06882f82009-06-10 13:36:04 -07004908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004909 try {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07004910 focus.mClient.dispatchTrackball(ev, eventTime, true);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004911 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004912 } catch (android.os.RemoteException e) {
4913 Log.i(TAG, "WINDOW DIED during key dispatch: " + focus);
4914 try {
4915 removeWindow(focus.mSession, focus.mClient);
4916 } catch (java.util.NoSuchElementException ex) {
4917 // This will happen if the window has already been
4918 // removed.
4919 }
4920 }
Romain Guy06882f82009-06-10 13:36:04 -07004921
Dianne Hackborncfaef692009-06-15 14:24:44 -07004922 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004923 }
Romain Guy06882f82009-06-10 13:36:04 -07004924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004925 /**
4926 * @return Returns true if event was dispatched, false if it was dropped for any reason
4927 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07004928 private int dispatchKey(KeyEvent event, int pid, int uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004929 if (DEBUG_INPUT) Log.v(TAG, "Dispatch key: " + event);
4930
4931 Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004932 null, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004933 if (focusObj == null) {
4934 Log.w(TAG, "No focus window, dropping: " + event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004935 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004936 }
4937 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004938 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004939 }
Romain Guy06882f82009-06-10 13:36:04 -07004940
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07004941 // Okay we have finished waiting for the last event to be processed.
4942 // First off, if this is a repeat event, check to see if there is
4943 // a corresponding up event in the queue. If there is, we will
4944 // just drop the repeat, because it makes no sense to repeat after
4945 // the user has released a key. (This is especially important for
4946 // long presses.)
4947 if (event.getRepeatCount() > 0 && mQueue.hasKeyUpEvent(event)) {
4948 return INJECT_SUCCEEDED;
4949 }
4950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004951 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07004952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004953 if (DEBUG_INPUT) Log.v(
4954 TAG, "Dispatching to " + focus + ": " + event);
4955
4956 if (uid != 0 && uid != focus.mSession.mUid) {
4957 if (mContext.checkPermission(
4958 android.Manifest.permission.INJECT_EVENTS, pid, uid)
4959 != PackageManager.PERMISSION_GRANTED) {
4960 Log.w(TAG, "Permission denied: injecting key event from pid "
4961 + pid + " uid " + uid + " to window " + focus
4962 + " owned by uid " + focus.mSession.mUid);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004963 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004964 }
4965 }
Romain Guy06882f82009-06-10 13:36:04 -07004966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004967 synchronized(mWindowMap) {
4968 mKeyWaiter.bindTargetWindowLocked(focus);
4969 }
4970
4971 // NOSHIP extra state logging
4972 mKeyWaiter.recordDispatchState(event, focus);
4973 // END NOSHIP
Romain Guy06882f82009-06-10 13:36:04 -07004974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004975 try {
4976 if (DEBUG_INPUT || DEBUG_FOCUS) {
4977 Log.v(TAG, "Delivering key " + event.getKeyCode()
4978 + " to " + focus);
4979 }
4980 focus.mClient.dispatchKey(event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07004981 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004982 } catch (android.os.RemoteException e) {
4983 Log.i(TAG, "WINDOW DIED during key dispatch: " + focus);
4984 try {
4985 removeWindow(focus.mSession, focus.mClient);
4986 } catch (java.util.NoSuchElementException ex) {
4987 // This will happen if the window has already been
4988 // removed.
4989 }
4990 }
Romain Guy06882f82009-06-10 13:36:04 -07004991
Dianne Hackborncfaef692009-06-15 14:24:44 -07004992 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004993 }
Romain Guy06882f82009-06-10 13:36:04 -07004994
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004995 public void pauseKeyDispatching(IBinder _token) {
4996 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4997 "pauseKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004998 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 }
5000
5001 synchronized (mWindowMap) {
5002 WindowToken token = mTokenMap.get(_token);
5003 if (token != null) {
5004 mKeyWaiter.pauseDispatchingLocked(token);
5005 }
5006 }
5007 }
5008
5009 public void resumeKeyDispatching(IBinder _token) {
5010 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5011 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005012 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005013 }
5014
5015 synchronized (mWindowMap) {
5016 WindowToken token = mTokenMap.get(_token);
5017 if (token != null) {
5018 mKeyWaiter.resumeDispatchingLocked(token);
5019 }
5020 }
5021 }
5022
5023 public void setEventDispatching(boolean enabled) {
5024 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5025 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005026 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005027 }
5028
5029 synchronized (mWindowMap) {
5030 mKeyWaiter.setEventDispatchingLocked(enabled);
5031 }
5032 }
Romain Guy06882f82009-06-10 13:36:04 -07005033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005034 /**
5035 * Injects a keystroke event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005036 *
5037 * @param ev A motion event describing the keystroke action. (Be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 * {@link SystemClock#uptimeMillis()} as the timebase.)
5039 * @param sync If true, wait for the event to be completed before returning to the caller.
5040 * @return Returns true if event was dispatched, false if it was dropped for any reason
5041 */
5042 public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
5043 long downTime = ev.getDownTime();
5044 long eventTime = ev.getEventTime();
5045
5046 int action = ev.getAction();
5047 int code = ev.getKeyCode();
5048 int repeatCount = ev.getRepeatCount();
5049 int metaState = ev.getMetaState();
5050 int deviceId = ev.getDeviceId();
5051 int scancode = ev.getScanCode();
5052
5053 if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
5054 if (downTime == 0) downTime = eventTime;
5055
5056 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
The Android Open Source Project10592532009-03-18 17:39:46 -07005057 deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005059 final int pid = Binder.getCallingPid();
5060 final int uid = Binder.getCallingUid();
5061 final long ident = Binder.clearCallingIdentity();
5062 final int result = dispatchKey(newEvent, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005064 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005066 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005067 switch (result) {
5068 case INJECT_NO_PERMISSION:
5069 throw new SecurityException(
5070 "Injecting to another application requires INJECT_EVENT permission");
5071 case INJECT_SUCCEEDED:
5072 return true;
5073 }
5074 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005075 }
5076
5077 /**
5078 * Inject a pointer (touch) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005079 *
5080 * @param ev A motion event describing the pointer (touch) action. (As noted in
5081 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005082 * {@link SystemClock#uptimeMillis()} as the timebase.)
5083 * @param sync If true, wait for the event to be completed before returning to the caller.
5084 * @return Returns true if event was dispatched, false if it was dropped for any reason
5085 */
5086 public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005087 final int pid = Binder.getCallingPid();
5088 final int uid = Binder.getCallingUid();
5089 final long ident = Binder.clearCallingIdentity();
5090 final int result = dispatchPointer(null, ev, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005091 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005092 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005094 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005095 switch (result) {
5096 case INJECT_NO_PERMISSION:
5097 throw new SecurityException(
5098 "Injecting to another application requires INJECT_EVENT permission");
5099 case INJECT_SUCCEEDED:
5100 return true;
5101 }
5102 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005103 }
Romain Guy06882f82009-06-10 13:36:04 -07005104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005105 /**
5106 * Inject a trackball (navigation device) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005107 *
5108 * @param ev A motion event describing the trackball action. (As noted in
5109 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 * {@link SystemClock#uptimeMillis()} as the timebase.)
5111 * @param sync If true, wait for the event to be completed before returning to the caller.
5112 * @return Returns true if event was dispatched, false if it was dropped for any reason
5113 */
5114 public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005115 final int pid = Binder.getCallingPid();
5116 final int uid = Binder.getCallingUid();
5117 final long ident = Binder.clearCallingIdentity();
5118 final int result = dispatchTrackball(null, ev, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005120 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005122 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005123 switch (result) {
5124 case INJECT_NO_PERMISSION:
5125 throw new SecurityException(
5126 "Injecting to another application requires INJECT_EVENT permission");
5127 case INJECT_SUCCEEDED:
5128 return true;
5129 }
5130 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005131 }
Romain Guy06882f82009-06-10 13:36:04 -07005132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005133 private WindowState getFocusedWindow() {
5134 synchronized (mWindowMap) {
5135 return getFocusedWindowLocked();
5136 }
5137 }
5138
5139 private WindowState getFocusedWindowLocked() {
5140 return mCurrentFocus;
5141 }
Romain Guy06882f82009-06-10 13:36:04 -07005142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 /**
5144 * This class holds the state for dispatching key events. This state
5145 * is protected by the KeyWaiter instance, NOT by the window lock. You
5146 * can be holding the main window lock while acquire the KeyWaiter lock,
5147 * but not the other way around.
5148 */
5149 final class KeyWaiter {
5150 // NOSHIP debugging
5151 public class DispatchState {
5152 private KeyEvent event;
5153 private WindowState focus;
5154 private long time;
5155 private WindowState lastWin;
5156 private IBinder lastBinder;
5157 private boolean finished;
5158 private boolean gotFirstWindow;
5159 private boolean eventDispatching;
5160 private long timeToSwitch;
5161 private boolean wasFrozen;
5162 private boolean focusPaused;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005163 private WindowState curFocus;
Romain Guy06882f82009-06-10 13:36:04 -07005164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 DispatchState(KeyEvent theEvent, WindowState theFocus) {
5166 focus = theFocus;
5167 event = theEvent;
5168 time = System.currentTimeMillis();
5169 // snapshot KeyWaiter state
5170 lastWin = mLastWin;
5171 lastBinder = mLastBinder;
5172 finished = mFinished;
5173 gotFirstWindow = mGotFirstWindow;
5174 eventDispatching = mEventDispatching;
5175 timeToSwitch = mTimeToSwitch;
5176 wasFrozen = mWasFrozen;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005177 curFocus = mCurrentFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005178 // cache the paused state at ctor time as well
5179 if (theFocus == null || theFocus.mToken == null) {
5180 Log.i(TAG, "focus " + theFocus + " mToken is null at event dispatch!");
5181 focusPaused = false;
5182 } else {
5183 focusPaused = theFocus.mToken.paused;
5184 }
5185 }
Romain Guy06882f82009-06-10 13:36:04 -07005186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005187 public String toString() {
5188 return "{{" + event + " to " + focus + " @ " + time
5189 + " lw=" + lastWin + " lb=" + lastBinder
5190 + " fin=" + finished + " gfw=" + gotFirstWindow
5191 + " ed=" + eventDispatching + " tts=" + timeToSwitch
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005192 + " wf=" + wasFrozen + " fp=" + focusPaused
5193 + " mcf=" + mCurrentFocus + "}}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005194 }
5195 };
5196 private DispatchState mDispatchState = null;
5197 public void recordDispatchState(KeyEvent theEvent, WindowState theFocus) {
5198 mDispatchState = new DispatchState(theEvent, theFocus);
5199 }
5200 // END NOSHIP
5201
5202 public static final int RETURN_NOTHING = 0;
5203 public static final int RETURN_PENDING_POINTER = 1;
5204 public static final int RETURN_PENDING_TRACKBALL = 2;
Romain Guy06882f82009-06-10 13:36:04 -07005205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 final Object SKIP_TARGET_TOKEN = new Object();
5207 final Object CONSUMED_EVENT_TOKEN = new Object();
Romain Guy06882f82009-06-10 13:36:04 -07005208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005209 private WindowState mLastWin = null;
5210 private IBinder mLastBinder = null;
5211 private boolean mFinished = true;
5212 private boolean mGotFirstWindow = false;
5213 private boolean mEventDispatching = true;
5214 private long mTimeToSwitch = 0;
5215 /* package */ boolean mWasFrozen = false;
Romain Guy06882f82009-06-10 13:36:04 -07005216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005217 // Target of Motion events
5218 WindowState mMotionTarget;
Romain Guy06882f82009-06-10 13:36:04 -07005219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005220 // Windows above the target who would like to receive an "outside"
5221 // touch event for any down events outside of them.
5222 WindowState mOutsideTouchTargets;
5223
5224 /**
5225 * Wait for the last event dispatch to complete, then find the next
5226 * target that should receive the given event and wait for that one
5227 * to be ready to receive it.
5228 */
5229 Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev,
5230 MotionEvent nextMotion, boolean isPointerEvent,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005231 boolean failIfTimeout, int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005232 long startTime = SystemClock.uptimeMillis();
5233 long keyDispatchingTimeout = 5 * 1000;
5234 long waitedFor = 0;
5235
5236 while (true) {
5237 // Figure out which window we care about. It is either the
5238 // last window we are waiting to have process the event or,
5239 // if none, then the next window we think the event should go
5240 // to. Note: we retrieve mLastWin outside of the lock, so
5241 // it may change before we lock. Thus we must check it again.
5242 WindowState targetWin = mLastWin;
5243 boolean targetIsNew = targetWin == null;
5244 if (DEBUG_INPUT) Log.v(
5245 TAG, "waitForLastKey: mFinished=" + mFinished +
5246 ", mLastWin=" + mLastWin);
5247 if (targetIsNew) {
5248 Object target = findTargetWindow(nextKey, qev, nextMotion,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005249 isPointerEvent, callingPid, callingUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005250 if (target == SKIP_TARGET_TOKEN) {
5251 // The user has pressed a special key, and we are
5252 // dropping all pending events before it.
5253 if (DEBUG_INPUT) Log.v(TAG, "Skipping: " + nextKey
5254 + " " + nextMotion);
5255 return null;
5256 }
5257 if (target == CONSUMED_EVENT_TOKEN) {
5258 if (DEBUG_INPUT) Log.v(TAG, "Consumed: " + nextKey
5259 + " " + nextMotion);
5260 return target;
5261 }
5262 targetWin = (WindowState)target;
5263 }
Romain Guy06882f82009-06-10 13:36:04 -07005264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005265 AppWindowToken targetApp = null;
Romain Guy06882f82009-06-10 13:36:04 -07005266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005267 // Now: is it okay to send the next event to this window?
5268 synchronized (this) {
5269 // First: did we come here based on the last window not
5270 // being null, but it changed by the time we got here?
5271 // If so, try again.
5272 if (!targetIsNew && mLastWin == null) {
5273 continue;
5274 }
Romain Guy06882f82009-06-10 13:36:04 -07005275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 // We never dispatch events if not finished with the
5277 // last one, or the display is frozen.
5278 if (mFinished && !mDisplayFrozen) {
5279 // If event dispatching is disabled, then we
5280 // just consume the events.
5281 if (!mEventDispatching) {
5282 if (DEBUG_INPUT) Log.v(TAG,
5283 "Skipping event; dispatching disabled: "
5284 + nextKey + " " + nextMotion);
5285 return null;
5286 }
5287 if (targetWin != null) {
5288 // If this is a new target, and that target is not
5289 // paused or unresponsive, then all looks good to
5290 // handle the event.
5291 if (targetIsNew && !targetWin.mToken.paused) {
5292 return targetWin;
5293 }
Romain Guy06882f82009-06-10 13:36:04 -07005294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005295 // If we didn't find a target window, and there is no
5296 // focused app window, then just eat the events.
5297 } else if (mFocusedApp == null) {
5298 if (DEBUG_INPUT) Log.v(TAG,
5299 "Skipping event; no focused app: "
5300 + nextKey + " " + nextMotion);
5301 return null;
5302 }
5303 }
Romain Guy06882f82009-06-10 13:36:04 -07005304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 if (DEBUG_INPUT) Log.v(
5306 TAG, "Waiting for last key in " + mLastBinder
5307 + " target=" + targetWin
5308 + " mFinished=" + mFinished
5309 + " mDisplayFrozen=" + mDisplayFrozen
5310 + " targetIsNew=" + targetIsNew
5311 + " paused="
5312 + (targetWin != null ? targetWin.mToken.paused : false)
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005313 + " mFocusedApp=" + mFocusedApp
5314 + " mCurrentFocus=" + mCurrentFocus);
Romain Guy06882f82009-06-10 13:36:04 -07005315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005316 targetApp = targetWin != null
5317 ? targetWin.mAppToken : mFocusedApp;
Romain Guy06882f82009-06-10 13:36:04 -07005318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005319 long curTimeout = keyDispatchingTimeout;
5320 if (mTimeToSwitch != 0) {
5321 long now = SystemClock.uptimeMillis();
5322 if (mTimeToSwitch <= now) {
5323 // If an app switch key has been pressed, and we have
5324 // waited too long for the current app to finish
5325 // processing keys, then wait no more!
5326 doFinishedKeyLocked(true);
5327 continue;
5328 }
5329 long switchTimeout = mTimeToSwitch - now;
5330 if (curTimeout > switchTimeout) {
5331 curTimeout = switchTimeout;
5332 }
5333 }
Romain Guy06882f82009-06-10 13:36:04 -07005334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 try {
5336 // after that continue
5337 // processing keys, so we don't get stuck.
5338 if (DEBUG_INPUT) Log.v(
5339 TAG, "Waiting for key dispatch: " + curTimeout);
5340 wait(curTimeout);
5341 if (DEBUG_INPUT) Log.v(TAG, "Finished waiting @"
5342 + SystemClock.uptimeMillis() + " startTime="
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005343 + startTime + " switchTime=" + mTimeToSwitch
5344 + " target=" + targetWin + " mLW=" + mLastWin
5345 + " mLB=" + mLastBinder + " fin=" + mFinished
5346 + " mCurrentFocus=" + mCurrentFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005347 } catch (InterruptedException e) {
5348 }
5349 }
5350
5351 // If we were frozen during configuration change, restart the
5352 // timeout checks from now; otherwise look at whether we timed
5353 // out before awakening.
5354 if (mWasFrozen) {
5355 waitedFor = 0;
5356 mWasFrozen = false;
5357 } else {
5358 waitedFor = SystemClock.uptimeMillis() - startTime;
5359 }
5360
5361 if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) {
5362 IApplicationToken at = null;
5363 synchronized (this) {
5364 Log.w(TAG, "Key dispatching timed out sending to " +
5365 (targetWin != null ? targetWin.mAttrs.getTitle()
5366 : "<null>"));
5367 // NOSHIP debugging
5368 Log.w(TAG, "Dispatch state: " + mDispatchState);
5369 Log.w(TAG, "Current state: " + new DispatchState(nextKey, targetWin));
5370 // END NOSHIP
5371 //dump();
5372 if (targetWin != null) {
5373 at = targetWin.getAppToken();
5374 } else if (targetApp != null) {
5375 at = targetApp.appToken;
5376 }
5377 }
5378
5379 boolean abort = true;
5380 if (at != null) {
5381 try {
5382 long timeout = at.getKeyDispatchingTimeout();
5383 if (timeout > waitedFor) {
5384 // we did not wait the proper amount of time for this application.
5385 // set the timeout to be the real timeout and wait again.
5386 keyDispatchingTimeout = timeout - waitedFor;
5387 continue;
5388 } else {
5389 abort = at.keyDispatchingTimedOut();
5390 }
5391 } catch (RemoteException ex) {
5392 }
5393 }
5394
5395 synchronized (this) {
5396 if (abort && (mLastWin == targetWin || targetWin == null)) {
5397 mFinished = true;
Romain Guy06882f82009-06-10 13:36:04 -07005398 if (mLastWin != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005399 if (DEBUG_INPUT) Log.v(TAG,
5400 "Window " + mLastWin +
5401 " timed out on key input");
5402 if (mLastWin.mToken.paused) {
5403 Log.w(TAG, "Un-pausing dispatching to this window");
5404 mLastWin.mToken.paused = false;
5405 }
5406 }
5407 if (mMotionTarget == targetWin) {
5408 mMotionTarget = null;
5409 }
5410 mLastWin = null;
5411 mLastBinder = null;
5412 if (failIfTimeout || targetWin == null) {
5413 return null;
5414 }
5415 } else {
5416 Log.w(TAG, "Continuing to wait for key to be dispatched");
5417 startTime = SystemClock.uptimeMillis();
5418 }
5419 }
5420 }
5421 }
5422 }
Romain Guy06882f82009-06-10 13:36:04 -07005423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005424 Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005425 MotionEvent nextMotion, boolean isPointerEvent,
5426 int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 mOutsideTouchTargets = null;
Romain Guy06882f82009-06-10 13:36:04 -07005428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 if (nextKey != null) {
5430 // Find the target window for a normal key event.
5431 final int keycode = nextKey.getKeyCode();
5432 final int repeatCount = nextKey.getRepeatCount();
5433 final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP;
5434 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode);
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 if (!dispatch) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005437 if (callingUid == 0 ||
5438 mContext.checkPermission(
5439 android.Manifest.permission.INJECT_EVENTS,
5440 callingPid, callingUid)
5441 == PackageManager.PERMISSION_GRANTED) {
5442 mPolicy.interceptKeyTi(null, keycode,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07005443 nextKey.getMetaState(), down, repeatCount,
5444 nextKey.getFlags());
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005445 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 Log.w(TAG, "Event timeout during app switch: dropping "
5447 + nextKey);
5448 return SKIP_TARGET_TOKEN;
5449 }
Romain Guy06882f82009-06-10 13:36:04 -07005450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")");
Romain Guy06882f82009-06-10 13:36:04 -07005452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005453 WindowState focus = null;
5454 synchronized(mWindowMap) {
5455 focus = getFocusedWindowLocked();
5456 }
Romain Guy06882f82009-06-10 13:36:04 -07005457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005458 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
Romain Guy06882f82009-06-10 13:36:04 -07005459
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005460 if (callingUid == 0 ||
5461 (focus != null && callingUid == focus.mSession.mUid) ||
5462 mContext.checkPermission(
5463 android.Manifest.permission.INJECT_EVENTS,
5464 callingPid, callingUid)
5465 == PackageManager.PERMISSION_GRANTED) {
5466 if (mPolicy.interceptKeyTi(focus,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07005467 keycode, nextKey.getMetaState(), down, repeatCount,
5468 nextKey.getFlags())) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005469 return CONSUMED_EVENT_TOKEN;
5470 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005471 }
Romain Guy06882f82009-06-10 13:36:04 -07005472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005473 return focus;
Romain Guy06882f82009-06-10 13:36:04 -07005474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005475 } else if (!isPointerEvent) {
5476 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1);
5477 if (!dispatch) {
5478 Log.w(TAG, "Event timeout during app switch: dropping trackball "
5479 + nextMotion);
5480 return SKIP_TARGET_TOKEN;
5481 }
Romain Guy06882f82009-06-10 13:36:04 -07005482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005483 WindowState focus = null;
5484 synchronized(mWindowMap) {
5485 focus = getFocusedWindowLocked();
5486 }
Romain Guy06882f82009-06-10 13:36:04 -07005487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
5489 return focus;
5490 }
Romain Guy06882f82009-06-10 13:36:04 -07005491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005492 if (nextMotion == null) {
5493 return SKIP_TARGET_TOKEN;
5494 }
Romain Guy06882f82009-06-10 13:36:04 -07005495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005496 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(
5497 KeyEvent.KEYCODE_UNKNOWN);
5498 if (!dispatch) {
5499 Log.w(TAG, "Event timeout during app switch: dropping pointer "
5500 + nextMotion);
5501 return SKIP_TARGET_TOKEN;
5502 }
Romain Guy06882f82009-06-10 13:36:04 -07005503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005504 // Find the target window for a pointer event.
5505 int action = nextMotion.getAction();
5506 final float xf = nextMotion.getX();
5507 final float yf = nextMotion.getY();
5508 final long eventTime = nextMotion.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07005509
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005510 final boolean screenWasOff = qev != null
5511 && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07005512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005513 WindowState target = null;
Romain Guy06882f82009-06-10 13:36:04 -07005514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005515 synchronized(mWindowMap) {
5516 synchronized (this) {
5517 if (action == MotionEvent.ACTION_DOWN) {
5518 if (mMotionTarget != null) {
5519 // this is weird, we got a pen down, but we thought it was
5520 // already down!
5521 // XXX: We should probably send an ACTION_UP to the current
5522 // target.
5523 Log.w(TAG, "Pointer down received while already down in: "
5524 + mMotionTarget);
5525 mMotionTarget = null;
5526 }
Romain Guy06882f82009-06-10 13:36:04 -07005527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005528 // ACTION_DOWN is special, because we need to lock next events to
5529 // the window we'll land onto.
5530 final int x = (int)xf;
5531 final int y = (int)yf;
Romain Guy06882f82009-06-10 13:36:04 -07005532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005533 final ArrayList windows = mWindows;
5534 final int N = windows.size();
5535 WindowState topErrWindow = null;
5536 final Rect tmpRect = mTempRect;
5537 for (int i=N-1; i>=0; i--) {
5538 WindowState child = (WindowState)windows.get(i);
5539 //Log.i(TAG, "Checking dispatch to: " + child);
5540 final int flags = child.mAttrs.flags;
5541 if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
5542 if (topErrWindow == null) {
5543 topErrWindow = child;
5544 }
5545 }
5546 if (!child.isVisibleLw()) {
5547 //Log.i(TAG, "Not visible!");
5548 continue;
5549 }
5550 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
5551 //Log.i(TAG, "Not touchable!");
5552 if ((flags & WindowManager.LayoutParams
5553 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5554 child.mNextOutsideTouch = mOutsideTouchTargets;
5555 mOutsideTouchTargets = child;
5556 }
5557 continue;
5558 }
5559 tmpRect.set(child.mFrame);
5560 if (child.mTouchableInsets == ViewTreeObserver
5561 .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
5562 // The touch is inside of the window if it is
5563 // inside the frame, AND the content part of that
5564 // frame that was given by the application.
5565 tmpRect.left += child.mGivenContentInsets.left;
5566 tmpRect.top += child.mGivenContentInsets.top;
5567 tmpRect.right -= child.mGivenContentInsets.right;
5568 tmpRect.bottom -= child.mGivenContentInsets.bottom;
5569 } else if (child.mTouchableInsets == ViewTreeObserver
5570 .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
5571 // The touch is inside of the window if it is
5572 // inside the frame, AND the visible part of that
5573 // frame that was given by the application.
5574 tmpRect.left += child.mGivenVisibleInsets.left;
5575 tmpRect.top += child.mGivenVisibleInsets.top;
5576 tmpRect.right -= child.mGivenVisibleInsets.right;
5577 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
5578 }
5579 final int touchFlags = flags &
5580 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5581 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
5582 if (tmpRect.contains(x, y) || touchFlags == 0) {
5583 //Log.i(TAG, "Using this target!");
5584 if (!screenWasOff || (flags &
5585 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
5586 mMotionTarget = child;
5587 } else {
5588 //Log.i(TAG, "Waking, skip!");
5589 mMotionTarget = null;
5590 }
5591 break;
5592 }
Romain Guy06882f82009-06-10 13:36:04 -07005593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005594 if ((flags & WindowManager.LayoutParams
5595 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5596 child.mNextOutsideTouch = mOutsideTouchTargets;
5597 mOutsideTouchTargets = child;
5598 //Log.i(TAG, "Adding to outside target list: " + child);
5599 }
5600 }
5601
5602 // if there's an error window but it's not accepting
5603 // focus (typically because it is not yet visible) just
5604 // wait for it -- any other focused window may in fact
5605 // be in ANR state.
5606 if (topErrWindow != null && mMotionTarget != topErrWindow) {
5607 mMotionTarget = null;
5608 }
5609 }
Romain Guy06882f82009-06-10 13:36:04 -07005610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005611 target = mMotionTarget;
5612 }
5613 }
Romain Guy06882f82009-06-10 13:36:04 -07005614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 wakeupIfNeeded(target, eventType(nextMotion));
Romain Guy06882f82009-06-10 13:36:04 -07005616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005617 // Pointer events are a little different -- if there isn't a
5618 // target found for any event, then just drop it.
5619 return target != null ? target : SKIP_TARGET_TOKEN;
5620 }
Romain Guy06882f82009-06-10 13:36:04 -07005621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 boolean checkShouldDispatchKey(int keycode) {
5623 synchronized (this) {
5624 if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) {
5625 mTimeToSwitch = 0;
5626 return true;
5627 }
5628 if (mTimeToSwitch != 0
5629 && mTimeToSwitch < SystemClock.uptimeMillis()) {
5630 return false;
5631 }
5632 return true;
5633 }
5634 }
Romain Guy06882f82009-06-10 13:36:04 -07005635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 void bindTargetWindowLocked(WindowState win,
5637 int pendingWhat, QueuedEvent pendingMotion) {
5638 synchronized (this) {
5639 bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion);
5640 }
5641 }
Romain Guy06882f82009-06-10 13:36:04 -07005642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005643 void bindTargetWindowLocked(WindowState win) {
5644 synchronized (this) {
5645 bindTargetWindowLockedLocked(win, RETURN_NOTHING, null);
5646 }
5647 }
5648
5649 void bindTargetWindowLockedLocked(WindowState win,
5650 int pendingWhat, QueuedEvent pendingMotion) {
5651 mLastWin = win;
5652 mLastBinder = win.mClient.asBinder();
5653 mFinished = false;
5654 if (pendingMotion != null) {
5655 final Session s = win.mSession;
5656 if (pendingWhat == RETURN_PENDING_POINTER) {
5657 releasePendingPointerLocked(s);
5658 s.mPendingPointerMove = pendingMotion;
5659 s.mPendingPointerWindow = win;
Romain Guy06882f82009-06-10 13:36:04 -07005660 if (DEBUG_INPUT) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005661 "bindTargetToWindow " + s.mPendingPointerMove);
5662 } else if (pendingWhat == RETURN_PENDING_TRACKBALL) {
5663 releasePendingTrackballLocked(s);
5664 s.mPendingTrackballMove = pendingMotion;
5665 s.mPendingTrackballWindow = win;
5666 }
5667 }
5668 }
Romain Guy06882f82009-06-10 13:36:04 -07005669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005670 void releasePendingPointerLocked(Session s) {
5671 if (DEBUG_INPUT) Log.v(TAG,
5672 "releasePendingPointer " + s.mPendingPointerMove);
5673 if (s.mPendingPointerMove != null) {
5674 mQueue.recycleEvent(s.mPendingPointerMove);
5675 s.mPendingPointerMove = null;
5676 }
5677 }
Romain Guy06882f82009-06-10 13:36:04 -07005678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005679 void releasePendingTrackballLocked(Session s) {
5680 if (s.mPendingTrackballMove != null) {
5681 mQueue.recycleEvent(s.mPendingTrackballMove);
5682 s.mPendingTrackballMove = null;
5683 }
5684 }
Romain Guy06882f82009-06-10 13:36:04 -07005685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005686 MotionEvent finishedKey(Session session, IWindow client, boolean force,
5687 int returnWhat) {
5688 if (DEBUG_INPUT) Log.v(
5689 TAG, "finishedKey: client=" + client + ", force=" + force);
5690
5691 if (client == null) {
5692 return null;
5693 }
5694
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005695 MotionEvent res = null;
5696 QueuedEvent qev = null;
5697 WindowState win = null;
5698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005699 synchronized (this) {
5700 if (DEBUG_INPUT) Log.v(
5701 TAG, "finishedKey: client=" + client.asBinder()
5702 + ", force=" + force + ", last=" + mLastBinder
5703 + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
5704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005705 if (returnWhat == RETURN_PENDING_POINTER) {
5706 qev = session.mPendingPointerMove;
5707 win = session.mPendingPointerWindow;
5708 session.mPendingPointerMove = null;
5709 session.mPendingPointerWindow = null;
5710 } else if (returnWhat == RETURN_PENDING_TRACKBALL) {
5711 qev = session.mPendingTrackballMove;
5712 win = session.mPendingTrackballWindow;
5713 session.mPendingTrackballMove = null;
5714 session.mPendingTrackballWindow = null;
5715 }
Romain Guy06882f82009-06-10 13:36:04 -07005716
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005717 if (mLastBinder == client.asBinder()) {
5718 if (DEBUG_INPUT) Log.v(
5719 TAG, "finishedKey: last paused="
5720 + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
5721 if (mLastWin != null && (!mLastWin.mToken.paused || force
5722 || !mEventDispatching)) {
5723 doFinishedKeyLocked(false);
5724 } else {
5725 // Make sure to wake up anyone currently waiting to
5726 // dispatch a key, so they can re-evaluate their
5727 // current situation.
5728 mFinished = true;
5729 notifyAll();
5730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005731 }
Romain Guy06882f82009-06-10 13:36:04 -07005732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005733 if (qev != null) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005734 res = (MotionEvent)qev.event;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005735 if (DEBUG_INPUT) Log.v(TAG,
5736 "Returning pending motion: " + res);
5737 mQueue.recycleEvent(qev);
5738 if (win != null && returnWhat == RETURN_PENDING_POINTER) {
5739 res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
5740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005742 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005743
5744 if (res != null && returnWhat == RETURN_PENDING_POINTER) {
5745 synchronized (mWindowMap) {
5746 if (mWallpaperTarget == win) {
5747 sendPointerToWallpaperLocked(win, res, res.getEventTime());
5748 }
5749 }
5750 }
5751
5752 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005753 }
5754
5755 void tickle() {
5756 synchronized (this) {
5757 notifyAll();
5758 }
5759 }
Romain Guy06882f82009-06-10 13:36:04 -07005760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005761 void handleNewWindowLocked(WindowState newWindow) {
5762 if (!newWindow.canReceiveKeys()) {
5763 return;
5764 }
5765 synchronized (this) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005766 if (DEBUG_INPUT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005767 TAG, "New key dispatch window: win="
5768 + newWindow.mClient.asBinder()
5769 + ", last=" + mLastBinder
5770 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
5771 + "), finished=" + mFinished + ", paused="
5772 + newWindow.mToken.paused);
5773
5774 // Displaying a window implicitly causes dispatching to
5775 // be unpaused. (This is to protect against bugs if someone
5776 // pauses dispatching but forgets to resume.)
5777 newWindow.mToken.paused = false;
5778
5779 mGotFirstWindow = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780
5781 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
5782 if (DEBUG_INPUT) Log.v(TAG,
5783 "New SYSTEM_ERROR window; resetting state");
5784 mLastWin = null;
5785 mLastBinder = null;
5786 mMotionTarget = null;
5787 mFinished = true;
5788 } else if (mLastWin != null) {
5789 // If the new window is above the window we are
5790 // waiting on, then stop waiting and let key dispatching
5791 // start on the new guy.
5792 if (DEBUG_INPUT) Log.v(
5793 TAG, "Last win layer=" + mLastWin.mLayer
5794 + ", new win layer=" + newWindow.mLayer);
5795 if (newWindow.mLayer >= mLastWin.mLayer) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005796 // The new window is above the old; finish pending input to the last
5797 // window and start directing it to the new one.
5798 mLastWin.mToken.paused = false;
5799 doFinishedKeyLocked(true); // does a notifyAll()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005800 }
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005801 // Either the new window is lower, so there is no need to wake key waiters,
5802 // or we just finished key input to the previous window, which implicitly
5803 // notified the key waiters. In both cases, we don't need to issue the
5804 // notification here.
5805 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 }
5807
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005808 // Now that we've put a new window state in place, make the event waiter
5809 // take notice and retarget its attentions.
5810 notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005811 }
5812 }
5813
5814 void pauseDispatchingLocked(WindowToken token) {
5815 synchronized (this)
5816 {
5817 if (DEBUG_INPUT) Log.v(TAG, "Pausing WindowToken " + token);
5818 token.paused = true;
5819
5820 /*
5821 if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) {
5822 mPaused = true;
5823 } else {
5824 if (mLastWin == null) {
Dave Bortcfe65242009-04-09 14:51:04 -07005825 Log.i(TAG, "Key dispatching not paused: no last window.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005826 } else if (mFinished) {
Dave Bortcfe65242009-04-09 14:51:04 -07005827 Log.i(TAG, "Key dispatching not paused: finished last key.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005828 } else {
Dave Bortcfe65242009-04-09 14:51:04 -07005829 Log.i(TAG, "Key dispatching not paused: window in higher layer.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005830 }
5831 }
5832 */
5833 }
5834 }
5835
5836 void resumeDispatchingLocked(WindowToken token) {
5837 synchronized (this) {
5838 if (token.paused) {
5839 if (DEBUG_INPUT) Log.v(
5840 TAG, "Resuming WindowToken " + token
5841 + ", last=" + mLastBinder
5842 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
5843 + "), finished=" + mFinished + ", paused="
5844 + token.paused);
5845 token.paused = false;
5846 if (mLastWin != null && mLastWin.mToken == token && mFinished) {
5847 doFinishedKeyLocked(true);
5848 } else {
5849 notifyAll();
5850 }
5851 }
5852 }
5853 }
5854
5855 void setEventDispatchingLocked(boolean enabled) {
5856 synchronized (this) {
5857 mEventDispatching = enabled;
5858 notifyAll();
5859 }
5860 }
Romain Guy06882f82009-06-10 13:36:04 -07005861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 void appSwitchComing() {
5863 synchronized (this) {
5864 // Don't wait for more than .5 seconds for app to finish
5865 // processing the pending events.
5866 long now = SystemClock.uptimeMillis() + 500;
5867 if (DEBUG_INPUT) Log.v(TAG, "appSwitchComing: " + now);
5868 if (mTimeToSwitch == 0 || now < mTimeToSwitch) {
5869 mTimeToSwitch = now;
5870 }
5871 notifyAll();
5872 }
5873 }
Romain Guy06882f82009-06-10 13:36:04 -07005874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005875 private final void doFinishedKeyLocked(boolean doRecycle) {
5876 if (mLastWin != null) {
5877 releasePendingPointerLocked(mLastWin.mSession);
5878 releasePendingTrackballLocked(mLastWin.mSession);
5879 }
Romain Guy06882f82009-06-10 13:36:04 -07005880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005881 if (mLastWin == null || !mLastWin.mToken.paused
5882 || !mLastWin.isVisibleLw()) {
5883 // If the current window has been paused, we aren't -really-
5884 // finished... so let the waiters still wait.
5885 mLastWin = null;
5886 mLastBinder = null;
5887 }
5888 mFinished = true;
5889 notifyAll();
5890 }
5891 }
5892
5893 private class KeyQ extends KeyInputQueue
5894 implements KeyInputQueue.FilterCallback {
5895 PowerManager.WakeLock mHoldingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07005896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005897 KeyQ() {
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07005898 super(mContext, WindowManagerService.this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005899 PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
5900 mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
5901 "KEEP_SCREEN_ON_FLAG");
5902 mHoldingScreen.setReferenceCounted(false);
5903 }
5904
5905 @Override
5906 boolean preprocessEvent(InputDevice device, RawInputEvent event) {
5907 if (mPolicy.preprocessInputEventTq(event)) {
5908 return true;
5909 }
Romain Guy06882f82009-06-10 13:36:04 -07005910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005911 switch (event.type) {
5912 case RawInputEvent.EV_KEY: {
5913 // XXX begin hack
5914 if (DEBUG) {
5915 if (event.keycode == KeyEvent.KEYCODE_G) {
5916 if (event.value != 0) {
5917 // G down
5918 mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
5919 }
5920 return false;
5921 }
5922 if (event.keycode == KeyEvent.KEYCODE_D) {
5923 if (event.value != 0) {
5924 //dump();
5925 }
5926 return false;
5927 }
5928 }
5929 // XXX end hack
Romain Guy06882f82009-06-10 13:36:04 -07005930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 boolean screenIsOff = !mPowerManager.screenIsOn();
5932 boolean screenIsDim = !mPowerManager.screenIsBright();
5933 int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
Romain Guy06882f82009-06-10 13:36:04 -07005934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) {
5936 mPowerManager.goToSleep(event.when);
5937 }
5938
5939 if (screenIsOff) {
5940 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
5941 }
5942 if (screenIsDim) {
5943 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
5944 }
5945 if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
5946 mPowerManager.userActivity(event.when, false,
Michael Chane96440f2009-05-06 10:27:36 -07005947 LocalPowerManager.BUTTON_EVENT, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005948 }
Romain Guy06882f82009-06-10 13:36:04 -07005949
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005950 if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
5951 if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) {
5952 filterQueue(this);
5953 mKeyWaiter.appSwitchComing();
5954 }
5955 return true;
5956 } else {
5957 return false;
5958 }
5959 }
Romain Guy06882f82009-06-10 13:36:04 -07005960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005961 case RawInputEvent.EV_REL: {
5962 boolean screenIsOff = !mPowerManager.screenIsOn();
5963 boolean screenIsDim = !mPowerManager.screenIsBright();
5964 if (screenIsOff) {
5965 if (!mPolicy.isWakeRelMovementTq(event.deviceId,
5966 device.classes, event)) {
5967 //Log.i(TAG, "dropping because screenIsOff and !isWakeKey");
5968 return false;
5969 }
5970 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
5971 }
5972 if (screenIsDim) {
5973 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
5974 }
5975 return true;
5976 }
Romain Guy06882f82009-06-10 13:36:04 -07005977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005978 case RawInputEvent.EV_ABS: {
5979 boolean screenIsOff = !mPowerManager.screenIsOn();
5980 boolean screenIsDim = !mPowerManager.screenIsBright();
5981 if (screenIsOff) {
5982 if (!mPolicy.isWakeAbsMovementTq(event.deviceId,
5983 device.classes, event)) {
5984 //Log.i(TAG, "dropping because screenIsOff and !isWakeKey");
5985 return false;
5986 }
5987 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
5988 }
5989 if (screenIsDim) {
5990 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
5991 }
5992 return true;
5993 }
Romain Guy06882f82009-06-10 13:36:04 -07005994
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005995 default:
5996 return true;
5997 }
5998 }
5999
6000 public int filterEvent(QueuedEvent ev) {
6001 switch (ev.classType) {
6002 case RawInputEvent.CLASS_KEYBOARD:
6003 KeyEvent ke = (KeyEvent)ev.event;
6004 if (mPolicy.isMovementKeyTi(ke.getKeyCode())) {
6005 Log.w(TAG, "Dropping movement key during app switch: "
6006 + ke.getKeyCode() + ", action=" + ke.getAction());
6007 return FILTER_REMOVE;
6008 }
6009 return FILTER_ABORT;
6010 default:
6011 return FILTER_KEEP;
6012 }
6013 }
Romain Guy06882f82009-06-10 13:36:04 -07006014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006015 /**
6016 * Must be called with the main window manager lock held.
6017 */
6018 void setHoldScreenLocked(boolean holding) {
6019 boolean state = mHoldingScreen.isHeld();
6020 if (holding != state) {
6021 if (holding) {
6022 mHoldingScreen.acquire();
6023 } else {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07006024 mPolicy.screenOnStoppedLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 mHoldingScreen.release();
6026 }
6027 }
6028 }
Michael Chan53071d62009-05-13 17:29:48 -07006029 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006030
6031 public boolean detectSafeMode() {
6032 mSafeMode = mPolicy.detectSafeMode();
6033 return mSafeMode;
6034 }
Romain Guy06882f82009-06-10 13:36:04 -07006035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006036 public void systemReady() {
6037 mPolicy.systemReady();
6038 }
Romain Guy06882f82009-06-10 13:36:04 -07006039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006040 private final class InputDispatcherThread extends Thread {
6041 // Time to wait when there is nothing to do: 9999 seconds.
6042 static final int LONG_WAIT=9999*1000;
6043
6044 public InputDispatcherThread() {
6045 super("InputDispatcher");
6046 }
Romain Guy06882f82009-06-10 13:36:04 -07006047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006048 @Override
6049 public void run() {
6050 while (true) {
6051 try {
6052 process();
6053 } catch (Exception e) {
6054 Log.e(TAG, "Exception in input dispatcher", e);
6055 }
6056 }
6057 }
Romain Guy06882f82009-06-10 13:36:04 -07006058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006059 private void process() {
6060 android.os.Process.setThreadPriority(
6061 android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -07006062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006063 // The last key event we saw
6064 KeyEvent lastKey = null;
6065
6066 // Last keydown time for auto-repeating keys
6067 long lastKeyTime = SystemClock.uptimeMillis();
6068 long nextKeyTime = lastKeyTime+LONG_WAIT;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006069 long downTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006070
Romain Guy06882f82009-06-10 13:36:04 -07006071 // How many successive repeats we generated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006072 int keyRepeatCount = 0;
6073
6074 // Need to report that configuration has changed?
6075 boolean configChanged = false;
Romain Guy06882f82009-06-10 13:36:04 -07006076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006077 while (true) {
6078 long curTime = SystemClock.uptimeMillis();
6079
6080 if (DEBUG_INPUT) Log.v(
6081 TAG, "Waiting for next key: now=" + curTime
6082 + ", repeat @ " + nextKeyTime);
6083
6084 // Retrieve next event, waiting only as long as the next
6085 // repeat timeout. If the configuration has changed, then
6086 // don't wait at all -- we'll report the change as soon as
6087 // we have processed all events.
6088 QueuedEvent ev = mQueue.getEvent(
6089 (int)((!configChanged && curTime < nextKeyTime)
6090 ? (nextKeyTime-curTime) : 0));
6091
6092 if (DEBUG_INPUT && ev != null) Log.v(
6093 TAG, "Event: type=" + ev.classType + " data=" + ev.event);
6094
Michael Chan53071d62009-05-13 17:29:48 -07006095 if (MEASURE_LATENCY) {
6096 lt.sample("2 got event ", System.nanoTime() - ev.whenNano);
6097 }
6098
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006099 try {
6100 if (ev != null) {
Michael Chan53071d62009-05-13 17:29:48 -07006101 curTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006102 int eventType;
6103 if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
6104 eventType = eventType((MotionEvent)ev.event);
6105 } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
6106 ev.classType == RawInputEvent.CLASS_TRACKBALL) {
6107 eventType = LocalPowerManager.BUTTON_EVENT;
6108 } else {
6109 eventType = LocalPowerManager.OTHER_EVENT;
6110 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07006111 try {
Michael Chan53071d62009-05-13 17:29:48 -07006112 if ((curTime - mLastBatteryStatsCallTime)
Michael Chane96440f2009-05-06 10:27:36 -07006113 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
Michael Chan53071d62009-05-13 17:29:48 -07006114 mLastBatteryStatsCallTime = curTime;
Michael Chane96440f2009-05-06 10:27:36 -07006115 mBatteryStats.noteInputEvent();
6116 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07006117 } catch (RemoteException e) {
6118 // Ignore
6119 }
Michael Chane10de972009-05-18 11:24:50 -07006120
6121 if (eventType != TOUCH_EVENT
6122 && eventType != LONG_TOUCH_EVENT
6123 && eventType != CHEEK_EVENT) {
6124 mPowerManager.userActivity(curTime, false,
6125 eventType, false);
6126 } else if (mLastTouchEventType != eventType
6127 || (curTime - mLastUserActivityCallTime)
6128 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
6129 mLastUserActivityCallTime = curTime;
6130 mLastTouchEventType = eventType;
6131 mPowerManager.userActivity(curTime, false,
6132 eventType, false);
6133 }
6134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006135 switch (ev.classType) {
6136 case RawInputEvent.CLASS_KEYBOARD:
6137 KeyEvent ke = (KeyEvent)ev.event;
6138 if (ke.isDown()) {
6139 lastKey = ke;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006140 downTime = curTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006141 keyRepeatCount = 0;
6142 lastKeyTime = curTime;
6143 nextKeyTime = lastKeyTime
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006144 + ViewConfiguration.getLongPressTimeout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006145 if (DEBUG_INPUT) Log.v(
6146 TAG, "Received key down: first repeat @ "
6147 + nextKeyTime);
6148 } else {
6149 lastKey = null;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006150 downTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006151 // Arbitrary long timeout.
6152 lastKeyTime = curTime;
6153 nextKeyTime = curTime + LONG_WAIT;
6154 if (DEBUG_INPUT) Log.v(
6155 TAG, "Received key up: ignore repeat @ "
6156 + nextKeyTime);
6157 }
6158 dispatchKey((KeyEvent)ev.event, 0, 0);
6159 mQueue.recycleEvent(ev);
6160 break;
6161 case RawInputEvent.CLASS_TOUCHSCREEN:
6162 //Log.i(TAG, "Read next event " + ev);
6163 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
6164 break;
6165 case RawInputEvent.CLASS_TRACKBALL:
6166 dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
6167 break;
6168 case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
6169 configChanged = true;
6170 break;
6171 default:
6172 mQueue.recycleEvent(ev);
6173 break;
6174 }
Romain Guy06882f82009-06-10 13:36:04 -07006175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006176 } else if (configChanged) {
6177 configChanged = false;
6178 sendNewConfiguration();
Romain Guy06882f82009-06-10 13:36:04 -07006179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006180 } else if (lastKey != null) {
6181 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07006182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006183 // Timeout occurred while key was down. If it is at or
6184 // past the key repeat time, dispatch the repeat.
6185 if (DEBUG_INPUT) Log.v(
6186 TAG, "Key timeout: repeat=" + nextKeyTime
6187 + ", now=" + curTime);
6188 if (curTime < nextKeyTime) {
6189 continue;
6190 }
Romain Guy06882f82009-06-10 13:36:04 -07006191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006192 lastKeyTime = nextKeyTime;
6193 nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY;
6194 keyRepeatCount++;
6195 if (DEBUG_INPUT) Log.v(
6196 TAG, "Key repeat: count=" + keyRepeatCount
6197 + ", next @ " + nextKeyTime);
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006198 KeyEvent newEvent;
6199 if (downTime != 0 && (downTime
6200 + ViewConfiguration.getLongPressTimeout())
6201 <= curTime) {
6202 newEvent = KeyEvent.changeTimeRepeat(lastKey,
6203 curTime, keyRepeatCount,
6204 lastKey.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6205 downTime = 0;
6206 } else {
6207 newEvent = KeyEvent.changeTimeRepeat(lastKey,
6208 curTime, keyRepeatCount);
6209 }
6210 dispatchKey(newEvent, 0, 0);
Romain Guy06882f82009-06-10 13:36:04 -07006211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006212 } else {
6213 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07006214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 lastKeyTime = curTime;
6216 nextKeyTime = curTime + LONG_WAIT;
6217 }
Romain Guy06882f82009-06-10 13:36:04 -07006218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 } catch (Exception e) {
6220 Log.e(TAG,
6221 "Input thread received uncaught exception: " + e, e);
6222 }
6223 }
6224 }
6225 }
6226
6227 // -------------------------------------------------------------
6228 // Client Session State
6229 // -------------------------------------------------------------
6230
6231 private final class Session extends IWindowSession.Stub
6232 implements IBinder.DeathRecipient {
6233 final IInputMethodClient mClient;
6234 final IInputContext mInputContext;
6235 final int mUid;
6236 final int mPid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006237 final String mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006238 SurfaceSession mSurfaceSession;
6239 int mNumWindow = 0;
6240 boolean mClientDead = false;
Romain Guy06882f82009-06-10 13:36:04 -07006241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006242 /**
6243 * Current pointer move event being dispatched to client window... must
6244 * hold key lock to access.
6245 */
6246 QueuedEvent mPendingPointerMove;
6247 WindowState mPendingPointerWindow;
Romain Guy06882f82009-06-10 13:36:04 -07006248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006249 /**
6250 * Current trackball move event being dispatched to client window... must
6251 * hold key lock to access.
6252 */
6253 QueuedEvent mPendingTrackballMove;
6254 WindowState mPendingTrackballWindow;
6255
6256 public Session(IInputMethodClient client, IInputContext inputContext) {
6257 mClient = client;
6258 mInputContext = inputContext;
6259 mUid = Binder.getCallingUid();
6260 mPid = Binder.getCallingPid();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006261 StringBuilder sb = new StringBuilder();
6262 sb.append("Session{");
6263 sb.append(Integer.toHexString(System.identityHashCode(this)));
6264 sb.append(" uid ");
6265 sb.append(mUid);
6266 sb.append("}");
6267 mStringName = sb.toString();
Romain Guy06882f82009-06-10 13:36:04 -07006268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006269 synchronized (mWindowMap) {
6270 if (mInputMethodManager == null && mHaveInputMethods) {
6271 IBinder b = ServiceManager.getService(
6272 Context.INPUT_METHOD_SERVICE);
6273 mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
6274 }
6275 }
6276 long ident = Binder.clearCallingIdentity();
6277 try {
6278 // Note: it is safe to call in to the input method manager
6279 // here because we are not holding our lock.
6280 if (mInputMethodManager != null) {
6281 mInputMethodManager.addClient(client, inputContext,
6282 mUid, mPid);
6283 } else {
6284 client.setUsingInputMethod(false);
6285 }
6286 client.asBinder().linkToDeath(this, 0);
6287 } catch (RemoteException e) {
6288 // The caller has died, so we can just forget about this.
6289 try {
6290 if (mInputMethodManager != null) {
6291 mInputMethodManager.removeClient(client);
6292 }
6293 } catch (RemoteException ee) {
6294 }
6295 } finally {
6296 Binder.restoreCallingIdentity(ident);
6297 }
6298 }
Romain Guy06882f82009-06-10 13:36:04 -07006299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006300 @Override
6301 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
6302 throws RemoteException {
6303 try {
6304 return super.onTransact(code, data, reply, flags);
6305 } catch (RuntimeException e) {
6306 // Log all 'real' exceptions thrown to the caller
6307 if (!(e instanceof SecurityException)) {
6308 Log.e(TAG, "Window Session Crash", e);
6309 }
6310 throw e;
6311 }
6312 }
6313
6314 public void binderDied() {
6315 // Note: it is safe to call in to the input method manager
6316 // here because we are not holding our lock.
6317 try {
6318 if (mInputMethodManager != null) {
6319 mInputMethodManager.removeClient(mClient);
6320 }
6321 } catch (RemoteException e) {
6322 }
6323 synchronized(mWindowMap) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07006324 mClient.asBinder().unlinkToDeath(this, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006325 mClientDead = true;
6326 killSessionLocked();
6327 }
6328 }
6329
6330 public int add(IWindow window, WindowManager.LayoutParams attrs,
6331 int viewVisibility, Rect outContentInsets) {
6332 return addWindow(this, window, attrs, viewVisibility, outContentInsets);
6333 }
Romain Guy06882f82009-06-10 13:36:04 -07006334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006335 public void remove(IWindow window) {
6336 removeWindow(this, window);
6337 }
Romain Guy06882f82009-06-10 13:36:04 -07006338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006339 public int relayout(IWindow window, WindowManager.LayoutParams attrs,
6340 int requestedWidth, int requestedHeight, int viewFlags,
6341 boolean insetsPending, Rect outFrame, Rect outContentInsets,
6342 Rect outVisibleInsets, Surface outSurface) {
6343 return relayoutWindow(this, window, attrs,
6344 requestedWidth, requestedHeight, viewFlags, insetsPending,
6345 outFrame, outContentInsets, outVisibleInsets, outSurface);
6346 }
Romain Guy06882f82009-06-10 13:36:04 -07006347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006348 public void setTransparentRegion(IWindow window, Region region) {
6349 setTransparentRegionWindow(this, window, region);
6350 }
Romain Guy06882f82009-06-10 13:36:04 -07006351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006352 public void setInsets(IWindow window, int touchableInsets,
6353 Rect contentInsets, Rect visibleInsets) {
6354 setInsetsWindow(this, window, touchableInsets, contentInsets,
6355 visibleInsets);
6356 }
Romain Guy06882f82009-06-10 13:36:04 -07006357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006358 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
6359 getWindowDisplayFrame(this, window, outDisplayFrame);
6360 }
Romain Guy06882f82009-06-10 13:36:04 -07006361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006362 public void finishDrawing(IWindow window) {
6363 if (localLOGV) Log.v(
6364 TAG, "IWindow finishDrawing called for " + window);
6365 finishDrawingWindow(this, window);
6366 }
6367
6368 public void finishKey(IWindow window) {
6369 if (localLOGV) Log.v(
6370 TAG, "IWindow finishKey called for " + window);
6371 mKeyWaiter.finishedKey(this, window, false,
6372 KeyWaiter.RETURN_NOTHING);
6373 }
6374
6375 public MotionEvent getPendingPointerMove(IWindow window) {
6376 if (localLOGV) Log.v(
6377 TAG, "IWindow getPendingMotionEvent called for " + window);
6378 return mKeyWaiter.finishedKey(this, window, false,
6379 KeyWaiter.RETURN_PENDING_POINTER);
6380 }
Romain Guy06882f82009-06-10 13:36:04 -07006381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006382 public MotionEvent getPendingTrackballMove(IWindow window) {
6383 if (localLOGV) Log.v(
6384 TAG, "IWindow getPendingMotionEvent called for " + window);
6385 return mKeyWaiter.finishedKey(this, window, false,
6386 KeyWaiter.RETURN_PENDING_TRACKBALL);
6387 }
6388
6389 public void setInTouchMode(boolean mode) {
6390 synchronized(mWindowMap) {
6391 mInTouchMode = mode;
6392 }
6393 }
6394
6395 public boolean getInTouchMode() {
6396 synchronized(mWindowMap) {
6397 return mInTouchMode;
6398 }
6399 }
6400
6401 public boolean performHapticFeedback(IWindow window, int effectId,
6402 boolean always) {
6403 synchronized(mWindowMap) {
6404 long ident = Binder.clearCallingIdentity();
6405 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07006406 return mPolicy.performHapticFeedbackLw(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006407 windowForClientLocked(this, window), effectId, always);
6408 } finally {
6409 Binder.restoreCallingIdentity(ident);
6410 }
6411 }
6412 }
Romain Guy06882f82009-06-10 13:36:04 -07006413
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006414 public void setWallpaperPosition(IBinder window, float x, float y) {
6415 synchronized(mWindowMap) {
6416 long ident = Binder.clearCallingIdentity();
6417 try {
6418 setWindowWallpaperPositionLocked(windowForClientLocked(this, window),
6419 x, y);
6420 } finally {
6421 Binder.restoreCallingIdentity(ident);
6422 }
6423 }
6424 }
6425
Dianne Hackborn19382ac2009-09-11 21:13:37 -07006426 public void wallpaperOffsetsComplete(IBinder window) {
6427 WindowManagerService.this.wallpaperOffsetsComplete(window);
6428 }
6429
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006430 void windowAddedLocked() {
6431 if (mSurfaceSession == null) {
6432 if (localLOGV) Log.v(
6433 TAG, "First window added to " + this + ", creating SurfaceSession");
6434 mSurfaceSession = new SurfaceSession();
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07006435 if (SHOW_TRANSACTIONS) Log.i(
6436 TAG, " NEW SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006437 mSessions.add(this);
6438 }
6439 mNumWindow++;
6440 }
6441
6442 void windowRemovedLocked() {
6443 mNumWindow--;
6444 killSessionLocked();
6445 }
Romain Guy06882f82009-06-10 13:36:04 -07006446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006447 void killSessionLocked() {
6448 if (mNumWindow <= 0 && mClientDead) {
6449 mSessions.remove(this);
6450 if (mSurfaceSession != null) {
6451 if (localLOGV) Log.v(
6452 TAG, "Last window removed from " + this
6453 + ", destroying " + mSurfaceSession);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07006454 if (SHOW_TRANSACTIONS) Log.i(
6455 TAG, " KILL SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006456 try {
6457 mSurfaceSession.kill();
6458 } catch (Exception e) {
6459 Log.w(TAG, "Exception thrown when killing surface session "
6460 + mSurfaceSession + " in session " + this
6461 + ": " + e.toString());
6462 }
6463 mSurfaceSession = null;
6464 }
6465 }
6466 }
Romain Guy06882f82009-06-10 13:36:04 -07006467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006468 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006469 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
6470 pw.print(" mClientDead="); pw.print(mClientDead);
6471 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
6472 if (mPendingPointerWindow != null || mPendingPointerMove != null) {
6473 pw.print(prefix);
6474 pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
6475 pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
6476 }
6477 if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
6478 pw.print(prefix);
6479 pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
6480 pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
6481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006482 }
6483
6484 @Override
6485 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006486 return mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006487 }
6488 }
6489
6490 // -------------------------------------------------------------
6491 // Client Window State
6492 // -------------------------------------------------------------
6493
6494 private final class WindowState implements WindowManagerPolicy.WindowState {
6495 final Session mSession;
6496 final IWindow mClient;
6497 WindowToken mToken;
The Android Open Source Project10592532009-03-18 17:39:46 -07006498 WindowToken mRootToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006499 AppWindowToken mAppToken;
6500 AppWindowToken mTargetAppToken;
6501 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
6502 final DeathRecipient mDeathRecipient;
6503 final WindowState mAttachedWindow;
6504 final ArrayList mChildWindows = new ArrayList();
6505 final int mBaseLayer;
6506 final int mSubLayer;
6507 final boolean mLayoutAttached;
6508 final boolean mIsImWindow;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006509 final boolean mIsWallpaper;
6510 final boolean mIsFloatingLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006511 int mViewVisibility;
6512 boolean mPolicyVisibility = true;
6513 boolean mPolicyVisibilityAfterAnim = true;
6514 boolean mAppFreezing;
6515 Surface mSurface;
6516 boolean mAttachedHidden; // is our parent window hidden?
6517 boolean mLastHidden; // was this window last hidden?
Dianne Hackborn759a39e2009-08-09 17:20:27 -07006518 boolean mWallpaperVisible; // for wallpaper, what was last vis report?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006519 int mRequestedWidth;
6520 int mRequestedHeight;
6521 int mLastRequestedWidth;
6522 int mLastRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 int mLayer;
6524 int mAnimLayer;
6525 int mLastLayer;
6526 boolean mHaveFrame;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07006527 boolean mObscured;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07006528 boolean mTurnOnScreen;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006529
6530 WindowState mNextOutsideTouch;
Romain Guy06882f82009-06-10 13:36:04 -07006531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006532 // Actual frame shown on-screen (may be modified by animation)
6533 final Rect mShownFrame = new Rect();
6534 final Rect mLastShownFrame = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07006535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006536 /**
6537 * Insets that determine the actually visible area
6538 */
6539 final Rect mVisibleInsets = new Rect();
6540 final Rect mLastVisibleInsets = new Rect();
6541 boolean mVisibleInsetsChanged;
6542
6543 /**
6544 * Insets that are covered by system windows
6545 */
6546 final Rect mContentInsets = new Rect();
6547 final Rect mLastContentInsets = new Rect();
6548 boolean mContentInsetsChanged;
6549
6550 /**
6551 * Set to true if we are waiting for this window to receive its
6552 * given internal insets before laying out other windows based on it.
6553 */
6554 boolean mGivenInsetsPending;
Romain Guy06882f82009-06-10 13:36:04 -07006555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006556 /**
6557 * These are the content insets that were given during layout for
6558 * this window, to be applied to windows behind it.
6559 */
6560 final Rect mGivenContentInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07006561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006562 /**
6563 * These are the visible insets that were given during layout for
6564 * this window, to be applied to windows behind it.
6565 */
6566 final Rect mGivenVisibleInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07006567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006568 /**
6569 * Flag indicating whether the touchable region should be adjusted by
6570 * the visible insets; if false the area outside the visible insets is
6571 * NOT touchable, so we must use those to adjust the frame during hit
6572 * tests.
6573 */
6574 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
Romain Guy06882f82009-06-10 13:36:04 -07006575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006576 // Current transformation being applied.
6577 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
6578 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
6579 float mHScale=1, mVScale=1;
6580 float mLastHScale=1, mLastVScale=1;
6581 final Matrix mTmpMatrix = new Matrix();
6582
6583 // "Real" frame that the application sees.
6584 final Rect mFrame = new Rect();
6585 final Rect mLastFrame = new Rect();
6586
6587 final Rect mContainingFrame = new Rect();
6588 final Rect mDisplayFrame = new Rect();
6589 final Rect mContentFrame = new Rect();
6590 final Rect mVisibleFrame = new Rect();
6591
6592 float mShownAlpha = 1;
6593 float mAlpha = 1;
6594 float mLastAlpha = 1;
6595
6596 // Set to true if, when the window gets displayed, it should perform
6597 // an enter animation.
6598 boolean mEnterAnimationPending;
6599
6600 // Currently running animation.
6601 boolean mAnimating;
6602 boolean mLocalAnimating;
6603 Animation mAnimation;
6604 boolean mAnimationIsEntrance;
6605 boolean mHasTransformation;
6606 boolean mHasLocalTransformation;
6607 final Transformation mTransformation = new Transformation();
6608
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07006609 // If a window showing a wallpaper: the requested offset for the
6610 // wallpaper; if a wallpaper window: the currently applied offset.
6611 float mWallpaperX = -1;
6612 float mWallpaperY = -1;
6613
6614 // Wallpaper windows: pixels offset based on above variables.
6615 int mXOffset;
6616 int mYOffset;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006618 // This is set after IWindowSession.relayout() has been called at
6619 // least once for the window. It allows us to detect the situation
6620 // where we don't yet have a surface, but should have one soon, so
6621 // we can give the window focus before waiting for the relayout.
6622 boolean mRelayoutCalled;
Romain Guy06882f82009-06-10 13:36:04 -07006623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006624 // This is set after the Surface has been created but before the
6625 // window has been drawn. During this time the surface is hidden.
6626 boolean mDrawPending;
6627
6628 // This is set after the window has finished drawing for the first
6629 // time but before its surface is shown. The surface will be
6630 // displayed when the next layout is run.
6631 boolean mCommitDrawPending;
6632
6633 // This is set during the time after the window's drawing has been
6634 // committed, and before its surface is actually shown. It is used
6635 // to delay showing the surface until all windows in a token are ready
6636 // to be shown.
6637 boolean mReadyToShow;
Romain Guy06882f82009-06-10 13:36:04 -07006638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006639 // Set when the window has been shown in the screen the first time.
6640 boolean mHasDrawn;
6641
6642 // Currently running an exit animation?
6643 boolean mExiting;
6644
6645 // Currently on the mDestroySurface list?
6646 boolean mDestroying;
Romain Guy06882f82009-06-10 13:36:04 -07006647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006648 // Completely remove from window manager after exit animation?
6649 boolean mRemoveOnExit;
6650
6651 // Set when the orientation is changing and this window has not yet
6652 // been updated for the new orientation.
6653 boolean mOrientationChanging;
Romain Guy06882f82009-06-10 13:36:04 -07006654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006655 // Is this window now (or just being) removed?
6656 boolean mRemoved;
Romain Guy06882f82009-06-10 13:36:04 -07006657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 WindowState(Session s, IWindow c, WindowToken token,
6659 WindowState attachedWindow, WindowManager.LayoutParams a,
6660 int viewVisibility) {
6661 mSession = s;
6662 mClient = c;
6663 mToken = token;
6664 mAttrs.copyFrom(a);
6665 mViewVisibility = viewVisibility;
6666 DeathRecipient deathRecipient = new DeathRecipient();
6667 mAlpha = a.alpha;
6668 if (localLOGV) Log.v(
6669 TAG, "Window " + this + " client=" + c.asBinder()
6670 + " token=" + token + " (" + mAttrs.token + ")");
6671 try {
6672 c.asBinder().linkToDeath(deathRecipient, 0);
6673 } catch (RemoteException e) {
6674 mDeathRecipient = null;
6675 mAttachedWindow = null;
6676 mLayoutAttached = false;
6677 mIsImWindow = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006678 mIsWallpaper = false;
6679 mIsFloatingLayer = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006680 mBaseLayer = 0;
6681 mSubLayer = 0;
6682 return;
6683 }
6684 mDeathRecipient = deathRecipient;
Romain Guy06882f82009-06-10 13:36:04 -07006685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006686 if ((mAttrs.type >= FIRST_SUB_WINDOW &&
6687 mAttrs.type <= LAST_SUB_WINDOW)) {
6688 // The multiplier here is to reserve space for multiple
6689 // windows in the same type layer.
6690 mBaseLayer = mPolicy.windowTypeToLayerLw(
6691 attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
6692 + TYPE_LAYER_OFFSET;
6693 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
6694 mAttachedWindow = attachedWindow;
6695 mAttachedWindow.mChildWindows.add(this);
6696 mLayoutAttached = mAttrs.type !=
6697 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
6698 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
6699 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006700 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
6701 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006702 } else {
6703 // The multiplier here is to reserve space for multiple
6704 // windows in the same type layer.
6705 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
6706 * TYPE_LAYER_MULTIPLIER
6707 + TYPE_LAYER_OFFSET;
6708 mSubLayer = 0;
6709 mAttachedWindow = null;
6710 mLayoutAttached = false;
6711 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
6712 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006713 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
6714 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 }
6716
6717 WindowState appWin = this;
6718 while (appWin.mAttachedWindow != null) {
6719 appWin = mAttachedWindow;
6720 }
6721 WindowToken appToken = appWin.mToken;
6722 while (appToken.appWindowToken == null) {
6723 WindowToken parent = mTokenMap.get(appToken.token);
6724 if (parent == null || appToken == parent) {
6725 break;
6726 }
6727 appToken = parent;
6728 }
The Android Open Source Project10592532009-03-18 17:39:46 -07006729 mRootToken = appToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006730 mAppToken = appToken.appWindowToken;
6731
6732 mSurface = null;
6733 mRequestedWidth = 0;
6734 mRequestedHeight = 0;
6735 mLastRequestedWidth = 0;
6736 mLastRequestedHeight = 0;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006737 mXOffset = 0;
6738 mYOffset = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006739 mLayer = 0;
6740 mAnimLayer = 0;
6741 mLastLayer = 0;
6742 }
6743
6744 void attach() {
6745 if (localLOGV) Log.v(
6746 TAG, "Attaching " + this + " token=" + mToken
6747 + ", list=" + mToken.windows);
6748 mSession.windowAddedLocked();
6749 }
6750
6751 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
6752 mHaveFrame = true;
6753
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006754 final Rect container = mContainingFrame;
6755 container.set(pf);
6756
6757 final Rect display = mDisplayFrame;
6758 display.set(df);
6759
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07006760 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006761 container.intersect(mCompatibleScreenFrame);
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07006762 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
6763 display.intersect(mCompatibleScreenFrame);
6764 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006765 }
6766
6767 final int pw = container.right - container.left;
6768 final int ph = container.bottom - container.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006769
6770 int w,h;
6771 if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
6772 w = mAttrs.width < 0 ? pw : mAttrs.width;
6773 h = mAttrs.height< 0 ? ph : mAttrs.height;
6774 } else {
6775 w = mAttrs.width == mAttrs.FILL_PARENT ? pw : mRequestedWidth;
6776 h = mAttrs.height== mAttrs.FILL_PARENT ? ph : mRequestedHeight;
6777 }
Romain Guy06882f82009-06-10 13:36:04 -07006778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006779 final Rect content = mContentFrame;
6780 content.set(cf);
Romain Guy06882f82009-06-10 13:36:04 -07006781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006782 final Rect visible = mVisibleFrame;
6783 visible.set(vf);
Romain Guy06882f82009-06-10 13:36:04 -07006784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006785 final Rect frame = mFrame;
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07006786 final int fw = frame.width();
6787 final int fh = frame.height();
Romain Guy06882f82009-06-10 13:36:04 -07006788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006789 //System.out.println("In: w=" + w + " h=" + h + " container=" +
6790 // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
6791
6792 Gravity.apply(mAttrs.gravity, w, h, container,
6793 (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
6794 (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
6795
6796 //System.out.println("Out: " + mFrame);
6797
6798 // Now make sure the window fits in the overall display.
6799 Gravity.applyDisplay(mAttrs.gravity, df, frame);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006801 // Make sure the content and visible frames are inside of the
6802 // final window frame.
6803 if (content.left < frame.left) content.left = frame.left;
6804 if (content.top < frame.top) content.top = frame.top;
6805 if (content.right > frame.right) content.right = frame.right;
6806 if (content.bottom > frame.bottom) content.bottom = frame.bottom;
6807 if (visible.left < frame.left) visible.left = frame.left;
6808 if (visible.top < frame.top) visible.top = frame.top;
6809 if (visible.right > frame.right) visible.right = frame.right;
6810 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07006811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006812 final Rect contentInsets = mContentInsets;
6813 contentInsets.left = content.left-frame.left;
6814 contentInsets.top = content.top-frame.top;
6815 contentInsets.right = frame.right-content.right;
6816 contentInsets.bottom = frame.bottom-content.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07006817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006818 final Rect visibleInsets = mVisibleInsets;
6819 visibleInsets.left = visible.left-frame.left;
6820 visibleInsets.top = visible.top-frame.top;
6821 visibleInsets.right = frame.right-visible.right;
6822 visibleInsets.bottom = frame.bottom-visible.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07006823
Dianne Hackborn284ac932009-08-28 10:34:25 -07006824 if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
6825 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07006826 mDisplay.getHeight(), false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07006827 }
6828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006829 if (localLOGV) {
6830 //if ("com.google.android.youtube".equals(mAttrs.packageName)
6831 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
6832 Log.v(TAG, "Resolving (mRequestedWidth="
6833 + mRequestedWidth + ", mRequestedheight="
6834 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
6835 + "): frame=" + mFrame.toShortString()
6836 + " ci=" + contentInsets.toShortString()
6837 + " vi=" + visibleInsets.toShortString());
6838 //}
6839 }
6840 }
Romain Guy06882f82009-06-10 13:36:04 -07006841
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006842 public Rect getFrameLw() {
6843 return mFrame;
6844 }
6845
6846 public Rect getShownFrameLw() {
6847 return mShownFrame;
6848 }
6849
6850 public Rect getDisplayFrameLw() {
6851 return mDisplayFrame;
6852 }
6853
6854 public Rect getContentFrameLw() {
6855 return mContentFrame;
6856 }
6857
6858 public Rect getVisibleFrameLw() {
6859 return mVisibleFrame;
6860 }
6861
6862 public boolean getGivenInsetsPendingLw() {
6863 return mGivenInsetsPending;
6864 }
6865
6866 public Rect getGivenContentInsetsLw() {
6867 return mGivenContentInsets;
6868 }
Romain Guy06882f82009-06-10 13:36:04 -07006869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006870 public Rect getGivenVisibleInsetsLw() {
6871 return mGivenVisibleInsets;
6872 }
Romain Guy06882f82009-06-10 13:36:04 -07006873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006874 public WindowManager.LayoutParams getAttrs() {
6875 return mAttrs;
6876 }
6877
6878 public int getSurfaceLayer() {
6879 return mLayer;
6880 }
Romain Guy06882f82009-06-10 13:36:04 -07006881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006882 public IApplicationToken getAppToken() {
6883 return mAppToken != null ? mAppToken.appToken : null;
6884 }
6885
6886 public boolean hasAppShownWindows() {
6887 return mAppToken != null ? mAppToken.firstWindowDrawn : false;
6888 }
6889
6890 public boolean hasAppStartingIcon() {
6891 return mAppToken != null ? (mAppToken.startingData != null) : false;
6892 }
6893
6894 public WindowManagerPolicy.WindowState getAppStartingWindow() {
6895 return mAppToken != null ? mAppToken.startingWindow : null;
6896 }
6897
6898 public void setAnimation(Animation anim) {
6899 if (localLOGV) Log.v(
6900 TAG, "Setting animation in " + this + ": " + anim);
6901 mAnimating = false;
6902 mLocalAnimating = false;
6903 mAnimation = anim;
6904 mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
6905 mAnimation.scaleCurrentDuration(mWindowAnimationScale);
6906 }
6907
6908 public void clearAnimation() {
6909 if (mAnimation != null) {
6910 mAnimating = true;
6911 mLocalAnimating = false;
6912 mAnimation = null;
6913 }
6914 }
Romain Guy06882f82009-06-10 13:36:04 -07006915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006916 Surface createSurfaceLocked() {
6917 if (mSurface == null) {
6918 mDrawPending = true;
6919 mCommitDrawPending = false;
6920 mReadyToShow = false;
6921 if (mAppToken != null) {
6922 mAppToken.allDrawn = false;
6923 }
6924
6925 int flags = 0;
Mathias Agopian317a6282009-08-13 17:29:02 -07006926 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006927 flags |= Surface.PUSH_BUFFERS;
6928 }
6929
6930 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
6931 flags |= Surface.SECURE;
6932 }
6933 if (DEBUG_VISIBILITY) Log.v(
6934 TAG, "Creating surface in session "
6935 + mSession.mSurfaceSession + " window " + this
6936 + " w=" + mFrame.width()
6937 + " h=" + mFrame.height() + " format="
6938 + mAttrs.format + " flags=" + flags);
6939
6940 int w = mFrame.width();
6941 int h = mFrame.height();
6942 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
6943 // for a scaled surface, we always want the requested
6944 // size.
6945 w = mRequestedWidth;
6946 h = mRequestedHeight;
6947 }
6948
6949 try {
6950 mSurface = new Surface(
Romain Guy06882f82009-06-10 13:36:04 -07006951 mSession.mSurfaceSession, mSession.mPid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006952 0, w, h, mAttrs.format, flags);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07006953 if (SHOW_TRANSACTIONS) Log.i(TAG, " CREATE SURFACE "
6954 + mSurface + " IN SESSION "
6955 + mSession.mSurfaceSession
6956 + ": pid=" + mSession.mPid + " format="
6957 + mAttrs.format + " flags=0x"
6958 + Integer.toHexString(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006959 } catch (Surface.OutOfResourcesException e) {
6960 Log.w(TAG, "OutOfResourcesException creating surface");
6961 reclaimSomeSurfaceMemoryLocked(this, "create");
6962 return null;
6963 } catch (Exception e) {
6964 Log.e(TAG, "Exception creating surface", e);
6965 return null;
6966 }
Romain Guy06882f82009-06-10 13:36:04 -07006967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006968 if (localLOGV) Log.v(
6969 TAG, "Got surface: " + mSurface
6970 + ", set left=" + mFrame.left + " top=" + mFrame.top
6971 + ", animLayer=" + mAnimLayer);
6972 if (SHOW_TRANSACTIONS) {
6973 Log.i(TAG, ">>> OPEN TRANSACTION");
6974 Log.i(TAG, " SURFACE " + mSurface + ": CREATE ("
6975 + mAttrs.getTitle() + ") pos=(" +
6976 mFrame.left + "," + mFrame.top + ") (" +
6977 mFrame.width() + "x" + mFrame.height() + "), layer=" +
6978 mAnimLayer + " HIDE");
6979 }
6980 Surface.openTransaction();
6981 try {
6982 try {
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07006983 mSurface.setPosition(mFrame.left + mXOffset,
6984 mFrame.top + mYOffset);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006985 mSurface.setLayer(mAnimLayer);
6986 mSurface.hide();
6987 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07006988 if (SHOW_TRANSACTIONS) Log.i(TAG, " SURFACE "
6989 + mSurface + ": DITHER");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006990 mSurface.setFlags(Surface.SURFACE_DITHER,
6991 Surface.SURFACE_DITHER);
6992 }
6993 } catch (RuntimeException e) {
6994 Log.w(TAG, "Error creating surface in " + w, e);
6995 reclaimSomeSurfaceMemoryLocked(this, "create-init");
6996 }
6997 mLastHidden = true;
6998 } finally {
6999 if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION");
7000 Surface.closeTransaction();
7001 }
7002 if (localLOGV) Log.v(
7003 TAG, "Created surface " + this);
7004 }
7005 return mSurface;
7006 }
Romain Guy06882f82009-06-10 13:36:04 -07007007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007008 void destroySurfaceLocked() {
7009 // Window is no longer on-screen, so can no longer receive
7010 // key events... if we were waiting for it to finish
7011 // handling a key event, the wait is over!
7012 mKeyWaiter.finishedKey(mSession, mClient, true,
7013 KeyWaiter.RETURN_NOTHING);
7014 mKeyWaiter.releasePendingPointerLocked(mSession);
7015 mKeyWaiter.releasePendingTrackballLocked(mSession);
7016
7017 if (mAppToken != null && this == mAppToken.startingWindow) {
7018 mAppToken.startingDisplayed = false;
7019 }
Romain Guy06882f82009-06-10 13:36:04 -07007020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007021 if (mSurface != null) {
7022 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007023 if (DEBUG_VISIBILITY) {
7024 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07007025 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007026 Log.w(TAG, "Window " + this + " destroying surface "
7027 + mSurface + ", session " + mSession, e);
7028 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007029 if (SHOW_TRANSACTIONS) {
7030 RuntimeException ex = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07007031 if (!HIDE_STACK_CRAWLS) ex.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007032 Log.i(TAG, " SURFACE " + mSurface + ": DESTROY ("
7033 + mAttrs.getTitle() + ")", ex);
7034 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007035 mSurface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007036 } catch (RuntimeException e) {
7037 Log.w(TAG, "Exception thrown when destroying Window " + this
7038 + " surface " + mSurface + " session " + mSession
7039 + ": " + e.toString());
7040 }
7041 mSurface = null;
7042 mDrawPending = false;
7043 mCommitDrawPending = false;
7044 mReadyToShow = false;
7045
7046 int i = mChildWindows.size();
7047 while (i > 0) {
7048 i--;
7049 WindowState c = (WindowState)mChildWindows.get(i);
7050 c.mAttachedHidden = true;
7051 }
7052 }
7053 }
7054
7055 boolean finishDrawingLocked() {
7056 if (mDrawPending) {
7057 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Log.v(
7058 TAG, "finishDrawingLocked: " + mSurface);
7059 mCommitDrawPending = true;
7060 mDrawPending = false;
7061 return true;
7062 }
7063 return false;
7064 }
7065
7066 // This must be called while inside a transaction.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007067 boolean commitFinishDrawingLocked(long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007068 //Log.i(TAG, "commitFinishDrawingLocked: " + mSurface);
7069 if (!mCommitDrawPending) {
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007070 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007071 }
7072 mCommitDrawPending = false;
7073 mReadyToShow = true;
7074 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
7075 final AppWindowToken atoken = mAppToken;
7076 if (atoken == null || atoken.allDrawn || starting) {
7077 performShowLocked();
7078 }
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007079 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007080 }
7081
7082 // This must be called while inside a transaction.
7083 boolean performShowLocked() {
7084 if (DEBUG_VISIBILITY) {
7085 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07007086 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007087 Log.v(TAG, "performShow on " + this
7088 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
7089 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
7090 }
7091 if (mReadyToShow && isReadyForDisplay()) {
7092 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Log.i(
7093 TAG, " SURFACE " + mSurface + ": SHOW (performShowLocked)");
7094 if (DEBUG_VISIBILITY) Log.v(TAG, "Showing " + this
7095 + " during animation: policyVis=" + mPolicyVisibility
7096 + " attHidden=" + mAttachedHidden
7097 + " tok.hiddenRequested="
7098 + (mAppToken != null ? mAppToken.hiddenRequested : false)
Dianne Hackborn248b1882009-09-16 16:46:44 -07007099 + " tok.hidden="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007100 + (mAppToken != null ? mAppToken.hidden : false)
7101 + " animating=" + mAnimating
7102 + " tok animating="
7103 + (mAppToken != null ? mAppToken.animating : false));
7104 if (!showSurfaceRobustlyLocked(this)) {
7105 return false;
7106 }
7107 mLastAlpha = -1;
7108 mHasDrawn = true;
7109 mLastHidden = false;
7110 mReadyToShow = false;
7111 enableScreenIfNeededLocked();
7112
7113 applyEnterAnimationLocked(this);
Romain Guy06882f82009-06-10 13:36:04 -07007114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007115 int i = mChildWindows.size();
7116 while (i > 0) {
7117 i--;
7118 WindowState c = (WindowState)mChildWindows.get(i);
7119 if (c.mSurface != null && c.mAttachedHidden) {
7120 c.mAttachedHidden = false;
7121 c.performShowLocked();
7122 }
7123 }
Romain Guy06882f82009-06-10 13:36:04 -07007124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007125 if (mAttrs.type != TYPE_APPLICATION_STARTING
7126 && mAppToken != null) {
7127 mAppToken.firstWindowDrawn = true;
Dianne Hackborn248b1882009-09-16 16:46:44 -07007128
7129 if (mAppToken.startingData != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007130 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Log.v(TAG,
7131 "Finish starting " + mToken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007132 + ": first real window is shown, no animation");
Dianne Hackborn248b1882009-09-16 16:46:44 -07007133 // If this initial window is animating, stop it -- we
7134 // will do an animation to reveal it from behind the
7135 // starting window, so there is no need for it to also
7136 // be doing its own stuff.
7137 if (mAnimation != null) {
7138 mAnimation = null;
7139 // Make sure we clean up the animation.
7140 mAnimating = true;
7141 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007142 mFinishedStarting.add(mAppToken);
7143 mH.sendEmptyMessage(H.FINISHED_STARTING);
7144 }
7145 mAppToken.updateReportedVisibilityLocked();
7146 }
7147 }
7148 return true;
7149 }
Romain Guy06882f82009-06-10 13:36:04 -07007150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007151 // This must be called while inside a transaction. Returns true if
7152 // there is more animation to run.
7153 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
7154 if (!mDisplayFrozen) {
7155 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07007156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007157 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
7158 mHasTransformation = true;
7159 mHasLocalTransformation = true;
7160 if (!mLocalAnimating) {
7161 if (DEBUG_ANIM) Log.v(
7162 TAG, "Starting animation in " + this +
7163 " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
7164 " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
7165 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
7166 mAnimation.setStartTime(currentTime);
7167 mLocalAnimating = true;
7168 mAnimating = true;
7169 }
7170 mTransformation.clear();
7171 final boolean more = mAnimation.getTransformation(
7172 currentTime, mTransformation);
7173 if (DEBUG_ANIM) Log.v(
7174 TAG, "Stepped animation in " + this +
7175 ": more=" + more + ", xform=" + mTransformation);
7176 if (more) {
7177 // we're not done!
7178 return true;
7179 }
7180 if (DEBUG_ANIM) Log.v(
7181 TAG, "Finished animation in " + this +
7182 " @ " + currentTime);
7183 mAnimation = null;
7184 //WindowManagerService.this.dump();
7185 }
7186 mHasLocalTransformation = false;
7187 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007188 && mAppToken.animation != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007189 // When our app token is animating, we kind-of pretend like
7190 // we are as well. Note the mLocalAnimating mAnimationIsEntrance
7191 // part of this check means that we will only do this if
7192 // our window is not currently exiting, or it is not
7193 // locally animating itself. The idea being that one that
7194 // is exiting and doing a local animation should be removed
7195 // once that animation is done.
7196 mAnimating = true;
7197 mHasTransformation = true;
7198 mTransformation.clear();
7199 return false;
7200 } else if (mHasTransformation) {
7201 // Little trick to get through the path below to act like
7202 // we have finished an animation.
7203 mAnimating = true;
7204 } else if (isAnimating()) {
7205 mAnimating = true;
7206 }
7207 } else if (mAnimation != null) {
7208 // If the display is frozen, and there is a pending animation,
7209 // clear it and make sure we run the cleanup code.
7210 mAnimating = true;
7211 mLocalAnimating = true;
7212 mAnimation = null;
7213 }
Romain Guy06882f82009-06-10 13:36:04 -07007214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007215 if (!mAnimating && !mLocalAnimating) {
7216 return false;
7217 }
7218
7219 if (DEBUG_ANIM) Log.v(
7220 TAG, "Animation done in " + this + ": exiting=" + mExiting
7221 + ", reportedVisible="
7222 + (mAppToken != null ? mAppToken.reportedVisible : false));
Romain Guy06882f82009-06-10 13:36:04 -07007223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007224 mAnimating = false;
7225 mLocalAnimating = false;
7226 mAnimation = null;
7227 mAnimLayer = mLayer;
7228 if (mIsImWindow) {
7229 mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007230 } else if (mIsWallpaper) {
7231 mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007232 }
7233 if (DEBUG_LAYERS) Log.v(TAG, "Stepping win " + this
7234 + " anim layer: " + mAnimLayer);
7235 mHasTransformation = false;
7236 mHasLocalTransformation = false;
7237 mPolicyVisibility = mPolicyVisibilityAfterAnim;
7238 mTransformation.clear();
7239 if (mHasDrawn
7240 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
7241 && mAppToken != null
7242 && mAppToken.firstWindowDrawn
7243 && mAppToken.startingData != null) {
7244 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Finish starting "
7245 + mToken + ": first real window done animating");
7246 mFinishedStarting.add(mAppToken);
7247 mH.sendEmptyMessage(H.FINISHED_STARTING);
7248 }
Romain Guy06882f82009-06-10 13:36:04 -07007249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 finishExit();
7251
7252 if (mAppToken != null) {
7253 mAppToken.updateReportedVisibilityLocked();
7254 }
7255
7256 return false;
7257 }
7258
7259 void finishExit() {
7260 if (DEBUG_ANIM) Log.v(
7261 TAG, "finishExit in " + this
7262 + ": exiting=" + mExiting
7263 + " remove=" + mRemoveOnExit
7264 + " windowAnimating=" + isWindowAnimating());
Romain Guy06882f82009-06-10 13:36:04 -07007265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007266 final int N = mChildWindows.size();
7267 for (int i=0; i<N; i++) {
7268 ((WindowState)mChildWindows.get(i)).finishExit();
7269 }
Romain Guy06882f82009-06-10 13:36:04 -07007270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271 if (!mExiting) {
7272 return;
7273 }
Romain Guy06882f82009-06-10 13:36:04 -07007274
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275 if (isWindowAnimating()) {
7276 return;
7277 }
7278
7279 if (localLOGV) Log.v(
7280 TAG, "Exit animation finished in " + this
7281 + ": remove=" + mRemoveOnExit);
7282 if (mSurface != null) {
7283 mDestroySurface.add(this);
7284 mDestroying = true;
7285 if (SHOW_TRANSACTIONS) Log.i(
7286 TAG, " SURFACE " + mSurface + ": HIDE (finishExit)");
7287 try {
7288 mSurface.hide();
7289 } catch (RuntimeException e) {
7290 Log.w(TAG, "Error hiding surface in " + this, e);
7291 }
7292 mLastHidden = true;
7293 mKeyWaiter.releasePendingPointerLocked(mSession);
7294 }
7295 mExiting = false;
7296 if (mRemoveOnExit) {
7297 mPendingRemove.add(this);
7298 mRemoveOnExit = false;
7299 }
7300 }
Romain Guy06882f82009-06-10 13:36:04 -07007301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007302 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
7303 if (dsdx < .99999f || dsdx > 1.00001f) return false;
7304 if (dtdy < .99999f || dtdy > 1.00001f) return false;
7305 if (dtdx < -.000001f || dtdx > .000001f) return false;
7306 if (dsdy < -.000001f || dsdy > .000001f) return false;
7307 return true;
7308 }
Romain Guy06882f82009-06-10 13:36:04 -07007309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007310 void computeShownFrameLocked() {
7311 final boolean selfTransformation = mHasLocalTransformation;
7312 Transformation attachedTransformation =
7313 (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
7314 ? mAttachedWindow.mTransformation : null;
7315 Transformation appTransformation =
7316 (mAppToken != null && mAppToken.hasTransformation)
7317 ? mAppToken.transformation : null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007318
7319 // Wallpapers are animated based on the "real" window they
7320 // are currently targeting.
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007321 if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07007322 && mWallpaperTarget != null) {
Dianne Hackborn5baba162009-09-23 17:01:12 -07007323 if (mWallpaperTarget.mHasLocalTransformation &&
7324 mWallpaperTarget.mAnimation != null &&
7325 !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007326 attachedTransformation = mWallpaperTarget.mTransformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07007327 if (DEBUG_WALLPAPER && attachedTransformation != null) {
7328 Log.v(TAG, "WP target attached xform: " + attachedTransformation);
7329 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007330 }
7331 if (mWallpaperTarget.mAppToken != null &&
Dianne Hackborn5baba162009-09-23 17:01:12 -07007332 mWallpaperTarget.mAppToken.hasTransformation &&
7333 mWallpaperTarget.mAppToken.animation != null &&
7334 !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007335 appTransformation = mWallpaperTarget.mAppToken.transformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07007336 if (DEBUG_WALLPAPER && appTransformation != null) {
7337 Log.v(TAG, "WP target app xform: " + appTransformation);
7338 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007339 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007340 }
7341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007342 if (selfTransformation || attachedTransformation != null
7343 || appTransformation != null) {
Romain Guy06882f82009-06-10 13:36:04 -07007344 // cache often used attributes locally
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007345 final Rect frame = mFrame;
7346 final float tmpFloats[] = mTmpFloats;
7347 final Matrix tmpMatrix = mTmpMatrix;
7348
7349 // Compute the desired transformation.
Dianne Hackborn65c23872009-09-18 17:47:02 -07007350 tmpMatrix.setTranslate(0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007351 if (selfTransformation) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007352 tmpMatrix.postConcat(mTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 }
Dianne Hackborn65c23872009-09-18 17:47:02 -07007354 tmpMatrix.postTranslate(frame.left, frame.top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007355 if (attachedTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007356 tmpMatrix.postConcat(attachedTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007357 }
7358 if (appTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007359 tmpMatrix.postConcat(appTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007360 }
7361
7362 // "convert" it into SurfaceFlinger's format
7363 // (a 2x2 matrix + an offset)
7364 // Here we must not transform the position of the surface
7365 // since it is already included in the transformation.
7366 //Log.i(TAG, "Transform: " + matrix);
Romain Guy06882f82009-06-10 13:36:04 -07007367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007368 tmpMatrix.getValues(tmpFloats);
7369 mDsDx = tmpFloats[Matrix.MSCALE_X];
7370 mDtDx = tmpFloats[Matrix.MSKEW_X];
7371 mDsDy = tmpFloats[Matrix.MSKEW_Y];
7372 mDtDy = tmpFloats[Matrix.MSCALE_Y];
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007373 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
7374 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007375 int w = frame.width();
7376 int h = frame.height();
7377 mShownFrame.set(x, y, x+w, y+h);
7378
7379 // Now set the alpha... but because our current hardware
7380 // can't do alpha transformation on a non-opaque surface,
7381 // turn it off if we are running an animation that is also
7382 // transforming since it is more important to have that
7383 // animation be smooth.
7384 mShownAlpha = mAlpha;
7385 if (!mLimitedAlphaCompositing
7386 || (!PixelFormat.formatHasAlpha(mAttrs.format)
7387 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
7388 && x == frame.left && y == frame.top))) {
7389 //Log.i(TAG, "Applying alpha transform");
7390 if (selfTransformation) {
7391 mShownAlpha *= mTransformation.getAlpha();
7392 }
7393 if (attachedTransformation != null) {
7394 mShownAlpha *= attachedTransformation.getAlpha();
7395 }
7396 if (appTransformation != null) {
7397 mShownAlpha *= appTransformation.getAlpha();
7398 }
7399 } else {
7400 //Log.i(TAG, "Not applying alpha transform");
7401 }
Romain Guy06882f82009-06-10 13:36:04 -07007402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403 if (localLOGV) Log.v(
7404 TAG, "Continuing animation in " + this +
7405 ": " + mShownFrame +
7406 ", alpha=" + mTransformation.getAlpha());
7407 return;
7408 }
Romain Guy06882f82009-06-10 13:36:04 -07007409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007410 mShownFrame.set(mFrame);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007411 if (mXOffset != 0 || mYOffset != 0) {
7412 mShownFrame.offset(mXOffset, mYOffset);
7413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 mShownAlpha = mAlpha;
7415 mDsDx = 1;
7416 mDtDx = 0;
7417 mDsDy = 0;
7418 mDtDy = 1;
7419 }
Romain Guy06882f82009-06-10 13:36:04 -07007420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007421 /**
7422 * Is this window visible? It is not visible if there is no
7423 * surface, or we are in the process of running an exit animation
7424 * that will remove the surface, or its app token has been hidden.
7425 */
7426 public boolean isVisibleLw() {
7427 final AppWindowToken atoken = mAppToken;
7428 return mSurface != null && mPolicyVisibility && !mAttachedHidden
7429 && (atoken == null || !atoken.hiddenRequested)
7430 && !mExiting && !mDestroying;
7431 }
7432
7433 /**
7434 * Is this window visible, ignoring its app token? It is not visible
7435 * if there is no surface, or we are in the process of running an exit animation
7436 * that will remove the surface.
7437 */
7438 public boolean isWinVisibleLw() {
7439 final AppWindowToken atoken = mAppToken;
7440 return mSurface != null && mPolicyVisibility && !mAttachedHidden
7441 && (atoken == null || !atoken.hiddenRequested || atoken.animating)
7442 && !mExiting && !mDestroying;
7443 }
7444
7445 /**
7446 * The same as isVisible(), but follows the current hidden state of
7447 * the associated app token, not the pending requested hidden state.
7448 */
7449 boolean isVisibleNow() {
7450 return mSurface != null && mPolicyVisibility && !mAttachedHidden
The Android Open Source Project10592532009-03-18 17:39:46 -07007451 && !mRootToken.hidden && !mExiting && !mDestroying;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007452 }
7453
7454 /**
7455 * Same as isVisible(), but we also count it as visible between the
7456 * call to IWindowSession.add() and the first relayout().
7457 */
7458 boolean isVisibleOrAdding() {
7459 final AppWindowToken atoken = mAppToken;
7460 return (mSurface != null
7461 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
7462 && mPolicyVisibility && !mAttachedHidden
7463 && (atoken == null || !atoken.hiddenRequested)
7464 && !mExiting && !mDestroying;
7465 }
7466
7467 /**
7468 * Is this window currently on-screen? It is on-screen either if it
7469 * is visible or it is currently running an animation before no longer
7470 * being visible.
7471 */
7472 boolean isOnScreen() {
7473 final AppWindowToken atoken = mAppToken;
7474 if (atoken != null) {
7475 return mSurface != null && mPolicyVisibility && !mDestroying
7476 && ((!mAttachedHidden && !atoken.hiddenRequested)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07007477 || mAnimation != null || atoken.animation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007478 } else {
7479 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn0cd48872009-08-13 18:51:59 -07007480 && (!mAttachedHidden || mAnimation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 }
7482 }
Romain Guy06882f82009-06-10 13:36:04 -07007483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007484 /**
7485 * Like isOnScreen(), but we don't return true if the window is part
7486 * of a transition that has not yet been started.
7487 */
7488 boolean isReadyForDisplay() {
Dianne Hackborna8f60182009-09-01 19:01:50 -07007489 if (mRootToken.waitingToShow &&
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007490 mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07007491 return false;
7492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007493 final AppWindowToken atoken = mAppToken;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07007494 final boolean animating = atoken != null
7495 ? (atoken.animation != null) : false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007496 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007497 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
7498 && !mRootToken.hidden)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07007499 || mAnimation != null || animating);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007500 }
7501
7502 /** Is the window or its container currently animating? */
7503 boolean isAnimating() {
7504 final WindowState attached = mAttachedWindow;
7505 final AppWindowToken atoken = mAppToken;
7506 return mAnimation != null
7507 || (attached != null && attached.mAnimation != null)
Romain Guy06882f82009-06-10 13:36:04 -07007508 || (atoken != null &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007509 (atoken.animation != null
7510 || atoken.inPendingTransaction));
7511 }
7512
7513 /** Is this window currently animating? */
7514 boolean isWindowAnimating() {
7515 return mAnimation != null;
7516 }
7517
7518 /**
7519 * Like isOnScreen, but returns false if the surface hasn't yet
7520 * been drawn.
7521 */
7522 public boolean isDisplayedLw() {
7523 final AppWindowToken atoken = mAppToken;
7524 return mSurface != null && mPolicyVisibility && !mDestroying
7525 && !mDrawPending && !mCommitDrawPending
7526 && ((!mAttachedHidden &&
7527 (atoken == null || !atoken.hiddenRequested))
7528 || mAnimating);
7529 }
7530
7531 public boolean fillsScreenLw(int screenWidth, int screenHeight,
7532 boolean shownFrame, boolean onlyOpaque) {
7533 if (mSurface == null) {
7534 return false;
7535 }
7536 if (mAppToken != null && !mAppToken.appFullscreen) {
7537 return false;
7538 }
7539 if (onlyOpaque && mAttrs.format != PixelFormat.OPAQUE) {
7540 return false;
7541 }
7542 final Rect frame = shownFrame ? mShownFrame : mFrame;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007543
7544 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
7545 return frame.left <= mCompatibleScreenFrame.left &&
7546 frame.top <= mCompatibleScreenFrame.top &&
7547 frame.right >= mCompatibleScreenFrame.right &&
7548 frame.bottom >= mCompatibleScreenFrame.bottom;
7549 } else {
7550 return frame.left <= 0 && frame.top <= 0
7551 && frame.right >= screenWidth
7552 && frame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007553 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007554 }
Romain Guy06882f82009-06-10 13:36:04 -07007555
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007556 /**
Dianne Hackborn25994b42009-09-04 14:21:19 -07007557 * Return true if the window is opaque and fully drawn. This indicates
7558 * it may obscure windows behind it.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007559 */
7560 boolean isOpaqueDrawn() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07007561 return (mAttrs.format == PixelFormat.OPAQUE
7562 || mAttrs.type == TYPE_WALLPAPER)
7563 && mSurface != null && mAnimation == null
7564 && (mAppToken == null || mAppToken.animation == null)
7565 && !mDrawPending && !mCommitDrawPending;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007566 }
7567
7568 boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
7569 return
7570 // only if the application is requesting compatible window
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07007571 (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
7572 // only if it's visible
7573 mHasDrawn && mViewVisibility == View.VISIBLE &&
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007574 // and only if the application fills the compatible screen
7575 mFrame.left <= mCompatibleScreenFrame.left &&
7576 mFrame.top <= mCompatibleScreenFrame.top &&
7577 mFrame.right >= mCompatibleScreenFrame.right &&
7578 mFrame.bottom >= mCompatibleScreenFrame.bottom &&
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07007579 // and starting window do not need background filler
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007580 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007581 }
7582
7583 boolean isFullscreen(int screenWidth, int screenHeight) {
7584 return mFrame.left <= 0 && mFrame.top <= 0 &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007585 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586 }
7587
7588 void removeLocked() {
7589 if (mAttachedWindow != null) {
7590 mAttachedWindow.mChildWindows.remove(this);
7591 }
7592 destroySurfaceLocked();
7593 mSession.windowRemovedLocked();
7594 try {
7595 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
7596 } catch (RuntimeException e) {
7597 // Ignore if it has already been removed (usually because
7598 // we are doing this as part of processing a death note.)
7599 }
7600 }
7601
7602 private class DeathRecipient implements IBinder.DeathRecipient {
7603 public void binderDied() {
7604 try {
7605 synchronized(mWindowMap) {
7606 WindowState win = windowForClientLocked(mSession, mClient);
7607 Log.i(TAG, "WIN DEATH: " + win);
7608 if (win != null) {
7609 removeWindowLocked(mSession, win);
7610 }
7611 }
7612 } catch (IllegalArgumentException ex) {
7613 // This will happen if the window has already been
7614 // removed.
7615 }
7616 }
7617 }
7618
7619 /** Returns true if this window desires key events. */
7620 public final boolean canReceiveKeys() {
7621 return isVisibleOrAdding()
7622 && (mViewVisibility == View.VISIBLE)
7623 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
7624 }
7625
7626 public boolean hasDrawnLw() {
7627 return mHasDrawn;
7628 }
7629
7630 public boolean showLw(boolean doAnimation) {
7631 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim) {
7632 mPolicyVisibility = true;
7633 mPolicyVisibilityAfterAnim = true;
7634 if (doAnimation) {
7635 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
7636 }
7637 requestAnimationLocked(0);
7638 return true;
7639 }
7640 return false;
7641 }
7642
7643 public boolean hideLw(boolean doAnimation) {
7644 boolean current = doAnimation ? mPolicyVisibilityAfterAnim
7645 : mPolicyVisibility;
7646 if (current) {
7647 if (doAnimation) {
7648 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
7649 if (mAnimation == null) {
7650 doAnimation = false;
7651 }
7652 }
7653 if (doAnimation) {
7654 mPolicyVisibilityAfterAnim = false;
7655 } else {
7656 mPolicyVisibilityAfterAnim = false;
7657 mPolicyVisibility = false;
7658 }
7659 requestAnimationLocked(0);
7660 return true;
7661 }
7662 return false;
7663 }
7664
7665 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007666 StringBuilder sb = new StringBuilder(64);
Romain Guy06882f82009-06-10 13:36:04 -07007667
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007668 pw.print(prefix); pw.print("mSession="); pw.print(mSession);
7669 pw.print(" mClient="); pw.println(mClient.asBinder());
7670 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
7671 if (mAttachedWindow != null || mLayoutAttached) {
7672 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
7673 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
7674 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007675 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
7676 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
7677 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007678 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
7679 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007680 }
7681 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
7682 pw.print(" mSubLayer="); pw.print(mSubLayer);
7683 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
7684 pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
7685 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
7686 pw.print("="); pw.print(mAnimLayer);
7687 pw.print(" mLastLayer="); pw.println(mLastLayer);
7688 if (mSurface != null) {
7689 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
7690 }
7691 pw.print(prefix); pw.print("mToken="); pw.println(mToken);
7692 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
7693 if (mAppToken != null) {
7694 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
7695 }
7696 if (mTargetAppToken != null) {
7697 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
7698 }
7699 pw.print(prefix); pw.print("mViewVisibility=0x");
7700 pw.print(Integer.toHexString(mViewVisibility));
7701 pw.print(" mLastHidden="); pw.print(mLastHidden);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007702 pw.print(" mHaveFrame="); pw.print(mHaveFrame);
7703 pw.print(" mObscured="); pw.println(mObscured);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007704 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
7705 pw.print(prefix); pw.print("mPolicyVisibility=");
7706 pw.print(mPolicyVisibility);
7707 pw.print(" mPolicyVisibilityAfterAnim=");
7708 pw.print(mPolicyVisibilityAfterAnim);
7709 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
7710 }
7711 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007712 pw.print(" h="); pw.println(mRequestedHeight);
7713 if (mXOffset != 0 || mYOffset != 0) {
7714 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
7715 pw.print(" y="); pw.println(mYOffset);
7716 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007717 pw.print(prefix); pw.print("mGivenContentInsets=");
7718 mGivenContentInsets.printShortString(pw);
7719 pw.print(" mGivenVisibleInsets=");
7720 mGivenVisibleInsets.printShortString(pw);
7721 pw.println();
7722 if (mTouchableInsets != 0 || mGivenInsetsPending) {
7723 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
7724 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
7725 }
7726 pw.print(prefix); pw.print("mShownFrame=");
7727 mShownFrame.printShortString(pw);
7728 pw.print(" last="); mLastShownFrame.printShortString(pw);
7729 pw.println();
7730 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
7731 pw.print(" last="); mLastFrame.printShortString(pw);
7732 pw.println();
7733 pw.print(prefix); pw.print("mContainingFrame=");
7734 mContainingFrame.printShortString(pw);
7735 pw.print(" mDisplayFrame=");
7736 mDisplayFrame.printShortString(pw);
7737 pw.println();
7738 pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
7739 pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
7740 pw.println();
7741 pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
7742 pw.print(" last="); mLastContentInsets.printShortString(pw);
7743 pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
7744 pw.print(" last="); mLastVisibleInsets.printShortString(pw);
7745 pw.println();
7746 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
7747 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
7748 pw.print(" mAlpha="); pw.print(mAlpha);
7749 pw.print(" mLastAlpha="); pw.println(mLastAlpha);
7750 }
7751 if (mAnimating || mLocalAnimating || mAnimationIsEntrance
7752 || mAnimation != null) {
7753 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
7754 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
7755 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
7756 pw.print(" mAnimation="); pw.println(mAnimation);
7757 }
7758 if (mHasTransformation || mHasLocalTransformation) {
7759 pw.print(prefix); pw.print("XForm: has=");
7760 pw.print(mHasTransformation);
7761 pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
7762 pw.print(" "); mTransformation.printShortString(pw);
7763 pw.println();
7764 }
7765 pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
7766 pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
7767 pw.print(" mReadyToShow="); pw.print(mReadyToShow);
7768 pw.print(" mHasDrawn="); pw.println(mHasDrawn);
7769 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
7770 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
7771 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
7772 pw.print(" mDestroying="); pw.print(mDestroying);
7773 pw.print(" mRemoved="); pw.println(mRemoved);
7774 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07007775 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007776 pw.print(prefix); pw.print("mOrientationChanging=");
7777 pw.print(mOrientationChanging);
Dianne Hackborn93e462b2009-09-15 22:50:40 -07007778 pw.print(" mAppFreezing="); pw.print(mAppFreezing);
7779 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007780 }
Mitsuru Oshima589cebe2009-07-22 20:38:58 -07007781 if (mHScale != 1 || mVScale != 1) {
7782 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
7783 pw.print(" mVScale="); pw.println(mVScale);
7784 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007785 if (mWallpaperX != -1 || mWallpaperY != -1) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007786 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
7787 pw.print(" mWallpaperY="); pw.println(mWallpaperY);
7788 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007789 }
7790
7791 @Override
7792 public String toString() {
7793 return "Window{"
7794 + Integer.toHexString(System.identityHashCode(this))
7795 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
7796 }
7797 }
Romain Guy06882f82009-06-10 13:36:04 -07007798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007799 // -------------------------------------------------------------
7800 // Window Token State
7801 // -------------------------------------------------------------
7802
7803 class WindowToken {
7804 // The actual token.
7805 final IBinder token;
7806
7807 // The type of window this token is for, as per WindowManager.LayoutParams.
7808 final int windowType;
Romain Guy06882f82009-06-10 13:36:04 -07007809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 // Set if this token was explicitly added by a client, so should
7811 // not be removed when all windows are removed.
7812 final boolean explicit;
Romain Guy06882f82009-06-10 13:36:04 -07007813
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007814 // For printing.
7815 String stringName;
Romain Guy06882f82009-06-10 13:36:04 -07007816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007817 // If this is an AppWindowToken, this is non-null.
7818 AppWindowToken appWindowToken;
Romain Guy06882f82009-06-10 13:36:04 -07007819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007820 // All of the windows associated with this token.
7821 final ArrayList<WindowState> windows = new ArrayList<WindowState>();
7822
7823 // Is key dispatching paused for this token?
7824 boolean paused = false;
7825
7826 // Should this token's windows be hidden?
7827 boolean hidden;
7828
7829 // Temporary for finding which tokens no longer have visible windows.
7830 boolean hasVisible;
7831
Dianne Hackborna8f60182009-09-01 19:01:50 -07007832 // Set to true when this token is in a pending transaction where it
7833 // will be shown.
7834 boolean waitingToShow;
7835
7836 // Set to true when this token is in a pending transaction where it
7837 // will be hidden.
7838 boolean waitingToHide;
7839
7840 // Set to true when this token is in a pending transaction where its
7841 // windows will be put to the bottom of the list.
7842 boolean sendingToBottom;
7843
7844 // Set to true when this token is in a pending transaction where its
7845 // windows will be put to the top of the list.
7846 boolean sendingToTop;
7847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007848 WindowToken(IBinder _token, int type, boolean _explicit) {
7849 token = _token;
7850 windowType = type;
7851 explicit = _explicit;
7852 }
7853
7854 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007855 pw.print(prefix); pw.print("token="); pw.println(token);
7856 pw.print(prefix); pw.print("windows="); pw.println(windows);
7857 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
7858 pw.print(" hidden="); pw.print(hidden);
7859 pw.print(" hasVisible="); pw.println(hasVisible);
Dianne Hackborna8f60182009-09-01 19:01:50 -07007860 if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
7861 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
7862 pw.print(" waitingToHide="); pw.print(waitingToHide);
7863 pw.print(" sendingToBottom="); pw.print(sendingToBottom);
7864 pw.print(" sendingToTop="); pw.println(sendingToTop);
7865 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007866 }
7867
7868 @Override
7869 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007870 if (stringName == null) {
7871 StringBuilder sb = new StringBuilder();
7872 sb.append("WindowToken{");
7873 sb.append(Integer.toHexString(System.identityHashCode(this)));
7874 sb.append(" token="); sb.append(token); sb.append('}');
7875 stringName = sb.toString();
7876 }
7877 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007878 }
7879 };
7880
7881 class AppWindowToken extends WindowToken {
7882 // Non-null only for application tokens.
7883 final IApplicationToken appToken;
7884
7885 // All of the windows and child windows that are included in this
7886 // application token. Note this list is NOT sorted!
7887 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
7888
7889 int groupId = -1;
7890 boolean appFullscreen;
7891 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Romain Guy06882f82009-06-10 13:36:04 -07007892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007893 // These are used for determining when all windows associated with
7894 // an activity have been drawn, so they can be made visible together
7895 // at the same time.
7896 int lastTransactionSequence = mTransactionSequence-1;
7897 int numInterestingWindows;
7898 int numDrawnWindows;
7899 boolean inPendingTransaction;
7900 boolean allDrawn;
Romain Guy06882f82009-06-10 13:36:04 -07007901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007902 // Is this token going to be hidden in a little while? If so, it
7903 // won't be taken into account for setting the screen orientation.
7904 boolean willBeHidden;
Romain Guy06882f82009-06-10 13:36:04 -07007905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 // Is this window's surface needed? This is almost like hidden, except
7907 // it will sometimes be true a little earlier: when the token has
7908 // been shown, but is still waiting for its app transition to execute
7909 // before making its windows shown.
7910 boolean hiddenRequested;
Romain Guy06882f82009-06-10 13:36:04 -07007911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007912 // Have we told the window clients to hide themselves?
7913 boolean clientHidden;
Romain Guy06882f82009-06-10 13:36:04 -07007914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 // Last visibility state we reported to the app token.
7916 boolean reportedVisible;
7917
7918 // Set to true when the token has been removed from the window mgr.
7919 boolean removed;
7920
7921 // Have we been asked to have this token keep the screen frozen?
7922 boolean freezingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07007923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007924 boolean animating;
7925 Animation animation;
7926 boolean hasTransformation;
7927 final Transformation transformation = new Transformation();
Romain Guy06882f82009-06-10 13:36:04 -07007928
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007929 // Offset to the window of all layers in the token, for use by
7930 // AppWindowToken animations.
7931 int animLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -07007932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007933 // Information about an application starting window if displayed.
7934 StartingData startingData;
7935 WindowState startingWindow;
7936 View startingView;
7937 boolean startingDisplayed;
7938 boolean startingMoved;
7939 boolean firstWindowDrawn;
7940
7941 AppWindowToken(IApplicationToken _token) {
7942 super(_token.asBinder(),
7943 WindowManager.LayoutParams.TYPE_APPLICATION, true);
7944 appWindowToken = this;
7945 appToken = _token;
7946 }
Romain Guy06882f82009-06-10 13:36:04 -07007947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007948 public void setAnimation(Animation anim) {
7949 if (localLOGV) Log.v(
7950 TAG, "Setting animation in " + this + ": " + anim);
7951 animation = anim;
7952 animating = false;
7953 anim.restrictDuration(MAX_ANIMATION_DURATION);
7954 anim.scaleCurrentDuration(mTransitionAnimationScale);
7955 int zorder = anim.getZAdjustment();
7956 int adj = 0;
7957 if (zorder == Animation.ZORDER_TOP) {
7958 adj = TYPE_LAYER_OFFSET;
7959 } else if (zorder == Animation.ZORDER_BOTTOM) {
7960 adj = -TYPE_LAYER_OFFSET;
7961 }
Romain Guy06882f82009-06-10 13:36:04 -07007962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007963 if (animLayerAdjustment != adj) {
7964 animLayerAdjustment = adj;
7965 updateLayers();
7966 }
7967 }
Romain Guy06882f82009-06-10 13:36:04 -07007968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007969 public void setDummyAnimation() {
7970 if (animation == null) {
7971 if (localLOGV) Log.v(
7972 TAG, "Setting dummy animation in " + this);
7973 animation = sDummyAnimation;
7974 }
7975 }
7976
7977 public void clearAnimation() {
7978 if (animation != null) {
7979 animation = null;
7980 animating = true;
7981 }
7982 }
Romain Guy06882f82009-06-10 13:36:04 -07007983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007984 void updateLayers() {
7985 final int N = allAppWindows.size();
7986 final int adj = animLayerAdjustment;
7987 for (int i=0; i<N; i++) {
7988 WindowState w = allAppWindows.get(i);
7989 w.mAnimLayer = w.mLayer + adj;
7990 if (DEBUG_LAYERS) Log.v(TAG, "Updating layer " + w + ": "
7991 + w.mAnimLayer);
7992 if (w == mInputMethodTarget) {
7993 setInputMethodAnimLayerAdjustment(adj);
7994 }
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007995 if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007996 setWallpaperAnimLayerAdjustmentLocked(adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007997 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007998 }
7999 }
Romain Guy06882f82009-06-10 13:36:04 -07008000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008001 void sendAppVisibilityToClients() {
8002 final int N = allAppWindows.size();
8003 for (int i=0; i<N; i++) {
8004 WindowState win = allAppWindows.get(i);
8005 if (win == startingWindow && clientHidden) {
8006 // Don't hide the starting window.
8007 continue;
8008 }
8009 try {
8010 if (DEBUG_VISIBILITY) Log.v(TAG,
8011 "Setting visibility of " + win + ": " + (!clientHidden));
8012 win.mClient.dispatchAppVisibility(!clientHidden);
8013 } catch (RemoteException e) {
8014 }
8015 }
8016 }
Romain Guy06882f82009-06-10 13:36:04 -07008017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008018 void showAllWindowsLocked() {
8019 final int NW = allAppWindows.size();
8020 for (int i=0; i<NW; i++) {
8021 WindowState w = allAppWindows.get(i);
8022 if (DEBUG_VISIBILITY) Log.v(TAG,
8023 "performing show on: " + w);
8024 w.performShowLocked();
8025 }
8026 }
Romain Guy06882f82009-06-10 13:36:04 -07008027
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008028 // This must be called while inside a transaction.
8029 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
8030 if (!mDisplayFrozen) {
8031 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07008032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008033 if (animation == sDummyAnimation) {
8034 // This guy is going to animate, but not yet. For now count
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008035 // it as not animating for purposes of scheduling transactions;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008036 // when it is really time to animate, this will be set to
8037 // a real animation and the next call will execute normally.
8038 return false;
8039 }
Romain Guy06882f82009-06-10 13:36:04 -07008040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 if ((allDrawn || animating || startingDisplayed) && animation != null) {
8042 if (!animating) {
8043 if (DEBUG_ANIM) Log.v(
8044 TAG, "Starting animation in " + this +
8045 " @ " + currentTime + ": dw=" + dw + " dh=" + dh
8046 + " scale=" + mTransitionAnimationScale
8047 + " allDrawn=" + allDrawn + " animating=" + animating);
8048 animation.initialize(dw, dh, dw, dh);
8049 animation.setStartTime(currentTime);
8050 animating = true;
8051 }
8052 transformation.clear();
8053 final boolean more = animation.getTransformation(
8054 currentTime, transformation);
8055 if (DEBUG_ANIM) Log.v(
8056 TAG, "Stepped animation in " + this +
8057 ": more=" + more + ", xform=" + transformation);
8058 if (more) {
8059 // we're done!
8060 hasTransformation = true;
8061 return true;
8062 }
8063 if (DEBUG_ANIM) Log.v(
8064 TAG, "Finished animation in " + this +
8065 " @ " + currentTime);
8066 animation = null;
8067 }
8068 } else if (animation != null) {
8069 // If the display is frozen, and there is a pending animation,
8070 // clear it and make sure we run the cleanup code.
8071 animating = true;
8072 animation = null;
8073 }
8074
8075 hasTransformation = false;
Romain Guy06882f82009-06-10 13:36:04 -07008076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008077 if (!animating) {
8078 return false;
8079 }
8080
8081 clearAnimation();
8082 animating = false;
8083 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
8084 moveInputMethodWindowsIfNeededLocked(true);
8085 }
Romain Guy06882f82009-06-10 13:36:04 -07008086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008087 if (DEBUG_ANIM) Log.v(
8088 TAG, "Animation done in " + this
8089 + ": reportedVisible=" + reportedVisible);
8090
8091 transformation.clear();
8092 if (animLayerAdjustment != 0) {
8093 animLayerAdjustment = 0;
8094 updateLayers();
8095 }
Romain Guy06882f82009-06-10 13:36:04 -07008096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008097 final int N = windows.size();
8098 for (int i=0; i<N; i++) {
8099 ((WindowState)windows.get(i)).finishExit();
8100 }
8101 updateReportedVisibilityLocked();
Romain Guy06882f82009-06-10 13:36:04 -07008102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008103 return false;
8104 }
8105
8106 void updateReportedVisibilityLocked() {
8107 if (appToken == null) {
8108 return;
8109 }
Romain Guy06882f82009-06-10 13:36:04 -07008110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008111 int numInteresting = 0;
8112 int numVisible = 0;
8113 boolean nowGone = true;
Romain Guy06882f82009-06-10 13:36:04 -07008114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008115 if (DEBUG_VISIBILITY) Log.v(TAG, "Update reported visibility: " + this);
8116 final int N = allAppWindows.size();
8117 for (int i=0; i<N; i++) {
8118 WindowState win = allAppWindows.get(i);
8119 if (win == startingWindow || win.mAppFreezing) {
8120 continue;
8121 }
8122 if (DEBUG_VISIBILITY) {
8123 Log.v(TAG, "Win " + win + ": isDisplayed="
8124 + win.isDisplayedLw()
8125 + ", isAnimating=" + win.isAnimating());
8126 if (!win.isDisplayedLw()) {
8127 Log.v(TAG, "Not displayed: s=" + win.mSurface
8128 + " pv=" + win.mPolicyVisibility
8129 + " dp=" + win.mDrawPending
8130 + " cdp=" + win.mCommitDrawPending
8131 + " ah=" + win.mAttachedHidden
8132 + " th="
8133 + (win.mAppToken != null
8134 ? win.mAppToken.hiddenRequested : false)
8135 + " a=" + win.mAnimating);
8136 }
8137 }
8138 numInteresting++;
8139 if (win.isDisplayedLw()) {
8140 if (!win.isAnimating()) {
8141 numVisible++;
8142 }
8143 nowGone = false;
8144 } else if (win.isAnimating()) {
8145 nowGone = false;
8146 }
8147 }
Romain Guy06882f82009-06-10 13:36:04 -07008148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008149 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
8150 if (DEBUG_VISIBILITY) Log.v(TAG, "VIS " + this + ": interesting="
8151 + numInteresting + " visible=" + numVisible);
8152 if (nowVisible != reportedVisible) {
8153 if (DEBUG_VISIBILITY) Log.v(
8154 TAG, "Visibility changed in " + this
8155 + ": vis=" + nowVisible);
8156 reportedVisible = nowVisible;
8157 Message m = mH.obtainMessage(
8158 H.REPORT_APPLICATION_TOKEN_WINDOWS,
8159 nowVisible ? 1 : 0,
8160 nowGone ? 1 : 0,
8161 this);
8162 mH.sendMessage(m);
8163 }
8164 }
Romain Guy06882f82009-06-10 13:36:04 -07008165
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07008166 WindowState findMainWindow() {
8167 int j = windows.size();
8168 while (j > 0) {
8169 j--;
8170 WindowState win = windows.get(j);
8171 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
8172 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
8173 return win;
8174 }
8175 }
8176 return null;
8177 }
8178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008179 void dump(PrintWriter pw, String prefix) {
8180 super.dump(pw, prefix);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008181 if (appToken != null) {
8182 pw.print(prefix); pw.println("app=true");
8183 }
8184 if (allAppWindows.size() > 0) {
8185 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
8186 }
8187 pw.print(prefix); pw.print("groupId="); pw.print(groupId);
Dianne Hackborna8f60182009-09-01 19:01:50 -07008188 pw.print(" appFullscreen="); pw.print(appFullscreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008189 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
8190 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
8191 pw.print(" clientHidden="); pw.print(clientHidden);
8192 pw.print(" willBeHidden="); pw.print(willBeHidden);
8193 pw.print(" reportedVisible="); pw.println(reportedVisible);
8194 if (paused || freezingScreen) {
8195 pw.print(prefix); pw.print("paused="); pw.print(paused);
8196 pw.print(" freezingScreen="); pw.println(freezingScreen);
8197 }
8198 if (numInterestingWindows != 0 || numDrawnWindows != 0
8199 || inPendingTransaction || allDrawn) {
8200 pw.print(prefix); pw.print("numInterestingWindows=");
8201 pw.print(numInterestingWindows);
8202 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
8203 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
8204 pw.print(" allDrawn="); pw.println(allDrawn);
8205 }
8206 if (animating || animation != null) {
8207 pw.print(prefix); pw.print("animating="); pw.print(animating);
8208 pw.print(" animation="); pw.println(animation);
8209 }
8210 if (animLayerAdjustment != 0) {
8211 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
8212 }
8213 if (hasTransformation) {
8214 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
8215 pw.print(" transformation="); transformation.printShortString(pw);
8216 pw.println();
8217 }
8218 if (startingData != null || removed || firstWindowDrawn) {
8219 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
8220 pw.print(" removed="); pw.print(removed);
8221 pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
8222 }
8223 if (startingWindow != null || startingView != null
8224 || startingDisplayed || startingMoved) {
8225 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
8226 pw.print(" startingView="); pw.print(startingView);
8227 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
8228 pw.print(" startingMoved"); pw.println(startingMoved);
8229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008230 }
8231
8232 @Override
8233 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008234 if (stringName == null) {
8235 StringBuilder sb = new StringBuilder();
8236 sb.append("AppWindowToken{");
8237 sb.append(Integer.toHexString(System.identityHashCode(this)));
8238 sb.append(" token="); sb.append(token); sb.append('}');
8239 stringName = sb.toString();
8240 }
8241 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008242 }
8243 }
Romain Guy06882f82009-06-10 13:36:04 -07008244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008245 // -------------------------------------------------------------
8246 // DummyAnimation
8247 // -------------------------------------------------------------
8248
8249 // This is an animation that does nothing: it just immediately finishes
8250 // itself every time it is called. It is used as a stub animation in cases
8251 // where we want to synchronize multiple things that may be animating.
8252 static final class DummyAnimation extends Animation {
8253 public boolean getTransformation(long currentTime, Transformation outTransformation) {
8254 return false;
8255 }
8256 }
8257 static final Animation sDummyAnimation = new DummyAnimation();
Romain Guy06882f82009-06-10 13:36:04 -07008258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008259 // -------------------------------------------------------------
8260 // Async Handler
8261 // -------------------------------------------------------------
8262
8263 static final class StartingData {
8264 final String pkg;
8265 final int theme;
8266 final CharSequence nonLocalizedLabel;
8267 final int labelRes;
8268 final int icon;
Romain Guy06882f82009-06-10 13:36:04 -07008269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270 StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
8271 int _labelRes, int _icon) {
8272 pkg = _pkg;
8273 theme = _theme;
8274 nonLocalizedLabel = _nonLocalizedLabel;
8275 labelRes = _labelRes;
8276 icon = _icon;
8277 }
8278 }
8279
8280 private final class H extends Handler {
8281 public static final int REPORT_FOCUS_CHANGE = 2;
8282 public static final int REPORT_LOSING_FOCUS = 3;
8283 public static final int ANIMATE = 4;
8284 public static final int ADD_STARTING = 5;
8285 public static final int REMOVE_STARTING = 6;
8286 public static final int FINISHED_STARTING = 7;
8287 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008288 public static final int WINDOW_FREEZE_TIMEOUT = 11;
8289 public static final int HOLD_SCREEN_CHANGED = 12;
8290 public static final int APP_TRANSITION_TIMEOUT = 13;
8291 public static final int PERSIST_ANIMATION_SCALE = 14;
8292 public static final int FORCE_GC = 15;
8293 public static final int ENABLE_SCREEN = 16;
8294 public static final int APP_FREEZE_TIMEOUT = 17;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07008295 public static final int COMPUTE_AND_SEND_NEW_CONFIGURATION = 18;
Romain Guy06882f82009-06-10 13:36:04 -07008296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008297 private Session mLastReportedHold;
Romain Guy06882f82009-06-10 13:36:04 -07008298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008299 public H() {
8300 }
Romain Guy06882f82009-06-10 13:36:04 -07008301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008302 @Override
8303 public void handleMessage(Message msg) {
8304 switch (msg.what) {
8305 case REPORT_FOCUS_CHANGE: {
8306 WindowState lastFocus;
8307 WindowState newFocus;
Romain Guy06882f82009-06-10 13:36:04 -07008308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008309 synchronized(mWindowMap) {
8310 lastFocus = mLastFocus;
8311 newFocus = mCurrentFocus;
8312 if (lastFocus == newFocus) {
8313 // Focus is not changing, so nothing to do.
8314 return;
8315 }
8316 mLastFocus = newFocus;
8317 //Log.i(TAG, "Focus moving from " + lastFocus
8318 // + " to " + newFocus);
8319 if (newFocus != null && lastFocus != null
8320 && !newFocus.isDisplayedLw()) {
8321 //Log.i(TAG, "Delaying loss of focus...");
8322 mLosingFocus.add(lastFocus);
8323 lastFocus = null;
8324 }
8325 }
8326
8327 if (lastFocus != newFocus) {
8328 //System.out.println("Changing focus from " + lastFocus
8329 // + " to " + newFocus);
8330 if (newFocus != null) {
8331 try {
8332 //Log.i(TAG, "Gaining focus: " + newFocus);
8333 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
8334 } catch (RemoteException e) {
8335 // Ignore if process has died.
8336 }
8337 }
8338
8339 if (lastFocus != null) {
8340 try {
8341 //Log.i(TAG, "Losing focus: " + lastFocus);
8342 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
8343 } catch (RemoteException e) {
8344 // Ignore if process has died.
8345 }
8346 }
8347 }
8348 } break;
8349
8350 case REPORT_LOSING_FOCUS: {
8351 ArrayList<WindowState> losers;
Romain Guy06882f82009-06-10 13:36:04 -07008352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008353 synchronized(mWindowMap) {
8354 losers = mLosingFocus;
8355 mLosingFocus = new ArrayList<WindowState>();
8356 }
8357
8358 final int N = losers.size();
8359 for (int i=0; i<N; i++) {
8360 try {
8361 //Log.i(TAG, "Losing delayed focus: " + losers.get(i));
8362 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
8363 } catch (RemoteException e) {
8364 // Ignore if process has died.
8365 }
8366 }
8367 } break;
8368
8369 case ANIMATE: {
8370 synchronized(mWindowMap) {
8371 mAnimationPending = false;
8372 performLayoutAndPlaceSurfacesLocked();
8373 }
8374 } break;
8375
8376 case ADD_STARTING: {
8377 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8378 final StartingData sd = wtoken.startingData;
8379
8380 if (sd == null) {
8381 // Animation has been canceled... do nothing.
8382 return;
8383 }
Romain Guy06882f82009-06-10 13:36:04 -07008384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008385 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Add starting "
8386 + wtoken + ": pkg=" + sd.pkg);
Romain Guy06882f82009-06-10 13:36:04 -07008387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008388 View view = null;
8389 try {
8390 view = mPolicy.addStartingWindow(
8391 wtoken.token, sd.pkg,
8392 sd.theme, sd.nonLocalizedLabel, sd.labelRes,
8393 sd.icon);
8394 } catch (Exception e) {
8395 Log.w(TAG, "Exception when adding starting window", e);
8396 }
8397
8398 if (view != null) {
8399 boolean abort = false;
8400
8401 synchronized(mWindowMap) {
8402 if (wtoken.removed || wtoken.startingData == null) {
8403 // If the window was successfully added, then
8404 // we need to remove it.
8405 if (wtoken.startingWindow != null) {
8406 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
8407 "Aborted starting " + wtoken
8408 + ": removed=" + wtoken.removed
8409 + " startingData=" + wtoken.startingData);
8410 wtoken.startingWindow = null;
8411 wtoken.startingData = null;
8412 abort = true;
8413 }
8414 } else {
8415 wtoken.startingView = view;
8416 }
8417 if (DEBUG_STARTING_WINDOW && !abort) Log.v(TAG,
8418 "Added starting " + wtoken
8419 + ": startingWindow="
8420 + wtoken.startingWindow + " startingView="
8421 + wtoken.startingView);
8422 }
8423
8424 if (abort) {
8425 try {
8426 mPolicy.removeStartingWindow(wtoken.token, view);
8427 } catch (Exception e) {
8428 Log.w(TAG, "Exception when removing starting window", e);
8429 }
8430 }
8431 }
8432 } break;
8433
8434 case REMOVE_STARTING: {
8435 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8436 IBinder token = null;
8437 View view = null;
8438 synchronized (mWindowMap) {
8439 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Remove starting "
8440 + wtoken + ": startingWindow="
8441 + wtoken.startingWindow + " startingView="
8442 + wtoken.startingView);
8443 if (wtoken.startingWindow != null) {
8444 view = wtoken.startingView;
8445 token = wtoken.token;
8446 wtoken.startingData = null;
8447 wtoken.startingView = null;
8448 wtoken.startingWindow = null;
8449 }
8450 }
8451 if (view != null) {
8452 try {
8453 mPolicy.removeStartingWindow(token, view);
8454 } catch (Exception e) {
8455 Log.w(TAG, "Exception when removing starting window", e);
8456 }
8457 }
8458 } break;
8459
8460 case FINISHED_STARTING: {
8461 IBinder token = null;
8462 View view = null;
8463 while (true) {
8464 synchronized (mWindowMap) {
8465 final int N = mFinishedStarting.size();
8466 if (N <= 0) {
8467 break;
8468 }
8469 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
8470
8471 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
8472 "Finished starting " + wtoken
8473 + ": startingWindow=" + wtoken.startingWindow
8474 + " startingView=" + wtoken.startingView);
8475
8476 if (wtoken.startingWindow == null) {
8477 continue;
8478 }
8479
8480 view = wtoken.startingView;
8481 token = wtoken.token;
8482 wtoken.startingData = null;
8483 wtoken.startingView = null;
8484 wtoken.startingWindow = null;
8485 }
8486
8487 try {
8488 mPolicy.removeStartingWindow(token, view);
8489 } catch (Exception e) {
8490 Log.w(TAG, "Exception when removing starting window", e);
8491 }
8492 }
8493 } break;
8494
8495 case REPORT_APPLICATION_TOKEN_WINDOWS: {
8496 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8497
8498 boolean nowVisible = msg.arg1 != 0;
8499 boolean nowGone = msg.arg2 != 0;
8500
8501 try {
8502 if (DEBUG_VISIBILITY) Log.v(
8503 TAG, "Reporting visible in " + wtoken
8504 + " visible=" + nowVisible
8505 + " gone=" + nowGone);
8506 if (nowVisible) {
8507 wtoken.appToken.windowsVisible();
8508 } else {
8509 wtoken.appToken.windowsGone();
8510 }
8511 } catch (RemoteException ex) {
8512 }
8513 } break;
Romain Guy06882f82009-06-10 13:36:04 -07008514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008515 case WINDOW_FREEZE_TIMEOUT: {
8516 synchronized (mWindowMap) {
8517 Log.w(TAG, "Window freeze timeout expired.");
8518 int i = mWindows.size();
8519 while (i > 0) {
8520 i--;
8521 WindowState w = (WindowState)mWindows.get(i);
8522 if (w.mOrientationChanging) {
8523 w.mOrientationChanging = false;
8524 Log.w(TAG, "Force clearing orientation change: " + w);
8525 }
8526 }
8527 performLayoutAndPlaceSurfacesLocked();
8528 }
8529 break;
8530 }
Romain Guy06882f82009-06-10 13:36:04 -07008531
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 case HOLD_SCREEN_CHANGED: {
8533 Session oldHold;
8534 Session newHold;
8535 synchronized (mWindowMap) {
8536 oldHold = mLastReportedHold;
8537 newHold = (Session)msg.obj;
8538 mLastReportedHold = newHold;
8539 }
Romain Guy06882f82009-06-10 13:36:04 -07008540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008541 if (oldHold != newHold) {
8542 try {
8543 if (oldHold != null) {
8544 mBatteryStats.noteStopWakelock(oldHold.mUid,
8545 "window",
8546 BatteryStats.WAKE_TYPE_WINDOW);
8547 }
8548 if (newHold != null) {
8549 mBatteryStats.noteStartWakelock(newHold.mUid,
8550 "window",
8551 BatteryStats.WAKE_TYPE_WINDOW);
8552 }
8553 } catch (RemoteException e) {
8554 }
8555 }
8556 break;
8557 }
Romain Guy06882f82009-06-10 13:36:04 -07008558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008559 case APP_TRANSITION_TIMEOUT: {
8560 synchronized (mWindowMap) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07008561 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008562 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
8563 "*** APP TRANSITION TIMEOUT");
8564 mAppTransitionReady = true;
8565 mAppTransitionTimeout = true;
8566 performLayoutAndPlaceSurfacesLocked();
8567 }
8568 }
8569 break;
8570 }
Romain Guy06882f82009-06-10 13:36:04 -07008571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008572 case PERSIST_ANIMATION_SCALE: {
8573 Settings.System.putFloat(mContext.getContentResolver(),
8574 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
8575 Settings.System.putFloat(mContext.getContentResolver(),
8576 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
8577 break;
8578 }
Romain Guy06882f82009-06-10 13:36:04 -07008579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008580 case FORCE_GC: {
8581 synchronized(mWindowMap) {
8582 if (mAnimationPending) {
8583 // If we are animating, don't do the gc now but
8584 // delay a bit so we don't interrupt the animation.
8585 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
8586 2000);
8587 return;
8588 }
8589 // If we are currently rotating the display, it will
8590 // schedule a new message when done.
8591 if (mDisplayFrozen) {
8592 return;
8593 }
8594 mFreezeGcPending = 0;
8595 }
8596 Runtime.getRuntime().gc();
8597 break;
8598 }
Romain Guy06882f82009-06-10 13:36:04 -07008599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008600 case ENABLE_SCREEN: {
8601 performEnableScreen();
8602 break;
8603 }
Romain Guy06882f82009-06-10 13:36:04 -07008604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008605 case APP_FREEZE_TIMEOUT: {
8606 synchronized (mWindowMap) {
8607 Log.w(TAG, "App freeze timeout expired.");
8608 int i = mAppTokens.size();
8609 while (i > 0) {
8610 i--;
8611 AppWindowToken tok = mAppTokens.get(i);
8612 if (tok.freezingScreen) {
8613 Log.w(TAG, "Force clearing freeze: " + tok);
8614 unsetAppFreezingScreenLocked(tok, true, true);
8615 }
8616 }
8617 }
8618 break;
8619 }
Romain Guy06882f82009-06-10 13:36:04 -07008620
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07008621 case COMPUTE_AND_SEND_NEW_CONFIGURATION: {
Dianne Hackborncfaef692009-06-15 14:24:44 -07008622 if (updateOrientationFromAppTokensUnchecked(null, null) != null) {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07008623 sendNewConfiguration();
8624 }
8625 break;
8626 }
Romain Guy06882f82009-06-10 13:36:04 -07008627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008628 }
8629 }
8630 }
8631
8632 // -------------------------------------------------------------
8633 // IWindowManager API
8634 // -------------------------------------------------------------
8635
8636 public IWindowSession openSession(IInputMethodClient client,
8637 IInputContext inputContext) {
8638 if (client == null) throw new IllegalArgumentException("null client");
8639 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
8640 return new Session(client, inputContext);
8641 }
8642
8643 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
8644 synchronized (mWindowMap) {
8645 // The focus for the client is the window immediately below
8646 // where we would place the input method window.
8647 int idx = findDesiredInputMethodWindowIndexLocked(false);
8648 WindowState imFocus;
8649 if (idx > 0) {
8650 imFocus = (WindowState)mWindows.get(idx-1);
8651 if (imFocus != null) {
8652 if (imFocus.mSession.mClient != null &&
8653 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
8654 return true;
8655 }
8656 }
8657 }
8658 }
8659 return false;
8660 }
Romain Guy06882f82009-06-10 13:36:04 -07008661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008662 // -------------------------------------------------------------
8663 // Internals
8664 // -------------------------------------------------------------
8665
8666 final WindowState windowForClientLocked(Session session, IWindow client) {
8667 return windowForClientLocked(session, client.asBinder());
8668 }
Romain Guy06882f82009-06-10 13:36:04 -07008669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008670 final WindowState windowForClientLocked(Session session, IBinder client) {
8671 WindowState win = mWindowMap.get(client);
8672 if (localLOGV) Log.v(
8673 TAG, "Looking up client " + client + ": " + win);
8674 if (win == null) {
8675 RuntimeException ex = new RuntimeException();
8676 Log.w(TAG, "Requested window " + client + " does not exist", ex);
8677 return null;
8678 }
8679 if (session != null && win.mSession != session) {
8680 RuntimeException ex = new RuntimeException();
8681 Log.w(TAG, "Requested window " + client + " is in session " +
8682 win.mSession + ", not " + session, ex);
8683 return null;
8684 }
8685
8686 return win;
8687 }
8688
Dianne Hackborna8f60182009-09-01 19:01:50 -07008689 final void rebuildAppWindowListLocked() {
8690 int NW = mWindows.size();
8691 int i;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07008692 int numRemoved = 0;
Dianne Hackborna8f60182009-09-01 19:01:50 -07008693
8694 // First remove all existing app windows.
8695 i=0;
8696 while (i < NW) {
8697 if (((WindowState)mWindows.get(i)).mAppToken != null) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07008698 WindowState win = (WindowState)mWindows.remove(i);
8699 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
8700 "Rebuild removing window: " + win);
Dianne Hackborna8f60182009-09-01 19:01:50 -07008701 NW--;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07008702 numRemoved++;
Dianne Hackborna8f60182009-09-01 19:01:50 -07008703 continue;
8704 }
8705 i++;
8706 }
8707
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07008708 // First add all of the exiting app tokens... these are no longer
8709 // in the main app list, but still have windows shown. We put them
8710 // in the back because now that the animation is over we no longer
8711 // will care about them.
8712 int NT = mExitingAppTokens.size();
Dianne Hackborna8f60182009-09-01 19:01:50 -07008713 i = 0;
8714 for (int j=0; j<NT; j++) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07008715 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
8716 }
8717
8718 // And add in the still active app tokens in Z order.
8719 NT = mAppTokens.size();
8720 for (int j=0; j<NT; j++) {
8721 i = reAddAppWindowsLocked(i, mAppTokens.get(j));
Dianne Hackborna8f60182009-09-01 19:01:50 -07008722 }
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07008723
8724 if (i != numRemoved) {
8725 Log.w(TAG, "Rebuild removed " + numRemoved
8726 + " windows but added " + i);
8727 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07008728 }
8729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008730 private final void assignLayersLocked() {
8731 int N = mWindows.size();
8732 int curBaseLayer = 0;
8733 int curLayer = 0;
8734 int i;
Romain Guy06882f82009-06-10 13:36:04 -07008735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008736 for (i=0; i<N; i++) {
8737 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008738 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
8739 || (i > 0 && w.mIsWallpaper)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008740 curLayer += WINDOW_LAYER_MULTIPLIER;
8741 w.mLayer = curLayer;
8742 } else {
8743 curBaseLayer = curLayer = w.mBaseLayer;
8744 w.mLayer = curLayer;
8745 }
8746 if (w.mTargetAppToken != null) {
8747 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
8748 } else if (w.mAppToken != null) {
8749 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
8750 } else {
8751 w.mAnimLayer = w.mLayer;
8752 }
8753 if (w.mIsImWindow) {
8754 w.mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008755 } else if (w.mIsWallpaper) {
8756 w.mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 }
8758 if (DEBUG_LAYERS) Log.v(TAG, "Assign layer " + w + ": "
8759 + w.mAnimLayer);
8760 //System.out.println(
8761 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
8762 }
8763 }
8764
8765 private boolean mInLayout = false;
8766 private final void performLayoutAndPlaceSurfacesLocked() {
8767 if (mInLayout) {
Dave Bortcfe65242009-04-09 14:51:04 -07008768 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008769 throw new RuntimeException("Recursive call!");
8770 }
8771 Log.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
8772 return;
8773 }
8774
8775 boolean recoveringMemory = false;
8776 if (mForceRemoves != null) {
8777 recoveringMemory = true;
8778 // Wait a little it for things to settle down, and off we go.
8779 for (int i=0; i<mForceRemoves.size(); i++) {
8780 WindowState ws = mForceRemoves.get(i);
8781 Log.i(TAG, "Force removing: " + ws);
8782 removeWindowInnerLocked(ws.mSession, ws);
8783 }
8784 mForceRemoves = null;
8785 Log.w(TAG, "Due to memory failure, waiting a bit for next layout");
8786 Object tmp = new Object();
8787 synchronized (tmp) {
8788 try {
8789 tmp.wait(250);
8790 } catch (InterruptedException e) {
8791 }
8792 }
8793 }
Romain Guy06882f82009-06-10 13:36:04 -07008794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008795 mInLayout = true;
8796 try {
8797 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
Romain Guy06882f82009-06-10 13:36:04 -07008798
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008799 int i = mPendingRemove.size()-1;
8800 if (i >= 0) {
8801 while (i >= 0) {
8802 WindowState w = mPendingRemove.get(i);
8803 removeWindowInnerLocked(w.mSession, w);
8804 i--;
8805 }
8806 mPendingRemove.clear();
8807
8808 mInLayout = false;
8809 assignLayersLocked();
8810 mLayoutNeeded = true;
8811 performLayoutAndPlaceSurfacesLocked();
8812
8813 } else {
8814 mInLayout = false;
8815 if (mLayoutNeeded) {
8816 requestAnimationLocked(0);
8817 }
8818 }
8819 } catch (RuntimeException e) {
8820 mInLayout = false;
8821 Log.e(TAG, "Unhandled exception while layout out windows", e);
8822 }
8823 }
8824
8825 private final void performLayoutLockedInner() {
8826 final int dw = mDisplay.getWidth();
8827 final int dh = mDisplay.getHeight();
8828
8829 final int N = mWindows.size();
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008830 int repeats = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008831 int i;
8832
8833 // FIRST LOOP: Perform a layout, if needed.
Romain Guy06882f82009-06-10 13:36:04 -07008834
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008835 while (mLayoutNeeded) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008836 mPolicy.beginLayoutLw(dw, dh);
8837
8838 // First perform layout of any root windows (not attached
8839 // to another window).
8840 int topAttached = -1;
8841 for (i = N-1; i >= 0; i--) {
8842 WindowState win = (WindowState) mWindows.get(i);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008843
8844 // Don't do layout of a window if it is not visible, or
8845 // soon won't be visible, to avoid wasting time and funky
8846 // changes while a window is animating away.
8847 final AppWindowToken atoken = win.mAppToken;
8848 final boolean gone = win.mViewVisibility == View.GONE
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008849 || !win.mRelayoutCalled
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008850 || win.mRootToken.hidden
8851 || (atoken != null && atoken.hiddenRequested)
8852 || !win.mPolicyVisibility
8853 || win.mAttachedHidden
8854 || win.mExiting || win.mDestroying;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008855
8856 // If this view is GONE, then skip it -- keep the current
8857 // frame, and let the caller know so they can ignore it
8858 // if they want. (We do the normal layout for INVISIBLE
8859 // windows, since that means "perform layout as normal,
8860 // just don't display").
8861 if (!gone || !win.mHaveFrame) {
8862 if (!win.mLayoutAttached) {
8863 mPolicy.layoutWindowLw(win, win.mAttrs, null);
8864 } else {
8865 if (topAttached < 0) topAttached = i;
8866 }
8867 }
8868 }
Romain Guy06882f82009-06-10 13:36:04 -07008869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008870 // Now perform layout of attached windows, which usually
8871 // depend on the position of the window they are attached to.
8872 // XXX does not deal with windows that are attached to windows
8873 // that are themselves attached.
8874 for (i = topAttached; i >= 0; i--) {
8875 WindowState win = (WindowState) mWindows.get(i);
8876
8877 // If this view is GONE, then skip it -- keep the current
8878 // frame, and let the caller know so they can ignore it
8879 // if they want. (We do the normal layout for INVISIBLE
8880 // windows, since that means "perform layout as normal,
8881 // just don't display").
8882 if (win.mLayoutAttached) {
8883 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
8884 || !win.mHaveFrame) {
8885 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
8886 }
8887 }
8888 }
8889
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07008890 int changes = mPolicy.finishLayoutLw();
8891 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
8892 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
8893 assignLayersLocked();
8894 }
8895 }
8896 if (changes == 0) {
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008897 mLayoutNeeded = false;
8898 } else if (repeats > 2) {
8899 Log.w(TAG, "Layout repeat aborted after too many iterations");
8900 mLayoutNeeded = false;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07008901 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
8902 Configuration newConfig = updateOrientationFromAppTokensLocked(
8903 null, null);
8904 if (newConfig != null) {
8905 mLayoutNeeded = true;
8906 mH.sendEmptyMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION);
8907 }
8908 }
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008909 } else {
8910 repeats++;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07008911 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
8912 Configuration newConfig = updateOrientationFromAppTokensLocked(
8913 null, null);
8914 if (newConfig != null) {
8915 mH.sendEmptyMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION);
8916 }
8917 }
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07008918 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008919 }
8920 }
Romain Guy06882f82009-06-10 13:36:04 -07008921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008922 private final void performLayoutAndPlaceSurfacesLockedInner(
8923 boolean recoveringMemory) {
8924 final long currentTime = SystemClock.uptimeMillis();
8925 final int dw = mDisplay.getWidth();
8926 final int dh = mDisplay.getHeight();
8927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 int i;
8929
8930 // FIRST LOOP: Perform a layout, if needed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008931 performLayoutLockedInner();
Romain Guy06882f82009-06-10 13:36:04 -07008932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008933 if (mFxSession == null) {
8934 mFxSession = new SurfaceSession();
8935 }
Romain Guy06882f82009-06-10 13:36:04 -07008936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008937 if (SHOW_TRANSACTIONS) Log.i(TAG, ">>> OPEN TRANSACTION");
8938
8939 // Initialize state of exiting tokens.
8940 for (i=mExitingTokens.size()-1; i>=0; i--) {
8941 mExitingTokens.get(i).hasVisible = false;
8942 }
8943
8944 // Initialize state of exiting applications.
8945 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
8946 mExitingAppTokens.get(i).hasVisible = false;
8947 }
8948
8949 // SECOND LOOP: Execute animations and update visibility of windows.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008950 boolean orientationChangeComplete = true;
8951 Session holdScreen = null;
8952 float screenBrightness = -1;
8953 boolean focusDisplayed = false;
8954 boolean animating = false;
8955
8956 Surface.openTransaction();
8957 try {
8958 boolean restart;
8959
8960 do {
8961 final int transactionSequence = ++mTransactionSequence;
8962
8963 // Update animations of all applications, including those
8964 // associated with exiting/removed apps
8965 boolean tokensAnimating = false;
8966 final int NAT = mAppTokens.size();
8967 for (i=0; i<NAT; i++) {
8968 if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
8969 tokensAnimating = true;
8970 }
8971 }
8972 final int NEAT = mExitingAppTokens.size();
8973 for (i=0; i<NEAT; i++) {
8974 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
8975 tokensAnimating = true;
8976 }
8977 }
8978
8979 animating = tokensAnimating;
8980 restart = false;
8981
8982 boolean tokenMayBeDrawn = false;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07008983 boolean wallpaperMayChange = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008984
8985 mPolicy.beginAnimationLw(dw, dh);
8986
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07008987 final int N = mWindows.size();
8988
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008989 for (i=N-1; i>=0; i--) {
8990 WindowState w = (WindowState)mWindows.get(i);
8991
8992 final WindowManager.LayoutParams attrs = w.mAttrs;
8993
8994 if (w.mSurface != null) {
8995 // Execute animation.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07008996 if (w.commitFinishDrawingLocked(currentTime)) {
8997 if ((w.mAttrs.flags
8998 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07008999 if (DEBUG_WALLPAPER) Log.v(TAG,
9000 "First draw done in potential wallpaper target " + w);
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009001 wallpaperMayChange = true;
9002 }
9003 }
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009004 boolean wasAnimating = w.mAnimating;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009005 if (w.stepAnimationLocked(currentTime, dw, dh)) {
9006 animating = true;
9007 //w.dump(" ");
9008 }
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009009 if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
9010 wallpaperMayChange = true;
9011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009012 mPolicy.animatingWindowLw(w, attrs);
9013 }
9014
9015 final AppWindowToken atoken = w.mAppToken;
9016 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
9017 if (atoken.lastTransactionSequence != transactionSequence) {
9018 atoken.lastTransactionSequence = transactionSequence;
9019 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9020 atoken.startingDisplayed = false;
9021 }
9022 if ((w.isOnScreen() || w.mAttrs.type
9023 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
9024 && !w.mExiting && !w.mDestroying) {
9025 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
9026 Log.v(TAG, "Eval win " + w + ": isDisplayed="
9027 + w.isDisplayedLw()
9028 + ", isAnimating=" + w.isAnimating());
9029 if (!w.isDisplayedLw()) {
9030 Log.v(TAG, "Not displayed: s=" + w.mSurface
9031 + " pv=" + w.mPolicyVisibility
9032 + " dp=" + w.mDrawPending
9033 + " cdp=" + w.mCommitDrawPending
9034 + " ah=" + w.mAttachedHidden
9035 + " th=" + atoken.hiddenRequested
9036 + " a=" + w.mAnimating);
9037 }
9038 }
9039 if (w != atoken.startingWindow) {
9040 if (!atoken.freezingScreen || !w.mAppFreezing) {
9041 atoken.numInterestingWindows++;
9042 if (w.isDisplayedLw()) {
9043 atoken.numDrawnWindows++;
9044 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Log.v(TAG,
9045 "tokenMayBeDrawn: " + atoken
9046 + " freezingScreen=" + atoken.freezingScreen
9047 + " mAppFreezing=" + w.mAppFreezing);
9048 tokenMayBeDrawn = true;
9049 }
9050 }
9051 } else if (w.isDisplayedLw()) {
9052 atoken.startingDisplayed = true;
9053 }
9054 }
9055 } else if (w.mReadyToShow) {
9056 w.performShowLocked();
9057 }
9058 }
9059
9060 if (mPolicy.finishAnimationLw()) {
9061 restart = true;
9062 }
9063
9064 if (tokenMayBeDrawn) {
9065 // See if any windows have been drawn, so they (and others
9066 // associated with them) can now be shown.
9067 final int NT = mTokenList.size();
9068 for (i=0; i<NT; i++) {
9069 AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
9070 if (wtoken == null) {
9071 continue;
9072 }
9073 if (wtoken.freezingScreen) {
9074 int numInteresting = wtoken.numInterestingWindows;
9075 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9076 if (DEBUG_VISIBILITY) Log.v(TAG,
9077 "allDrawn: " + wtoken
9078 + " interesting=" + numInteresting
9079 + " drawn=" + wtoken.numDrawnWindows);
9080 wtoken.showAllWindowsLocked();
9081 unsetAppFreezingScreenLocked(wtoken, false, true);
9082 orientationChangeComplete = true;
9083 }
9084 } else if (!wtoken.allDrawn) {
9085 int numInteresting = wtoken.numInterestingWindows;
9086 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9087 if (DEBUG_VISIBILITY) Log.v(TAG,
9088 "allDrawn: " + wtoken
9089 + " interesting=" + numInteresting
9090 + " drawn=" + wtoken.numDrawnWindows);
9091 wtoken.allDrawn = true;
9092 restart = true;
9093
9094 // We can now show all of the drawn windows!
9095 if (!mOpeningApps.contains(wtoken)) {
9096 wtoken.showAllWindowsLocked();
9097 }
9098 }
9099 }
9100 }
9101 }
9102
9103 // If we are ready to perform an app transition, check through
9104 // all of the app tokens to be shown and see if they are ready
9105 // to go.
9106 if (mAppTransitionReady) {
9107 int NN = mOpeningApps.size();
9108 boolean goodToGo = true;
9109 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9110 "Checking " + NN + " opening apps (frozen="
9111 + mDisplayFrozen + " timeout="
9112 + mAppTransitionTimeout + ")...");
9113 if (!mDisplayFrozen && !mAppTransitionTimeout) {
9114 // If the display isn't frozen, wait to do anything until
9115 // all of the apps are ready. Otherwise just go because
9116 // we'll unfreeze the display when everyone is ready.
9117 for (i=0; i<NN && goodToGo; i++) {
9118 AppWindowToken wtoken = mOpeningApps.get(i);
9119 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9120 "Check opening app" + wtoken + ": allDrawn="
9121 + wtoken.allDrawn + " startingDisplayed="
9122 + wtoken.startingDisplayed);
9123 if (!wtoken.allDrawn && !wtoken.startingDisplayed
9124 && !wtoken.startingMoved) {
9125 goodToGo = false;
9126 }
9127 }
9128 }
9129 if (goodToGo) {
9130 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "**** GOOD TO GO");
9131 int transit = mNextAppTransition;
9132 if (mSkipAppTransitionAnimation) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009133 transit = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009134 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009135 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009136 mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009137 mAppTransitionRunning = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009138 mAppTransitionTimeout = false;
9139 mStartingIconInTransition = false;
9140 mSkipAppTransitionAnimation = false;
9141
9142 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
9143
Dianne Hackborna8f60182009-09-01 19:01:50 -07009144 // If there are applications waiting to come to the
9145 // top of the stack, now is the time to move their windows.
9146 // (Note that we don't do apps going to the bottom
9147 // here -- we want to keep their windows in the old
9148 // Z-order until the animation completes.)
9149 if (mToTopApps.size() > 0) {
9150 NN = mAppTokens.size();
9151 for (i=0; i<NN; i++) {
9152 AppWindowToken wtoken = mAppTokens.get(i);
9153 if (wtoken.sendingToTop) {
9154 wtoken.sendingToTop = false;
9155 moveAppWindowsLocked(wtoken, NN, false);
9156 }
9157 }
9158 mToTopApps.clear();
9159 }
9160
Dianne Hackborn25994b42009-09-04 14:21:19 -07009161 WindowState oldWallpaper = mWallpaperTarget;
9162
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009163 adjustWallpaperWindowsLocked();
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009164 wallpaperMayChange = false;
9165
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009166 // The top-most window will supply the layout params,
9167 // and we will determine it below.
9168 LayoutParams animLp = null;
9169 int bestAnimLayer = -1;
9170
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07009171 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009172 "New wallpaper target=" + mWallpaperTarget
9173 + ", lower target=" + mLowerWallpaperTarget
9174 + ", upper target=" + mUpperWallpaperTarget);
Dianne Hackborn25994b42009-09-04 14:21:19 -07009175 int foundWallpapers = 0;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009176 // Do a first pass through the tokens for two
9177 // things:
9178 // (1) Determine if both the closing and opening
9179 // app token sets are wallpaper targets, in which
9180 // case special animations are needed
9181 // (since the wallpaper needs to stay static
9182 // behind them).
9183 // (2) Find the layout params of the top-most
9184 // application window in the tokens, which is
9185 // what will control the animation theme.
9186 final int NC = mClosingApps.size();
9187 NN = NC + mOpeningApps.size();
9188 for (i=0; i<NN; i++) {
9189 AppWindowToken wtoken;
9190 int mode;
9191 if (i < NC) {
9192 wtoken = mClosingApps.get(i);
9193 mode = 1;
9194 } else {
9195 wtoken = mOpeningApps.get(i-NC);
9196 mode = 2;
9197 }
9198 if (mLowerWallpaperTarget != null) {
9199 if (mLowerWallpaperTarget.mAppToken == wtoken
9200 || mUpperWallpaperTarget.mAppToken == wtoken) {
9201 foundWallpapers |= mode;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07009202 }
9203 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009204 if (wtoken.appFullscreen) {
9205 WindowState ws = wtoken.findMainWindow();
9206 if (ws != null) {
9207 // If this is a compatibility mode
9208 // window, we will always use its anim.
9209 if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
9210 animLp = ws.mAttrs;
9211 bestAnimLayer = Integer.MAX_VALUE;
9212 } else if (ws.mLayer > bestAnimLayer) {
9213 animLp = ws.mAttrs;
9214 bestAnimLayer = ws.mLayer;
9215 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07009216 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07009217 }
9218 }
9219
Dianne Hackborn25994b42009-09-04 14:21:19 -07009220 if (foundWallpapers == 3) {
9221 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9222 "Wallpaper animation!");
9223 switch (transit) {
9224 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
9225 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
9226 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
9227 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN;
9228 break;
9229 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
9230 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
9231 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
9232 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE;
9233 break;
9234 }
9235 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9236 "New transit: " + transit);
9237 } else if (oldWallpaper != null) {
9238 // We are transitioning from an activity with
9239 // a wallpaper to one without.
9240 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
9241 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9242 "New transit away from wallpaper: " + transit);
9243 } else if (mWallpaperTarget != null) {
9244 // We are transitioning from an activity without
9245 // a wallpaper to now showing the wallpaper
9246 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN;
9247 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9248 "New transit into wallpaper: " + transit);
9249 }
9250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009251 NN = mOpeningApps.size();
9252 for (i=0; i<NN; i++) {
9253 AppWindowToken wtoken = mOpeningApps.get(i);
9254 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9255 "Now opening app" + wtoken);
9256 wtoken.reportedVisible = false;
9257 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -07009258 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009259 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009260 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -07009261 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009262 wtoken.showAllWindowsLocked();
9263 }
9264 NN = mClosingApps.size();
9265 for (i=0; i<NN; i++) {
9266 AppWindowToken wtoken = mClosingApps.get(i);
9267 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9268 "Now closing app" + wtoken);
9269 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -07009270 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009271 setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009272 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -07009273 wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009274 // Force the allDrawn flag, because we want to start
9275 // this guy's animations regardless of whether it's
9276 // gotten drawn.
9277 wtoken.allDrawn = true;
9278 }
9279
9280 mOpeningApps.clear();
9281 mClosingApps.clear();
9282
9283 // This has changed the visibility of windows, so perform
9284 // a new layout to get them all up-to-date.
9285 mLayoutNeeded = true;
Dianne Hackborn20583ff2009-07-27 21:51:05 -07009286 if (!moveInputMethodWindowsIfNeededLocked(true)) {
9287 assignLayersLocked();
9288 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009289 performLayoutLockedInner();
9290 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
9291
9292 restart = true;
9293 }
9294 }
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009295
Dianne Hackborna8f60182009-09-01 19:01:50 -07009296 if (!animating && mAppTransitionRunning) {
9297 // We have finished the animation of an app transition. To do
9298 // this, we have delayed a lot of operations like showing and
9299 // hiding apps, moving apps in Z-order, etc. The app token list
9300 // reflects the correct Z-order, but the window list may now
9301 // be out of sync with it. So here we will just rebuild the
9302 // entire app window list. Fun!
9303 mAppTransitionRunning = false;
9304 // Clear information about apps that were moving.
9305 mToBottomApps.clear();
9306
9307 rebuildAppWindowListLocked();
9308 restart = true;
9309 moveInputMethodWindowsIfNeededLocked(false);
9310 wallpaperMayChange = true;
9311 mLayoutNeeded = true;
9312 }
9313
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009314 if (wallpaperMayChange) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009315 if (DEBUG_WALLPAPER) Log.v(TAG,
9316 "Wallpaper may change! Adjusting");
9317 int adjResult = adjustWallpaperWindowsLocked();
9318 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9319 if (DEBUG_WALLPAPER) Log.v(TAG,
9320 "Wallpaper layer changed: assigning layers + relayout");
9321 restart = true;
9322 mLayoutNeeded = true;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009323 assignLayersLocked();
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009324 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
9325 if (DEBUG_WALLPAPER) Log.v(TAG,
9326 "Wallpaper visibility changed: relayout");
9327 restart = true;
9328 mLayoutNeeded = true;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009329 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07009330 if (mLayoutNeeded) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009331 restart = true;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009332 performLayoutLockedInner();
9333 }
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009334 }
9335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009336 } while (restart);
9337
9338 // THIRD LOOP: Update the surfaces of all windows.
9339
9340 final boolean someoneLosingFocus = mLosingFocus.size() != 0;
9341
9342 boolean obscured = false;
9343 boolean blurring = false;
9344 boolean dimming = false;
9345 boolean covered = false;
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07009346 boolean syswin = false;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07009347 boolean backgroundFillerShown = false;
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009348 boolean forceHiding = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009349
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009350 final int N = mWindows.size();
9351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009352 for (i=N-1; i>=0; i--) {
9353 WindowState w = (WindowState)mWindows.get(i);
9354
9355 boolean displayed = false;
9356 final WindowManager.LayoutParams attrs = w.mAttrs;
9357 final int attrFlags = attrs.flags;
9358
9359 if (w.mSurface != null) {
9360 w.computeShownFrameLocked();
9361 if (localLOGV) Log.v(
9362 TAG, "Placing surface #" + i + " " + w.mSurface
9363 + ": new=" + w.mShownFrame + ", old="
9364 + w.mLastShownFrame);
9365
9366 boolean resize;
9367 int width, height;
9368 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
9369 resize = w.mLastRequestedWidth != w.mRequestedWidth ||
9370 w.mLastRequestedHeight != w.mRequestedHeight;
9371 // for a scaled surface, we just want to use
9372 // the requested size.
9373 width = w.mRequestedWidth;
9374 height = w.mRequestedHeight;
9375 w.mLastRequestedWidth = width;
9376 w.mLastRequestedHeight = height;
9377 w.mLastShownFrame.set(w.mShownFrame);
9378 try {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009379 if (SHOW_TRANSACTIONS) Log.i(
9380 TAG, " SURFACE " + w.mSurface
9381 + ": POS " + w.mShownFrame.left
9382 + ", " + w.mShownFrame.top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009383 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
9384 } catch (RuntimeException e) {
9385 Log.w(TAG, "Error positioning surface in " + w, e);
9386 if (!recoveringMemory) {
9387 reclaimSomeSurfaceMemoryLocked(w, "position");
9388 }
9389 }
9390 } else {
9391 resize = !w.mLastShownFrame.equals(w.mShownFrame);
9392 width = w.mShownFrame.width();
9393 height = w.mShownFrame.height();
9394 w.mLastShownFrame.set(w.mShownFrame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009395 }
9396
9397 if (resize) {
9398 if (width < 1) width = 1;
9399 if (height < 1) height = 1;
9400 if (w.mSurface != null) {
9401 try {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009402 if (SHOW_TRANSACTIONS) Log.i(
9403 TAG, " SURFACE " + w.mSurface + ": POS "
9404 + w.mShownFrame.left + ","
9405 + w.mShownFrame.top + " SIZE "
9406 + w.mShownFrame.width() + "x"
9407 + w.mShownFrame.height());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009408 w.mSurface.setSize(width, height);
9409 w.mSurface.setPosition(w.mShownFrame.left,
9410 w.mShownFrame.top);
9411 } catch (RuntimeException e) {
9412 // If something goes wrong with the surface (such
9413 // as running out of memory), don't take down the
9414 // entire system.
9415 Log.e(TAG, "Failure updating surface of " + w
9416 + "size=(" + width + "x" + height
9417 + "), pos=(" + w.mShownFrame.left
9418 + "," + w.mShownFrame.top + ")", e);
9419 if (!recoveringMemory) {
9420 reclaimSomeSurfaceMemoryLocked(w, "size");
9421 }
9422 }
9423 }
9424 }
9425 if (!w.mAppFreezing) {
9426 w.mContentInsetsChanged =
9427 !w.mLastContentInsets.equals(w.mContentInsets);
9428 w.mVisibleInsetsChanged =
9429 !w.mLastVisibleInsets.equals(w.mVisibleInsets);
Romain Guy06882f82009-06-10 13:36:04 -07009430 if (!w.mLastFrame.equals(w.mFrame)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009431 || w.mContentInsetsChanged
9432 || w.mVisibleInsetsChanged) {
9433 w.mLastFrame.set(w.mFrame);
9434 w.mLastContentInsets.set(w.mContentInsets);
9435 w.mLastVisibleInsets.set(w.mVisibleInsets);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009436 // If the screen is currently frozen, then keep
9437 // it frozen until this window draws at its new
9438 // orientation.
9439 if (mDisplayFrozen) {
9440 if (DEBUG_ORIENTATION) Log.v(TAG,
9441 "Resizing while display frozen: " + w);
9442 w.mOrientationChanging = true;
9443 if (mWindowsFreezingScreen) {
9444 mWindowsFreezingScreen = true;
9445 // XXX should probably keep timeout from
9446 // when we first froze the display.
9447 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9448 mH.sendMessageDelayed(mH.obtainMessage(
9449 H.WINDOW_FREEZE_TIMEOUT), 2000);
9450 }
9451 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 // If the orientation is changing, then we need to
9453 // hold off on unfreezing the display until this
9454 // window has been redrawn; to do that, we need
9455 // to go through the process of getting informed
9456 // by the application when it has finished drawing.
9457 if (w.mOrientationChanging) {
9458 if (DEBUG_ORIENTATION) Log.v(TAG,
9459 "Orientation start waiting for draw in "
9460 + w + ", surface " + w.mSurface);
9461 w.mDrawPending = true;
9462 w.mCommitDrawPending = false;
9463 w.mReadyToShow = false;
9464 if (w.mAppToken != null) {
9465 w.mAppToken.allDrawn = false;
9466 }
9467 }
Romain Guy06882f82009-06-10 13:36:04 -07009468 if (DEBUG_ORIENTATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009469 "Resizing window " + w + " to " + w.mFrame);
9470 mResizingWindows.add(w);
9471 } else if (w.mOrientationChanging) {
9472 if (!w.mDrawPending && !w.mCommitDrawPending) {
9473 if (DEBUG_ORIENTATION) Log.v(TAG,
9474 "Orientation not waiting for draw in "
9475 + w + ", surface " + w.mSurface);
9476 w.mOrientationChanging = false;
9477 }
9478 }
9479 }
9480
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009481 if ((forceHiding
9482 && attrs.type != WindowManager.LayoutParams.TYPE_STATUS_BAR
9483 && attrs.type != WindowManager.LayoutParams.TYPE_WALLPAPER)
9484 || w.mAttachedHidden) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009485 if (!w.mLastHidden) {
9486 //dump();
9487 w.mLastHidden = true;
9488 if (SHOW_TRANSACTIONS) Log.i(
9489 TAG, " SURFACE " + w.mSurface + ": HIDE (performLayout-attached)");
9490 if (w.mSurface != null) {
9491 try {
9492 w.mSurface.hide();
9493 } catch (RuntimeException e) {
9494 Log.w(TAG, "Exception hiding surface in " + w);
9495 }
9496 }
9497 mKeyWaiter.releasePendingPointerLocked(w.mSession);
9498 }
9499 // If we are waiting for this window to handle an
9500 // orientation change, well, it is hidden, so
9501 // doesn't really matter. Note that this does
9502 // introduce a potential glitch if the window
9503 // becomes unhidden before it has drawn for the
9504 // new orientation.
9505 if (w.mOrientationChanging) {
9506 w.mOrientationChanging = false;
9507 if (DEBUG_ORIENTATION) Log.v(TAG,
9508 "Orientation change skips hidden " + w);
9509 }
9510 } else if (!w.isReadyForDisplay()) {
9511 if (!w.mLastHidden) {
9512 //dump();
9513 w.mLastHidden = true;
9514 if (SHOW_TRANSACTIONS) Log.i(
9515 TAG, " SURFACE " + w.mSurface + ": HIDE (performLayout-ready)");
9516 if (w.mSurface != null) {
9517 try {
9518 w.mSurface.hide();
9519 } catch (RuntimeException e) {
9520 Log.w(TAG, "Exception exception hiding surface in " + w);
9521 }
9522 }
9523 mKeyWaiter.releasePendingPointerLocked(w.mSession);
9524 }
9525 // If we are waiting for this window to handle an
9526 // orientation change, well, it is hidden, so
9527 // doesn't really matter. Note that this does
9528 // introduce a potential glitch if the window
9529 // becomes unhidden before it has drawn for the
9530 // new orientation.
9531 if (w.mOrientationChanging) {
9532 w.mOrientationChanging = false;
9533 if (DEBUG_ORIENTATION) Log.v(TAG,
9534 "Orientation change skips hidden " + w);
9535 }
9536 } else if (w.mLastLayer != w.mAnimLayer
9537 || w.mLastAlpha != w.mShownAlpha
9538 || w.mLastDsDx != w.mDsDx
9539 || w.mLastDtDx != w.mDtDx
9540 || w.mLastDsDy != w.mDsDy
9541 || w.mLastDtDy != w.mDtDy
9542 || w.mLastHScale != w.mHScale
9543 || w.mLastVScale != w.mVScale
9544 || w.mLastHidden) {
9545 displayed = true;
9546 w.mLastAlpha = w.mShownAlpha;
9547 w.mLastLayer = w.mAnimLayer;
9548 w.mLastDsDx = w.mDsDx;
9549 w.mLastDtDx = w.mDtDx;
9550 w.mLastDsDy = w.mDsDy;
9551 w.mLastDtDy = w.mDtDy;
9552 w.mLastHScale = w.mHScale;
9553 w.mLastVScale = w.mVScale;
9554 if (SHOW_TRANSACTIONS) Log.i(
9555 TAG, " SURFACE " + w.mSurface + ": alpha="
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009556 + w.mShownAlpha + " layer=" + w.mAnimLayer
9557 + " matrix=[" + (w.mDsDx*w.mHScale)
9558 + "," + (w.mDtDx*w.mVScale)
9559 + "][" + (w.mDsDy*w.mHScale)
9560 + "," + (w.mDtDy*w.mVScale) + "]");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009561 if (w.mSurface != null) {
9562 try {
9563 w.mSurface.setAlpha(w.mShownAlpha);
9564 w.mSurface.setLayer(w.mAnimLayer);
9565 w.mSurface.setMatrix(
9566 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
9567 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
9568 } catch (RuntimeException e) {
9569 Log.w(TAG, "Error updating surface in " + w, e);
9570 if (!recoveringMemory) {
9571 reclaimSomeSurfaceMemoryLocked(w, "update");
9572 }
9573 }
9574 }
9575
9576 if (w.mLastHidden && !w.mDrawPending
9577 && !w.mCommitDrawPending
9578 && !w.mReadyToShow) {
9579 if (SHOW_TRANSACTIONS) Log.i(
9580 TAG, " SURFACE " + w.mSurface + ": SHOW (performLayout)");
9581 if (DEBUG_VISIBILITY) Log.v(TAG, "Showing " + w
9582 + " during relayout");
9583 if (showSurfaceRobustlyLocked(w)) {
9584 w.mHasDrawn = true;
9585 w.mLastHidden = false;
9586 } else {
9587 w.mOrientationChanging = false;
9588 }
9589 }
9590 if (w.mSurface != null) {
9591 w.mToken.hasVisible = true;
9592 }
9593 } else {
9594 displayed = true;
9595 }
9596
9597 if (displayed) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009598 if (attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) {
9599 forceHiding = true;
9600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009601 if (!covered) {
9602 if (attrs.width == LayoutParams.FILL_PARENT
9603 && attrs.height == LayoutParams.FILL_PARENT) {
9604 covered = true;
9605 }
9606 }
9607 if (w.mOrientationChanging) {
9608 if (w.mDrawPending || w.mCommitDrawPending) {
9609 orientationChangeComplete = false;
9610 if (DEBUG_ORIENTATION) Log.v(TAG,
9611 "Orientation continue waiting for draw in " + w);
9612 } else {
9613 w.mOrientationChanging = false;
9614 if (DEBUG_ORIENTATION) Log.v(TAG,
9615 "Orientation change complete in " + w);
9616 }
9617 }
9618 w.mToken.hasVisible = true;
9619 }
9620 } else if (w.mOrientationChanging) {
9621 if (DEBUG_ORIENTATION) Log.v(TAG,
9622 "Orientation change skips hidden " + w);
9623 w.mOrientationChanging = false;
9624 }
9625
9626 final boolean canBeSeen = w.isDisplayedLw();
9627
9628 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
9629 focusDisplayed = true;
9630 }
9631
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07009632 final boolean obscuredChanged = w.mObscured != obscured;
9633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009634 // Update effect.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009635 if (!(w.mObscured=obscured)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009636 if (w.mSurface != null) {
9637 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
9638 holdScreen = w.mSession;
9639 }
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07009640 if (!syswin && w.mAttrs.screenBrightness >= 0
9641 && screenBrightness < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009642 screenBrightness = w.mAttrs.screenBrightness;
9643 }
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07009644 if (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
9645 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
9646 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR) {
9647 syswin = true;
9648 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009649 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07009650
Dianne Hackborn25994b42009-09-04 14:21:19 -07009651 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
9652 if (opaqueDrawn && w.isFullscreen(dw, dh)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009653 // This window completely covers everything behind it,
9654 // so we want to leave all of them as unblurred (for
9655 // performance reasons).
9656 obscured = true;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07009657 } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
9658 if (SHOW_TRANSACTIONS) Log.d(TAG, "showing background filler");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07009659 // This window is in compatibility mode, and needs background filler.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07009660 obscured = true;
9661 if (mBackgroundFillerSurface == null) {
9662 try {
9663 mBackgroundFillerSurface = new Surface(mFxSession, 0,
9664 0, dw, dh,
9665 PixelFormat.OPAQUE,
9666 Surface.FX_SURFACE_NORMAL);
9667 } catch (Exception e) {
9668 Log.e(TAG, "Exception creating filler surface", e);
9669 }
9670 }
9671 try {
9672 mBackgroundFillerSurface.setPosition(0, 0);
9673 mBackgroundFillerSurface.setSize(dw, dh);
9674 // Using the same layer as Dim because they will never be shown at the
9675 // same time.
9676 mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
9677 mBackgroundFillerSurface.show();
9678 } catch (RuntimeException e) {
9679 Log.e(TAG, "Exception showing filler surface");
9680 }
9681 backgroundFillerShown = true;
9682 mBackgroundFillerShown = true;
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009683 } else if (canBeSeen && !obscured && !forceHiding &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009684 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
9685 if (localLOGV) Log.v(TAG, "Win " + w
9686 + ": blurring=" + blurring
9687 + " obscured=" + obscured
9688 + " displayed=" + displayed);
9689 if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
9690 if (!dimming) {
9691 //Log.i(TAG, "DIM BEHIND: " + w);
9692 dimming = true;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07009693 if (mDimAnimator == null) {
9694 mDimAnimator = new DimAnimator(mFxSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009695 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07009696 mDimAnimator.show(dw, dh);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009697 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07009698 mDimAnimator.updateParameters(w, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009699 }
9700 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
9701 if (!blurring) {
9702 //Log.i(TAG, "BLUR BEHIND: " + w);
9703 blurring = true;
9704 mBlurShown = true;
9705 if (mBlurSurface == null) {
9706 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR "
9707 + mBlurSurface + ": CREATE");
9708 try {
Romain Guy06882f82009-06-10 13:36:04 -07009709 mBlurSurface = new Surface(mFxSession, 0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009710 -1, 16, 16,
9711 PixelFormat.OPAQUE,
9712 Surface.FX_SURFACE_BLUR);
9713 } catch (Exception e) {
9714 Log.e(TAG, "Exception creating Blur surface", e);
9715 }
9716 }
9717 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR "
9718 + mBlurSurface + ": SHOW pos=(0,0) (" +
9719 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
9720 if (mBlurSurface != null) {
9721 mBlurSurface.setPosition(0, 0);
9722 mBlurSurface.setSize(dw, dh);
9723 try {
9724 mBlurSurface.show();
9725 } catch (RuntimeException e) {
9726 Log.w(TAG, "Failure showing blur surface", e);
9727 }
9728 }
9729 }
9730 mBlurSurface.setLayer(w.mAnimLayer-2);
9731 }
9732 }
9733 }
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07009734
9735 if (obscuredChanged && mWallpaperTarget == w) {
9736 // This is the wallpaper target and its obscured state
9737 // changed... make sure the current wallaper's visibility
9738 // has been updated accordingly.
9739 updateWallpaperVisibilityLocked();
9740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009741 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07009742
9743 if (backgroundFillerShown == false && mBackgroundFillerShown) {
9744 mBackgroundFillerShown = false;
9745 if (SHOW_TRANSACTIONS) Log.d(TAG, "hiding background filler");
9746 try {
9747 mBackgroundFillerSurface.hide();
9748 } catch (RuntimeException e) {
9749 Log.e(TAG, "Exception hiding filler surface", e);
9750 }
9751 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009752
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07009753 if (mDimAnimator != null && mDimAnimator.mDimShown) {
9754 animating |= mDimAnimator.updateSurface(dimming, currentTime, mDisplayFrozen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009755 }
Romain Guy06882f82009-06-10 13:36:04 -07009756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009757 if (!blurring && mBlurShown) {
9758 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR " + mBlurSurface
9759 + ": HIDE");
9760 try {
9761 mBlurSurface.hide();
9762 } catch (IllegalArgumentException e) {
9763 Log.w(TAG, "Illegal argument exception hiding blur surface");
9764 }
9765 mBlurShown = false;
9766 }
9767
9768 if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION");
9769 } catch (RuntimeException e) {
9770 Log.e(TAG, "Unhandled exception in Window Manager", e);
9771 }
9772
9773 Surface.closeTransaction();
Romain Guy06882f82009-06-10 13:36:04 -07009774
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775 if (DEBUG_ORIENTATION && mDisplayFrozen) Log.v(TAG,
9776 "With display frozen, orientationChangeComplete="
9777 + orientationChangeComplete);
9778 if (orientationChangeComplete) {
9779 if (mWindowsFreezingScreen) {
9780 mWindowsFreezingScreen = false;
9781 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9782 }
9783 if (mAppsFreezingScreen == 0) {
9784 stopFreezingDisplayLocked();
9785 }
9786 }
Romain Guy06882f82009-06-10 13:36:04 -07009787
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009788 i = mResizingWindows.size();
9789 if (i > 0) {
9790 do {
9791 i--;
9792 WindowState win = mResizingWindows.get(i);
9793 try {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009794 if (DEBUG_ORIENTATION) Log.v(TAG, "Reporting new frame to "
9795 + win + ": " + win.mFrame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009796 win.mClient.resized(win.mFrame.width(),
9797 win.mFrame.height(), win.mLastContentInsets,
9798 win.mLastVisibleInsets, win.mDrawPending);
9799 win.mContentInsetsChanged = false;
9800 win.mVisibleInsetsChanged = false;
9801 } catch (RemoteException e) {
9802 win.mOrientationChanging = false;
9803 }
9804 } while (i > 0);
9805 mResizingWindows.clear();
9806 }
Romain Guy06882f82009-06-10 13:36:04 -07009807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009808 // Destroy the surface of any windows that are no longer visible.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009809 boolean wallpaperDestroyed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009810 i = mDestroySurface.size();
9811 if (i > 0) {
9812 do {
9813 i--;
9814 WindowState win = mDestroySurface.get(i);
9815 win.mDestroying = false;
9816 if (mInputMethodWindow == win) {
9817 mInputMethodWindow = null;
9818 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009819 if (win == mWallpaperTarget) {
9820 wallpaperDestroyed = true;
9821 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009822 win.destroySurfaceLocked();
9823 } while (i > 0);
9824 mDestroySurface.clear();
9825 }
9826
9827 // Time to remove any exiting tokens?
9828 for (i=mExitingTokens.size()-1; i>=0; i--) {
9829 WindowToken token = mExitingTokens.get(i);
9830 if (!token.hasVisible) {
9831 mExitingTokens.remove(i);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07009832 if (token.windowType == TYPE_WALLPAPER) {
9833 mWallpaperTokens.remove(token);
9834 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009835 }
9836 }
9837
9838 // Time to remove any exiting applications?
9839 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
9840 AppWindowToken token = mExitingAppTokens.get(i);
9841 if (!token.hasVisible && !mClosingApps.contains(token)) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009842 // Make sure there is no animation running on this token,
9843 // so any windows associated with it will be removed as
9844 // soon as their animations are complete
9845 token.animation = null;
9846 token.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009847 mAppTokens.remove(token);
9848 mExitingAppTokens.remove(i);
9849 }
9850 }
9851
Dianne Hackborna8f60182009-09-01 19:01:50 -07009852 boolean needRelayout = false;
9853
9854 if (!animating && mAppTransitionRunning) {
9855 // We have finished the animation of an app transition. To do
9856 // this, we have delayed a lot of operations like showing and
9857 // hiding apps, moving apps in Z-order, etc. The app token list
9858 // reflects the correct Z-order, but the window list may now
9859 // be out of sync with it. So here we will just rebuild the
9860 // entire app window list. Fun!
9861 mAppTransitionRunning = false;
9862 needRelayout = true;
9863 rebuildAppWindowListLocked();
9864 // Clear information about apps that were moving.
9865 mToBottomApps.clear();
9866 }
9867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009868 if (focusDisplayed) {
9869 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
9870 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009871 if (wallpaperDestroyed) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009872 needRelayout = adjustWallpaperWindowsLocked() != 0;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009873 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07009874 if (needRelayout) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009875 requestAnimationLocked(0);
9876 } else if (animating) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009877 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
9878 }
9879 mQueue.setHoldScreenLocked(holdScreen != null);
9880 if (screenBrightness < 0 || screenBrightness > 1.0f) {
9881 mPowerManager.setScreenBrightnessOverride(-1);
9882 } else {
9883 mPowerManager.setScreenBrightnessOverride((int)
9884 (screenBrightness * Power.BRIGHTNESS_ON));
9885 }
9886 if (holdScreen != mHoldingScreenOn) {
9887 mHoldingScreenOn = holdScreen;
9888 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
9889 mH.sendMessage(m);
9890 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07009891
9892 if (mTurnOnScreen) {
9893 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
9894 LocalPowerManager.BUTTON_EVENT, true);
9895 mTurnOnScreen = false;
9896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009897 }
9898
9899 void requestAnimationLocked(long delay) {
9900 if (!mAnimationPending) {
9901 mAnimationPending = true;
9902 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
9903 }
9904 }
Romain Guy06882f82009-06-10 13:36:04 -07009905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009906 /**
9907 * Have the surface flinger show a surface, robustly dealing with
9908 * error conditions. In particular, if there is not enough memory
9909 * to show the surface, then we will try to get rid of other surfaces
9910 * in order to succeed.
Romain Guy06882f82009-06-10 13:36:04 -07009911 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009912 * @return Returns true if the surface was successfully shown.
9913 */
9914 boolean showSurfaceRobustlyLocked(WindowState win) {
9915 try {
9916 if (win.mSurface != null) {
9917 win.mSurface.show();
Dianne Hackborn93e462b2009-09-15 22:50:40 -07009918 if (win.mTurnOnScreen) {
9919 win.mTurnOnScreen = false;
9920 mTurnOnScreen = true;
9921 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 }
9923 return true;
9924 } catch (RuntimeException e) {
9925 Log.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
9926 }
Romain Guy06882f82009-06-10 13:36:04 -07009927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009928 reclaimSomeSurfaceMemoryLocked(win, "show");
Romain Guy06882f82009-06-10 13:36:04 -07009929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009930 return false;
9931 }
Romain Guy06882f82009-06-10 13:36:04 -07009932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009933 void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
9934 final Surface surface = win.mSurface;
Romain Guy06882f82009-06-10 13:36:04 -07009935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009936 EventLog.writeEvent(LOG_WM_NO_SURFACE_MEMORY, win.toString(),
9937 win.mSession.mPid, operation);
Romain Guy06882f82009-06-10 13:36:04 -07009938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009939 if (mForceRemoves == null) {
9940 mForceRemoves = new ArrayList<WindowState>();
9941 }
Romain Guy06882f82009-06-10 13:36:04 -07009942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009943 long callingIdentity = Binder.clearCallingIdentity();
9944 try {
9945 // There was some problem... first, do a sanity check of the
9946 // window list to make sure we haven't left any dangling surfaces
9947 // around.
9948 int N = mWindows.size();
9949 boolean leakedSurface = false;
9950 Log.i(TAG, "Out of memory for surface! Looking for leaks...");
9951 for (int i=0; i<N; i++) {
9952 WindowState ws = (WindowState)mWindows.get(i);
9953 if (ws.mSurface != null) {
9954 if (!mSessions.contains(ws.mSession)) {
9955 Log.w(TAG, "LEAKED SURFACE (session doesn't exist): "
9956 + ws + " surface=" + ws.mSurface
9957 + " token=" + win.mToken
9958 + " pid=" + ws.mSession.mPid
9959 + " uid=" + ws.mSession.mUid);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009960 ws.mSurface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009961 ws.mSurface = null;
9962 mForceRemoves.add(ws);
9963 i--;
9964 N--;
9965 leakedSurface = true;
9966 } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
9967 Log.w(TAG, "LEAKED SURFACE (app token hidden): "
9968 + ws + " surface=" + ws.mSurface
9969 + " token=" + win.mAppToken);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009970 ws.mSurface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009971 ws.mSurface = null;
9972 leakedSurface = true;
9973 }
9974 }
9975 }
Romain Guy06882f82009-06-10 13:36:04 -07009976
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009977 boolean killedApps = false;
9978 if (!leakedSurface) {
9979 Log.w(TAG, "No leaked surfaces; killing applicatons!");
9980 SparseIntArray pidCandidates = new SparseIntArray();
9981 for (int i=0; i<N; i++) {
9982 WindowState ws = (WindowState)mWindows.get(i);
9983 if (ws.mSurface != null) {
9984 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
9985 }
9986 }
9987 if (pidCandidates.size() > 0) {
9988 int[] pids = new int[pidCandidates.size()];
9989 for (int i=0; i<pids.length; i++) {
9990 pids[i] = pidCandidates.keyAt(i);
9991 }
9992 try {
9993 if (mActivityManager.killPidsForMemory(pids)) {
9994 killedApps = true;
9995 }
9996 } catch (RemoteException e) {
9997 }
9998 }
9999 }
Romain Guy06882f82009-06-10 13:36:04 -070010000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 if (leakedSurface || killedApps) {
10002 // We managed to reclaim some memory, so get rid of the trouble
10003 // surface and ask the app to request another one.
10004 Log.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
10005 if (surface != null) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010006 surface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010007 win.mSurface = null;
10008 }
Romain Guy06882f82009-06-10 13:36:04 -070010009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010010 try {
10011 win.mClient.dispatchGetNewSurface();
10012 } catch (RemoteException e) {
10013 }
10014 }
10015 } finally {
10016 Binder.restoreCallingIdentity(callingIdentity);
10017 }
10018 }
Romain Guy06882f82009-06-10 13:36:04 -070010019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010020 private boolean updateFocusedWindowLocked(int mode) {
10021 WindowState newFocus = computeFocusedWindowLocked();
10022 if (mCurrentFocus != newFocus) {
10023 // This check makes sure that we don't already have the focus
10024 // change message pending.
10025 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
10026 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
10027 if (localLOGV) Log.v(
10028 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
10029 final WindowState oldFocus = mCurrentFocus;
10030 mCurrentFocus = newFocus;
10031 mLosingFocus.remove(newFocus);
Romain Guy06882f82009-06-10 13:36:04 -070010032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010033 final WindowState imWindow = mInputMethodWindow;
10034 if (newFocus != imWindow && oldFocus != imWindow) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010035 if (moveInputMethodWindowsIfNeededLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010036 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010037 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
10038 mLayoutNeeded = true;
10039 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010040 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10041 performLayoutLockedInner();
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010042 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
10043 // Client will do the layout, but we need to assign layers
10044 // for handleNewWindowLocked() below.
10045 assignLayersLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010046 }
10047 }
Romain Guy06882f82009-06-10 13:36:04 -070010048
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010049 if (newFocus != null && mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
10050 mKeyWaiter.handleNewWindowLocked(newFocus);
10051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010052 return true;
10053 }
10054 return false;
10055 }
10056
10057 private WindowState computeFocusedWindowLocked() {
10058 WindowState result = null;
10059 WindowState win;
10060
10061 int i = mWindows.size() - 1;
10062 int nextAppIndex = mAppTokens.size()-1;
10063 WindowToken nextApp = nextAppIndex >= 0
10064 ? mAppTokens.get(nextAppIndex) : null;
10065
10066 while (i >= 0) {
10067 win = (WindowState)mWindows.get(i);
10068
10069 if (localLOGV || DEBUG_FOCUS) Log.v(
10070 TAG, "Looking for focus: " + i
10071 + " = " + win
10072 + ", flags=" + win.mAttrs.flags
10073 + ", canReceive=" + win.canReceiveKeys());
10074
10075 AppWindowToken thisApp = win.mAppToken;
Romain Guy06882f82009-06-10 13:36:04 -070010076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010077 // If this window's application has been removed, just skip it.
10078 if (thisApp != null && thisApp.removed) {
10079 i--;
10080 continue;
10081 }
Romain Guy06882f82009-06-10 13:36:04 -070010082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010083 // If there is a focused app, don't allow focus to go to any
10084 // windows below it. If this is an application window, step
10085 // through the app tokens until we find its app.
10086 if (thisApp != null && nextApp != null && thisApp != nextApp
10087 && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
10088 int origAppIndex = nextAppIndex;
10089 while (nextAppIndex > 0) {
10090 if (nextApp == mFocusedApp) {
10091 // Whoops, we are below the focused app... no focus
10092 // for you!
10093 if (localLOGV || DEBUG_FOCUS) Log.v(
10094 TAG, "Reached focused app: " + mFocusedApp);
10095 return null;
10096 }
10097 nextAppIndex--;
10098 nextApp = mAppTokens.get(nextAppIndex);
10099 if (nextApp == thisApp) {
10100 break;
10101 }
10102 }
10103 if (thisApp != nextApp) {
10104 // Uh oh, the app token doesn't exist! This shouldn't
10105 // happen, but if it does we can get totally hosed...
10106 // so restart at the original app.
10107 nextAppIndex = origAppIndex;
10108 nextApp = mAppTokens.get(nextAppIndex);
10109 }
10110 }
10111
10112 // Dispatch to this window if it is wants key events.
10113 if (win.canReceiveKeys()) {
10114 if (DEBUG_FOCUS) Log.v(
10115 TAG, "Found focus @ " + i + " = " + win);
10116 result = win;
10117 break;
10118 }
10119
10120 i--;
10121 }
10122
10123 return result;
10124 }
10125
10126 private void startFreezingDisplayLocked() {
10127 if (mDisplayFrozen) {
Chris Tate2ad63a92009-03-25 17:36:48 -070010128 // Freezing the display also suspends key event delivery, to
10129 // keep events from going astray while the display is reconfigured.
10130 // If someone has changed orientation again while the screen is
10131 // still frozen, the events will continue to be blocked while the
10132 // successive orientation change is processed. To prevent spurious
10133 // ANRs, we reset the event dispatch timeout in this case.
10134 synchronized (mKeyWaiter) {
10135 mKeyWaiter.mWasFrozen = true;
10136 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010137 return;
10138 }
Romain Guy06882f82009-06-10 13:36:04 -070010139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010140 mScreenFrozenLock.acquire();
Romain Guy06882f82009-06-10 13:36:04 -070010141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010142 long now = SystemClock.uptimeMillis();
10143 //Log.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
10144 if (mFreezeGcPending != 0) {
10145 if (now > (mFreezeGcPending+1000)) {
10146 //Log.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
10147 mH.removeMessages(H.FORCE_GC);
10148 Runtime.getRuntime().gc();
10149 mFreezeGcPending = now;
10150 }
10151 } else {
10152 mFreezeGcPending = now;
10153 }
Romain Guy06882f82009-06-10 13:36:04 -070010154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010155 mDisplayFrozen = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -070010156 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
10157 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010158 mAppTransitionReady = true;
10159 }
Romain Guy06882f82009-06-10 13:36:04 -070010160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010161 if (PROFILE_ORIENTATION) {
10162 File file = new File("/data/system/frozen");
10163 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
10164 }
10165 Surface.freezeDisplay(0);
10166 }
Romain Guy06882f82009-06-10 13:36:04 -070010167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010168 private void stopFreezingDisplayLocked() {
10169 if (!mDisplayFrozen) {
10170 return;
10171 }
Romain Guy06882f82009-06-10 13:36:04 -070010172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010173 mDisplayFrozen = false;
10174 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
10175 if (PROFILE_ORIENTATION) {
10176 Debug.stopMethodTracing();
10177 }
10178 Surface.unfreezeDisplay(0);
Romain Guy06882f82009-06-10 13:36:04 -070010179
Chris Tate2ad63a92009-03-25 17:36:48 -070010180 // Reset the key delivery timeout on unfreeze, too. We force a wakeup here
10181 // too because regular key delivery processing should resume immediately.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182 synchronized (mKeyWaiter) {
10183 mKeyWaiter.mWasFrozen = true;
10184 mKeyWaiter.notifyAll();
10185 }
10186
10187 // A little kludge: a lot could have happened while the
10188 // display was frozen, so now that we are coming back we
10189 // do a gc so that any remote references the system
10190 // processes holds on others can be released if they are
10191 // no longer needed.
10192 mH.removeMessages(H.FORCE_GC);
10193 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
10194 2000);
Romain Guy06882f82009-06-10 13:36:04 -070010195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010196 mScreenFrozenLock.release();
10197 }
Romain Guy06882f82009-06-10 13:36:04 -070010198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010199 @Override
10200 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10201 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10202 != PackageManager.PERMISSION_GRANTED) {
10203 pw.println("Permission Denial: can't dump WindowManager from from pid="
10204 + Binder.getCallingPid()
10205 + ", uid=" + Binder.getCallingUid());
10206 return;
10207 }
Romain Guy06882f82009-06-10 13:36:04 -070010208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010209 synchronized(mWindowMap) {
10210 pw.println("Current Window Manager state:");
10211 for (int i=mWindows.size()-1; i>=0; i--) {
10212 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010213 pw.print(" Window #"); pw.print(i); pw.print(' ');
10214 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010215 w.dump(pw, " ");
10216 }
10217 if (mInputMethodDialogs.size() > 0) {
10218 pw.println(" ");
10219 pw.println(" Input method dialogs:");
10220 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10221 WindowState w = mInputMethodDialogs.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010222 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010223 }
10224 }
10225 if (mPendingRemove.size() > 0) {
10226 pw.println(" ");
10227 pw.println(" Remove pending for:");
10228 for (int i=mPendingRemove.size()-1; i>=0; i--) {
10229 WindowState w = mPendingRemove.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010230 pw.print(" Remove #"); pw.print(i); pw.print(' ');
10231 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010232 w.dump(pw, " ");
10233 }
10234 }
10235 if (mForceRemoves != null && mForceRemoves.size() > 0) {
10236 pw.println(" ");
10237 pw.println(" Windows force removing:");
10238 for (int i=mForceRemoves.size()-1; i>=0; i--) {
10239 WindowState w = mForceRemoves.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010240 pw.print(" Removing #"); pw.print(i); pw.print(' ');
10241 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010242 w.dump(pw, " ");
10243 }
10244 }
10245 if (mDestroySurface.size() > 0) {
10246 pw.println(" ");
10247 pw.println(" Windows waiting to destroy their surface:");
10248 for (int i=mDestroySurface.size()-1; i>=0; i--) {
10249 WindowState w = mDestroySurface.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010250 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
10251 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010252 w.dump(pw, " ");
10253 }
10254 }
10255 if (mLosingFocus.size() > 0) {
10256 pw.println(" ");
10257 pw.println(" Windows losing focus:");
10258 for (int i=mLosingFocus.size()-1; i>=0; i--) {
10259 WindowState w = mLosingFocus.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010260 pw.print(" Losing #"); pw.print(i); pw.print(' ');
10261 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010262 w.dump(pw, " ");
10263 }
10264 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010265 if (mResizingWindows.size() > 0) {
10266 pw.println(" ");
10267 pw.println(" Windows waiting to resize:");
10268 for (int i=mResizingWindows.size()-1; i>=0; i--) {
10269 WindowState w = mResizingWindows.get(i);
10270 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
10271 pw.print(w); pw.println(":");
10272 w.dump(pw, " ");
10273 }
10274 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010275 if (mSessions.size() > 0) {
10276 pw.println(" ");
10277 pw.println(" All active sessions:");
10278 Iterator<Session> it = mSessions.iterator();
10279 while (it.hasNext()) {
10280 Session s = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010281 pw.print(" Session "); pw.print(s); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010282 s.dump(pw, " ");
10283 }
10284 }
10285 if (mTokenMap.size() > 0) {
10286 pw.println(" ");
10287 pw.println(" All tokens:");
10288 Iterator<WindowToken> it = mTokenMap.values().iterator();
10289 while (it.hasNext()) {
10290 WindowToken token = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010291 pw.print(" Token "); pw.print(token.token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292 token.dump(pw, " ");
10293 }
10294 }
10295 if (mTokenList.size() > 0) {
10296 pw.println(" ");
10297 pw.println(" Window token list:");
10298 for (int i=0; i<mTokenList.size(); i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010299 pw.print(" #"); pw.print(i); pw.print(": ");
10300 pw.println(mTokenList.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 }
10302 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070010303 if (mWallpaperTokens.size() > 0) {
10304 pw.println(" ");
10305 pw.println(" Wallpaper tokens:");
10306 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10307 WindowToken token = mWallpaperTokens.get(i);
10308 pw.print(" Wallpaper #"); pw.print(i);
10309 pw.print(' '); pw.print(token); pw.println(':');
10310 token.dump(pw, " ");
10311 }
10312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010313 if (mAppTokens.size() > 0) {
10314 pw.println(" ");
10315 pw.println(" Application tokens in Z order:");
10316 for (int i=mAppTokens.size()-1; i>=0; i--) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010317 pw.print(" App #"); pw.print(i); pw.print(": ");
10318 pw.println(mAppTokens.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 }
10320 }
10321 if (mFinishedStarting.size() > 0) {
10322 pw.println(" ");
10323 pw.println(" Finishing start of application tokens:");
10324 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10325 WindowToken token = mFinishedStarting.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010326 pw.print(" Finished Starting #"); pw.print(i);
10327 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010328 token.dump(pw, " ");
10329 }
10330 }
10331 if (mExitingTokens.size() > 0) {
10332 pw.println(" ");
10333 pw.println(" Exiting tokens:");
10334 for (int i=mExitingTokens.size()-1; i>=0; i--) {
10335 WindowToken token = mExitingTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010336 pw.print(" Exiting #"); pw.print(i);
10337 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 token.dump(pw, " ");
10339 }
10340 }
10341 if (mExitingAppTokens.size() > 0) {
10342 pw.println(" ");
10343 pw.println(" Exiting application tokens:");
10344 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
10345 WindowToken token = mExitingAppTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010346 pw.print(" Exiting App #"); pw.print(i);
10347 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010348 token.dump(pw, " ");
10349 }
10350 }
10351 pw.println(" ");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010352 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
10353 pw.print(" mLastFocus="); pw.println(mLastFocus);
10354 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
10355 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
10356 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
Dianne Hackbornf21adf62009-08-13 10:20:21 -070010357 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
Dianne Hackborn284ac932009-08-28 10:34:25 -070010358 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
10359 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10360 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10361 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010362 pw.print(" mInTouchMode="); pw.println(mInTouchMode);
10363 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
10364 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10365 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
10366 pw.print(" mBlurShown="); pw.println(mBlurShown);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010367 if (mDimAnimator != null) {
10368 mDimAnimator.printTo(pw);
10369 } else {
10370 pw.print( " no DimAnimator ");
10371 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010372 pw.print(" mInputMethodAnimLayerAdjustment=");
Dianne Hackborn759a39e2009-08-09 17:20:27 -070010373 pw.print(mInputMethodAnimLayerAdjustment);
10374 pw.print(" mWallpaperAnimLayerAdjustment=");
10375 pw.println(mWallpaperAnimLayerAdjustment);
Dianne Hackborn284ac932009-08-28 10:34:25 -070010376 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
10377 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010378 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
10379 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
10380 pw.print(" mAppsFreezingScreen="); pw.println(mAppsFreezingScreen);
10381 pw.print(" mRotation="); pw.print(mRotation);
10382 pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
10383 pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
10384 pw.print(" mAnimationPending="); pw.print(mAnimationPending);
10385 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
10386 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
10387 pw.print(" mNextAppTransition=0x");
10388 pw.print(Integer.toHexString(mNextAppTransition));
10389 pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
Dianne Hackborna8f60182009-09-01 19:01:50 -070010390 pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010391 pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
10392 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10393 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
10394 if (mOpeningApps.size() > 0) {
10395 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
10396 }
10397 if (mClosingApps.size() > 0) {
10398 pw.print(" mClosingApps="); pw.println(mClosingApps);
10399 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070010400 if (mToTopApps.size() > 0) {
10401 pw.print(" mToTopApps="); pw.println(mToTopApps);
10402 }
10403 if (mToBottomApps.size() > 0) {
10404 pw.print(" mToBottomApps="); pw.println(mToBottomApps);
10405 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010406 pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth());
10407 pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010408 pw.println(" KeyWaiter state:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010409 pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin);
10410 pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
10411 pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished);
10412 pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
10413 pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
10414 pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010415 }
10416 }
10417
10418 public void monitor() {
10419 synchronized (mWindowMap) { }
10420 synchronized (mKeyguardDisabled) { }
10421 synchronized (mKeyWaiter) { }
10422 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010423
Dianne Hackbornddca3ee2009-07-23 19:01:31 -070010424 public void virtualKeyFeedback(KeyEvent event) {
10425 mPolicy.keyFeedbackFromInput(event);
10426 }
10427
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010428 /**
10429 * DimAnimator class that controls the dim animation. This holds the surface and
10430 * all state used for dim animation.
10431 */
10432 private static class DimAnimator {
10433 Surface mDimSurface;
10434 boolean mDimShown = false;
10435 float mDimCurrentAlpha;
10436 float mDimTargetAlpha;
10437 float mDimDeltaPerMs;
10438 long mLastDimAnimTime;
10439
10440 DimAnimator (SurfaceSession session) {
10441 if (mDimSurface == null) {
10442 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
10443 + mDimSurface + ": CREATE");
10444 try {
10445 mDimSurface = new Surface(session, 0, -1, 16, 16, PixelFormat.OPAQUE,
10446 Surface.FX_SURFACE_DIM);
10447 } catch (Exception e) {
10448 Log.e(TAG, "Exception creating Dim surface", e);
10449 }
10450 }
10451 }
10452
10453 /**
10454 * Show the dim surface.
10455 */
10456 void show(int dw, int dh) {
10457 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
10458 dw + "x" + dh + ")");
10459 mDimShown = true;
10460 try {
10461 mDimSurface.setPosition(0, 0);
10462 mDimSurface.setSize(dw, dh);
10463 mDimSurface.show();
10464 } catch (RuntimeException e) {
10465 Log.w(TAG, "Failure showing dim surface", e);
10466 }
10467 }
10468
10469 /**
10470 * Set's the dim surface's layer and update dim parameters that will be used in
10471 * {@link updateSurface} after all windows are examined.
10472 */
10473 void updateParameters(WindowState w, long currentTime) {
10474 mDimSurface.setLayer(w.mAnimLayer-1);
10475
10476 final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010477 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface
10478 + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010479 if (mDimTargetAlpha != target) {
10480 // If the desired dim level has changed, then
10481 // start an animation to it.
10482 mLastDimAnimTime = currentTime;
10483 long duration = (w.mAnimating && w.mAnimation != null)
10484 ? w.mAnimation.computeDurationHint()
10485 : DEFAULT_DIM_DURATION;
10486 if (target > mDimTargetAlpha) {
10487 // This is happening behind the activity UI,
10488 // so we can make it run a little longer to
10489 // give a stronger impression without disrupting
10490 // the user.
10491 duration *= DIM_DURATION_MULTIPLIER;
10492 }
10493 if (duration < 1) {
10494 // Don't divide by zero
10495 duration = 1;
10496 }
10497 mDimTargetAlpha = target;
10498 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
10499 }
10500 }
10501
10502 /**
10503 * Updating the surface's alpha. Returns true if the animation continues, or returns
10504 * false when the animation is finished and the dim surface is hidden.
10505 */
10506 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
10507 if (!dimming) {
10508 if (mDimTargetAlpha != 0) {
10509 mLastDimAnimTime = currentTime;
10510 mDimTargetAlpha = 0;
10511 mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
10512 }
10513 }
10514
10515 boolean animating = false;
10516 if (mLastDimAnimTime != 0) {
10517 mDimCurrentAlpha += mDimDeltaPerMs
10518 * (currentTime-mLastDimAnimTime);
10519 boolean more = true;
10520 if (displayFrozen) {
10521 // If the display is frozen, there is no reason to animate.
10522 more = false;
10523 } else if (mDimDeltaPerMs > 0) {
10524 if (mDimCurrentAlpha > mDimTargetAlpha) {
10525 more = false;
10526 }
10527 } else if (mDimDeltaPerMs < 0) {
10528 if (mDimCurrentAlpha < mDimTargetAlpha) {
10529 more = false;
10530 }
10531 } else {
10532 more = false;
10533 }
10534
10535 // Do we need to continue animating?
10536 if (more) {
10537 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
10538 + mDimSurface + ": alpha=" + mDimCurrentAlpha);
10539 mLastDimAnimTime = currentTime;
10540 mDimSurface.setAlpha(mDimCurrentAlpha);
10541 animating = true;
10542 } else {
10543 mDimCurrentAlpha = mDimTargetAlpha;
10544 mLastDimAnimTime = 0;
10545 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
10546 + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
10547 mDimSurface.setAlpha(mDimCurrentAlpha);
10548 if (!dimming) {
10549 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface
10550 + ": HIDE");
10551 try {
10552 mDimSurface.hide();
10553 } catch (RuntimeException e) {
10554 Log.w(TAG, "Illegal argument exception hiding dim surface");
10555 }
10556 mDimShown = false;
10557 }
10558 }
10559 }
10560 return animating;
10561 }
10562
10563 public void printTo(PrintWriter pw) {
10564 pw.print(" mDimShown="); pw.print(mDimShown);
10565 pw.print(" current="); pw.print(mDimCurrentAlpha);
10566 pw.print(" target="); pw.print(mDimTargetAlpha);
10567 pw.print(" delta="); pw.print(mDimDeltaPerMs);
10568 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
10569 }
10570 }
10571
10572 /**
10573 * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
10574 * This is used for opening/closing transition for apps in compatible mode.
10575 */
10576 private static class FadeInOutAnimation extends Animation {
10577 int mWidth;
10578 boolean mFadeIn;
10579
10580 public FadeInOutAnimation(boolean fadeIn) {
10581 setInterpolator(new AccelerateInterpolator());
10582 setDuration(DEFAULT_FADE_IN_OUT_DURATION);
10583 mFadeIn = fadeIn;
10584 }
10585
10586 @Override
10587 protected void applyTransformation(float interpolatedTime, Transformation t) {
10588 float x = interpolatedTime;
10589 if (!mFadeIn) {
10590 x = 1.0f - x; // reverse the interpolation for fade out
10591 }
10592 if (x < 0.5) {
10593 // move the window out of the screen.
10594 t.getMatrix().setTranslate(mWidth, 0);
10595 } else {
10596 t.getMatrix().setTranslate(0, 0);// show
10597 t.setAlpha((x - 0.5f) * 2);
10598 }
10599 }
10600
10601 @Override
10602 public void initialize(int width, int height, int parentWidth, int parentHeight) {
10603 // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
10604 mWidth = width;
10605 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010606
10607 @Override
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -070010608 public int getZAdjustment() {
10609 return Animation.ZORDER_TOP;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010610 }
10611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010612}