blob: 69f4b89eb6b1965377b6821bbcb2d0353172c9dd [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;
Dianne Hackborn75804932009-10-20 20:15:20 -070066import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080067import android.os.Debug;
68import android.os.Handler;
69import android.os.IBinder;
Michael Chan53071d62009-05-13 17:29:48 -070070import android.os.LatencyTimer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071import android.os.LocalPowerManager;
72import android.os.Looper;
73import android.os.Message;
74import android.os.Parcel;
75import android.os.ParcelFileDescriptor;
76import android.os.Power;
77import android.os.PowerManager;
78import android.os.Process;
79import android.os.RemoteException;
80import android.os.ServiceManager;
81import android.os.SystemClock;
82import android.os.SystemProperties;
83import android.os.TokenWatcher;
84import android.provider.Settings;
Dianne Hackborn723738c2009-06-25 19:48:04 -070085import android.util.DisplayMetrics;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086import android.util.EventLog;
87import android.util.Log;
88import android.util.SparseIntArray;
89import android.view.Display;
90import android.view.Gravity;
91import android.view.IApplicationToken;
92import android.view.IOnKeyguardExitResult;
93import android.view.IRotationWatcher;
94import android.view.IWindow;
95import android.view.IWindowManager;
96import android.view.IWindowSession;
97import android.view.KeyEvent;
98import android.view.MotionEvent;
99import android.view.RawInputEvent;
100import android.view.Surface;
101import android.view.SurfaceSession;
102import android.view.View;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700103import android.view.ViewConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104import android.view.ViewTreeObserver;
105import android.view.WindowManager;
106import android.view.WindowManagerImpl;
107import android.view.WindowManagerPolicy;
108import android.view.WindowManager.LayoutParams;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700109import android.view.animation.AccelerateInterpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110import android.view.animation.Animation;
111import android.view.animation.AnimationUtils;
112import android.view.animation.Transformation;
113
114import java.io.BufferedWriter;
115import java.io.File;
116import java.io.FileDescriptor;
117import java.io.IOException;
118import java.io.OutputStream;
119import java.io.OutputStreamWriter;
120import java.io.PrintWriter;
121import java.io.StringWriter;
122import java.net.Socket;
123import java.util.ArrayList;
124import java.util.HashMap;
125import java.util.HashSet;
126import java.util.Iterator;
127import java.util.List;
128
129/** {@hide} */
Dianne Hackbornddca3ee2009-07-23 19:01:31 -0700130public class WindowManagerService extends IWindowManager.Stub
131 implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 static final String TAG = "WindowManager";
133 static final boolean DEBUG = false;
134 static final boolean DEBUG_FOCUS = false;
135 static final boolean DEBUG_ANIM = false;
136 static final boolean DEBUG_LAYERS = false;
137 static final boolean DEBUG_INPUT = false;
138 static final boolean DEBUG_INPUT_METHOD = false;
139 static final boolean DEBUG_VISIBILITY = false;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -0700140 static final boolean DEBUG_WINDOW_MOVEMENT = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 static final boolean DEBUG_ORIENTATION = false;
142 static final boolean DEBUG_APP_TRANSITIONS = false;
143 static final boolean DEBUG_STARTING_WINDOW = false;
144 static final boolean DEBUG_REORDER = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700145 static final boolean DEBUG_WALLPAPER = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800146 static final boolean SHOW_TRANSACTIONS = false;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700147 static final boolean HIDE_STACK_CRAWLS = true;
Michael Chan53071d62009-05-13 17:29:48 -0700148 static final boolean MEASURE_LATENCY = false;
149 static private LatencyTimer lt;
150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 static final boolean PROFILE_ORIENTATION = false;
152 static final boolean BLUR = true;
Dave Bortcfe65242009-04-09 14:51:04 -0700153 static final boolean localLOGV = DEBUG;
Romain Guy06882f82009-06-10 13:36:04 -0700154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final int LOG_WM_NO_SURFACE_MEMORY = 31000;
Romain Guy06882f82009-06-10 13:36:04 -0700156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 /** How long to wait for subsequent key repeats, in milliseconds */
158 static final int KEY_REPEAT_DELAY = 50;
159
160 /** How much to multiply the policy's type layer, to reserve room
161 * for multiple windows of the same type and Z-ordering adjustment
162 * with TYPE_LAYER_OFFSET. */
163 static final int TYPE_LAYER_MULTIPLIER = 10000;
Romain Guy06882f82009-06-10 13:36:04 -0700164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
166 * or below others in the same layer. */
167 static final int TYPE_LAYER_OFFSET = 1000;
Romain Guy06882f82009-06-10 13:36:04 -0700168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 /** How much to increment the layer for each window, to reserve room
170 * for effect surfaces between them.
171 */
172 static final int WINDOW_LAYER_MULTIPLIER = 5;
Romain Guy06882f82009-06-10 13:36:04 -0700173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 /** The maximum length we will accept for a loaded animation duration:
175 * this is 10 seconds.
176 */
177 static final int MAX_ANIMATION_DURATION = 10*1000;
178
179 /** Amount of time (in milliseconds) to animate the dim surface from one
180 * value to another, when no window animation is driving it.
181 */
182 static final int DEFAULT_DIM_DURATION = 200;
183
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700184 /** Amount of time (in milliseconds) to animate the fade-in-out transition for
185 * compatible windows.
186 */
187 static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 /** Adjustment to time to perform a dim, to make it more dramatic.
190 */
191 static final int DIM_DURATION_MULTIPLIER = 6;
Romain Guy06882f82009-06-10 13:36:04 -0700192
Dianne Hackborncfaef692009-06-15 14:24:44 -0700193 static final int INJECT_FAILED = 0;
194 static final int INJECT_SUCCEEDED = 1;
195 static final int INJECT_NO_PERMISSION = -1;
196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 static final int UPDATE_FOCUS_NORMAL = 0;
198 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
199 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
200 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
Romain Guy06882f82009-06-10 13:36:04 -0700201
Michael Chane96440f2009-05-06 10:27:36 -0700202 /** The minimum time between dispatching touch events. */
203 int mMinWaitTimeBetweenTouchEvents = 1000 / 35;
204
205 // Last touch event time
206 long mLastTouchEventTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700207
Michael Chane96440f2009-05-06 10:27:36 -0700208 // Last touch event type
209 int mLastTouchEventType = OTHER_EVENT;
Romain Guy06882f82009-06-10 13:36:04 -0700210
Michael Chane96440f2009-05-06 10:27:36 -0700211 // Time to wait before calling useractivity again. This saves CPU usage
212 // when we get a flood of touch events.
213 static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000;
214
215 // Last time we call user activity
216 long mLastUserActivityCallTime = 0;
217
Romain Guy06882f82009-06-10 13:36:04 -0700218 // Last time we updated battery stats
Michael Chane96440f2009-05-06 10:27:36 -0700219 long mLastBatteryStatsCallTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 private static final String SYSTEM_SECURE = "ro.secure";
Romain Guy06882f82009-06-10 13:36:04 -0700222 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223
224 /**
225 * Condition waited on by {@link #reenableKeyguard} to know the call to
226 * the window policy has finished.
227 */
228 private boolean mWaitingUntilKeyguardReenabled = false;
229
230
231 final TokenWatcher mKeyguardDisabled = new TokenWatcher(
232 new Handler(), "WindowManagerService.mKeyguardDisabled") {
233 public void acquired() {
234 mPolicy.enableKeyguard(false);
235 }
236 public void released() {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700237 mPolicy.enableKeyguard(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 synchronized (mKeyguardDisabled) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 mWaitingUntilKeyguardReenabled = false;
240 mKeyguardDisabled.notifyAll();
241 }
242 }
243 };
244
245 final Context mContext;
246
247 final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700248
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 final boolean mLimitedAlphaCompositing;
Romain Guy06882f82009-06-10 13:36:04 -0700250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
252
253 final IActivityManager mActivityManager;
Romain Guy06882f82009-06-10 13:36:04 -0700254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 final IBatteryStats mBatteryStats;
Romain Guy06882f82009-06-10 13:36:04 -0700256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 /**
258 * All currently active sessions with clients.
259 */
260 final HashSet<Session> mSessions = new HashSet<Session>();
Romain Guy06882f82009-06-10 13:36:04 -0700261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 /**
263 * Mapping from an IWindow IBinder to the server's Window object.
264 * This is also used as the lock for all of our state.
265 */
266 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
267
268 /**
269 * Mapping from a token IBinder to a WindowToken object.
270 */
271 final HashMap<IBinder, WindowToken> mTokenMap =
272 new HashMap<IBinder, WindowToken>();
273
274 /**
275 * The same tokens as mTokenMap, stored in a list for efficient iteration
276 * over them.
277 */
278 final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 /**
281 * Window tokens that are in the process of exiting, but still
282 * on screen for animations.
283 */
284 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
285
286 /**
287 * Z-ordered (bottom-most first) list of all application tokens, for
288 * controlling the ordering of windows in different applications. This
289 * contains WindowToken objects.
290 */
291 final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
292
293 /**
294 * Application tokens that are in the process of exiting, but still
295 * on screen for animations.
296 */
297 final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
298
299 /**
300 * List of window tokens that have finished starting their application,
301 * and now need to have the policy remove their windows.
302 */
303 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
304
305 /**
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700306 * This was the app token that was used to retrieve the last enter
307 * animation. It will be used for the next exit animation.
308 */
309 AppWindowToken mLastEnterAnimToken;
310
311 /**
312 * These were the layout params used to retrieve the last enter animation.
313 * They will be used for the next exit animation.
314 */
315 LayoutParams mLastEnterAnimParams;
316
317 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800318 * Z-ordered (bottom-most first) list of all Window objects.
319 */
320 final ArrayList mWindows = new ArrayList();
321
322 /**
323 * Windows that are being resized. Used so we can tell the client about
324 * the resize after closing the transaction in which we resized the
325 * underlying surface.
326 */
327 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
328
329 /**
330 * Windows whose animations have ended and now must be removed.
331 */
332 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
333
334 /**
335 * Windows whose surface should be destroyed.
336 */
337 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
338
339 /**
340 * Windows that have lost input focus and are waiting for the new
341 * focus window to be displayed before they are told about this.
342 */
343 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
344
345 /**
346 * This is set when we have run out of memory, and will either be an empty
347 * list or contain windows that need to be force removed.
348 */
349 ArrayList<WindowState> mForceRemoves;
Romain Guy06882f82009-06-10 13:36:04 -0700350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 IInputMethodManager mInputMethodManager;
Romain Guy06882f82009-06-10 13:36:04 -0700352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 SurfaceSession mFxSession;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700354 private DimAnimator mDimAnimator = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800355 Surface mBlurSurface;
356 boolean mBlurShown;
Romain Guy06882f82009-06-10 13:36:04 -0700357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 int mTransactionSequence = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360 final float[] mTmpFloats = new float[9];
361
362 boolean mSafeMode;
363 boolean mDisplayEnabled = false;
364 boolean mSystemBooted = false;
365 int mRotation = 0;
366 int mRequestedRotation = 0;
367 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Dianne Hackborn321ae682009-03-27 16:16:03 -0700368 int mLastRotationFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369 ArrayList<IRotationWatcher> mRotationWatchers
370 = new ArrayList<IRotationWatcher>();
Romain Guy06882f82009-06-10 13:36:04 -0700371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800372 boolean mLayoutNeeded = true;
373 boolean mAnimationPending = false;
374 boolean mDisplayFrozen = false;
375 boolean mWindowsFreezingScreen = false;
376 long mFreezeGcPending = 0;
377 int mAppsFreezingScreen = 0;
378
379 // This is held as long as we have the screen frozen, to give us time to
380 // perform a rotation animation when turning off shows the lock screen which
381 // changes the orientation.
382 PowerManager.WakeLock mScreenFrozenLock;
Romain Guy06882f82009-06-10 13:36:04 -0700383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 // State management of app transitions. When we are preparing for a
385 // transition, mNextAppTransition will be the kind of transition to
386 // perform or TRANSIT_NONE if we are not waiting. If we are waiting,
387 // mOpeningApps and mClosingApps are the lists of tokens that will be
388 // made visible or hidden at the next transition.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700389 int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700390 String mNextAppTransitionPackage;
391 int mNextAppTransitionEnter;
392 int mNextAppTransitionExit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 boolean mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -0700394 boolean mAppTransitionRunning = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 boolean mAppTransitionTimeout = false;
396 boolean mStartingIconInTransition = false;
397 boolean mSkipAppTransitionAnimation = false;
398 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
399 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
Dianne Hackborna8f60182009-09-01 19:01:50 -0700400 final ArrayList<AppWindowToken> mToTopApps = new ArrayList<AppWindowToken>();
401 final ArrayList<AppWindowToken> mToBottomApps = new ArrayList<AppWindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 //flag to detect fat touch events
404 boolean mFatTouch = false;
405 Display mDisplay;
Romain Guy06882f82009-06-10 13:36:04 -0700406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 H mH = new H();
408
409 WindowState mCurrentFocus = null;
410 WindowState mLastFocus = null;
Romain Guy06882f82009-06-10 13:36:04 -0700411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 // This just indicates the window the input method is on top of, not
413 // necessarily the window its input is going to.
414 WindowState mInputMethodTarget = null;
415 WindowState mUpcomingInputMethodTarget = null;
416 boolean mInputMethodTargetWaitingAnim;
417 int mInputMethodAnimLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -0700418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 WindowState mInputMethodWindow = null;
420 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
421
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700422 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
423
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700424 // If non-null, this is the currently visible window that is associated
425 // with the wallpaper.
426 WindowState mWallpaperTarget = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700427 // If non-null, we are in the middle of animating from one wallpaper target
428 // to another, and this is the lower one in Z-order.
429 WindowState mLowerWallpaperTarget = null;
430 // If non-null, we are in the middle of animating from one wallpaper target
431 // to another, and this is the higher one in Z-order.
432 WindowState mUpperWallpaperTarget = null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700433 int mWallpaperAnimLayerAdjustment;
Dianne Hackborn73e92b42009-10-15 14:29:19 -0700434 float mLastWallpaperX = -1;
435 float mLastWallpaperY = -1;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800436 float mLastWallpaperXStep = -1;
437 float mLastWallpaperYStep = -1;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700438 // This is set when we are waiting for a wallpaper to tell us it is done
439 // changing its scroll position.
440 WindowState mWaitingOnWallpaper;
441 // The last time we had a timeout when waiting for a wallpaper.
442 long mLastWallpaperTimeoutTime;
443 // We give a wallpaper up to 150ms to finish scrolling.
444 static final long WALLPAPER_TIMEOUT = 150;
445 // Time we wait after a timeout before trying to wait again.
446 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 AppWindowToken mFocusedApp = null;
449
450 PowerManagerService mPowerManager;
Romain Guy06882f82009-06-10 13:36:04 -0700451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 float mWindowAnimationScale = 1.0f;
453 float mTransitionAnimationScale = 1.0f;
Romain Guy06882f82009-06-10 13:36:04 -0700454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 final KeyWaiter mKeyWaiter = new KeyWaiter();
456 final KeyQ mQueue;
457 final InputDispatcherThread mInputThread;
458
459 // Who is holding the screen on.
460 Session mHoldingScreenOn;
Romain Guy06882f82009-06-10 13:36:04 -0700461
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700462 boolean mTurnOnScreen;
463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 /**
465 * Whether the UI is currently running in touch mode (not showing
466 * navigational focus because the user is directly pressing the screen).
467 */
468 boolean mInTouchMode = false;
469
470 private ViewServer mViewServer;
471
472 final Rect mTempRect = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -0700473
Dianne Hackbornc485a602009-03-24 22:39:49 -0700474 final Configuration mTempConfiguration = new Configuration();
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700475 int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700476
477 // The frame use to limit the size of the app running in compatibility mode.
478 Rect mCompatibleScreenFrame = new Rect();
479 // The surface used to fill the outer rim of the app running in compatibility mode.
480 Surface mBackgroundFillerSurface = null;
481 boolean mBackgroundFillerShown = false;
482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 public static WindowManagerService main(Context context,
484 PowerManagerService pm, boolean haveInputMethods) {
485 WMThread thr = new WMThread(context, pm, haveInputMethods);
486 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800488 synchronized (thr) {
489 while (thr.mService == null) {
490 try {
491 thr.wait();
492 } catch (InterruptedException e) {
493 }
494 }
495 }
Romain Guy06882f82009-06-10 13:36:04 -0700496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 return thr.mService;
498 }
Romain Guy06882f82009-06-10 13:36:04 -0700499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 static class WMThread extends Thread {
501 WindowManagerService mService;
Romain Guy06882f82009-06-10 13:36:04 -0700502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 private final Context mContext;
504 private final PowerManagerService mPM;
505 private final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 public WMThread(Context context, PowerManagerService pm,
508 boolean haveInputMethods) {
509 super("WindowManager");
510 mContext = context;
511 mPM = pm;
512 mHaveInputMethods = haveInputMethods;
513 }
Romain Guy06882f82009-06-10 13:36:04 -0700514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 public void run() {
516 Looper.prepare();
517 WindowManagerService s = new WindowManagerService(mContext, mPM,
518 mHaveInputMethods);
519 android.os.Process.setThreadPriority(
520 android.os.Process.THREAD_PRIORITY_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -0700521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 synchronized (this) {
523 mService = s;
524 notifyAll();
525 }
Romain Guy06882f82009-06-10 13:36:04 -0700526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800527 Looper.loop();
528 }
529 }
530
531 static class PolicyThread extends Thread {
532 private final WindowManagerPolicy mPolicy;
533 private final WindowManagerService mService;
534 private final Context mContext;
535 private final PowerManagerService mPM;
536 boolean mRunning = false;
Romain Guy06882f82009-06-10 13:36:04 -0700537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 public PolicyThread(WindowManagerPolicy policy,
539 WindowManagerService service, Context context,
540 PowerManagerService pm) {
541 super("WindowManagerPolicy");
542 mPolicy = policy;
543 mService = service;
544 mContext = context;
545 mPM = pm;
546 }
Romain Guy06882f82009-06-10 13:36:04 -0700547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 public void run() {
549 Looper.prepare();
550 //Looper.myLooper().setMessageLogging(new LogPrinter(
551 // Log.VERBOSE, "WindowManagerPolicy"));
552 android.os.Process.setThreadPriority(
553 android.os.Process.THREAD_PRIORITY_FOREGROUND);
554 mPolicy.init(mContext, mService, mPM);
Romain Guy06882f82009-06-10 13:36:04 -0700555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 synchronized (this) {
557 mRunning = true;
558 notifyAll();
559 }
Romain Guy06882f82009-06-10 13:36:04 -0700560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 Looper.loop();
562 }
563 }
564
565 private WindowManagerService(Context context, PowerManagerService pm,
566 boolean haveInputMethods) {
Michael Chan53071d62009-05-13 17:29:48 -0700567 if (MEASURE_LATENCY) {
568 lt = new LatencyTimer(100, 1000);
569 }
570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 mContext = context;
572 mHaveInputMethods = haveInputMethods;
573 mLimitedAlphaCompositing = context.getResources().getBoolean(
574 com.android.internal.R.bool.config_sf_limitedAlpha);
Romain Guy06882f82009-06-10 13:36:04 -0700575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576 mPowerManager = pm;
577 mPowerManager.setPolicy(mPolicy);
578 PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
579 mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
580 "SCREEN_FROZEN");
581 mScreenFrozenLock.setReferenceCounted(false);
582
583 mActivityManager = ActivityManagerNative.getDefault();
584 mBatteryStats = BatteryStatsService.getService();
585
586 // Get persisted window scale setting
587 mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
588 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
589 mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
590 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
Romain Guy06882f82009-06-10 13:36:04 -0700591
Michael Chan9f028e62009-08-04 17:37:46 -0700592 int max_events_per_sec = 35;
593 try {
594 max_events_per_sec = Integer.parseInt(SystemProperties
595 .get("windowsmgr.max_events_per_sec"));
596 if (max_events_per_sec < 1) {
597 max_events_per_sec = 35;
598 }
599 } catch (NumberFormatException e) {
600 }
601 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 mQueue = new KeyQ();
604
605 mInputThread = new InputDispatcherThread();
Romain Guy06882f82009-06-10 13:36:04 -0700606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607 PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
608 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 synchronized (thr) {
611 while (!thr.mRunning) {
612 try {
613 thr.wait();
614 } catch (InterruptedException e) {
615 }
616 }
617 }
Romain Guy06882f82009-06-10 13:36:04 -0700618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800619 mInputThread.start();
Romain Guy06882f82009-06-10 13:36:04 -0700620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 // Add ourself to the Watchdog monitors.
622 Watchdog.getInstance().addMonitor(this);
623 }
624
625 @Override
626 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
627 throws RemoteException {
628 try {
629 return super.onTransact(code, data, reply, flags);
630 } catch (RuntimeException e) {
631 // The window manager only throws security exceptions, so let's
632 // log all others.
633 if (!(e instanceof SecurityException)) {
634 Log.e(TAG, "Window Manager Crash", e);
635 }
636 throw e;
637 }
638 }
639
640 private void placeWindowAfter(Object pos, WindowState window) {
641 final int i = mWindows.indexOf(pos);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700642 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 TAG, "Adding window " + window + " at "
644 + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
645 mWindows.add(i+1, window);
646 }
647
648 private void placeWindowBefore(Object pos, WindowState window) {
649 final int i = mWindows.indexOf(pos);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700650 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 TAG, "Adding window " + window + " at "
652 + i + " of " + mWindows.size() + " (before " + pos + ")");
653 mWindows.add(i, window);
654 }
655
656 //This method finds out the index of a window that has the same app token as
657 //win. used for z ordering the windows in mWindows
658 private int findIdxBasedOnAppTokens(WindowState win) {
659 //use a local variable to cache mWindows
660 ArrayList localmWindows = mWindows;
661 int jmax = localmWindows.size();
662 if(jmax == 0) {
663 return -1;
664 }
665 for(int j = (jmax-1); j >= 0; j--) {
666 WindowState wentry = (WindowState)localmWindows.get(j);
667 if(wentry.mAppToken == win.mAppToken) {
668 return j;
669 }
670 }
671 return -1;
672 }
Romain Guy06882f82009-06-10 13:36:04 -0700673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800674 private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
675 final IWindow client = win.mClient;
676 final WindowToken token = win.mToken;
677 final ArrayList localmWindows = mWindows;
Romain Guy06882f82009-06-10 13:36:04 -0700678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800679 final int N = localmWindows.size();
680 final WindowState attached = win.mAttachedWindow;
681 int i;
682 if (attached == null) {
683 int tokenWindowsPos = token.windows.size();
684 if (token.appWindowToken != null) {
685 int index = tokenWindowsPos-1;
686 if (index >= 0) {
687 // If this application has existing windows, we
688 // simply place the new window on top of them... but
689 // keep the starting window on top.
690 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
691 // Base windows go behind everything else.
692 placeWindowBefore(token.windows.get(0), win);
693 tokenWindowsPos = 0;
694 } else {
695 AppWindowToken atoken = win.mAppToken;
696 if (atoken != null &&
697 token.windows.get(index) == atoken.startingWindow) {
698 placeWindowBefore(token.windows.get(index), win);
699 tokenWindowsPos--;
700 } else {
701 int newIdx = findIdxBasedOnAppTokens(win);
702 if(newIdx != -1) {
Romain Guy06882f82009-06-10 13:36:04 -0700703 //there is a window above this one associated with the same
704 //apptoken note that the window could be a floating window
705 //that was created later or a window at the top of the list of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 //windows associated with this token.
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700707 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
708 TAG, "Adding window " + win + " at "
709 + (newIdx+1) + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 localmWindows.add(newIdx+1, win);
Romain Guy06882f82009-06-10 13:36:04 -0700711 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 }
713 }
714 } else {
715 if (localLOGV) Log.v(
716 TAG, "Figuring out where to add app window "
717 + client.asBinder() + " (token=" + token + ")");
718 // Figure out where the window should go, based on the
719 // order of applications.
720 final int NA = mAppTokens.size();
721 Object pos = null;
722 for (i=NA-1; i>=0; i--) {
723 AppWindowToken t = mAppTokens.get(i);
724 if (t == token) {
725 i--;
726 break;
727 }
Dianne Hackborna8f60182009-09-01 19:01:50 -0700728
729 // We haven't reached the token yet; if this token
730 // is not going to the bottom and has windows, we can
731 // use it as an anchor for when we do reach the token.
732 if (!t.sendingToBottom && t.windows.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800733 pos = t.windows.get(0);
734 }
735 }
736 // We now know the index into the apps. If we found
737 // an app window above, that gives us the position; else
738 // we need to look some more.
739 if (pos != null) {
740 // Move behind any windows attached to this one.
Romain Guy06882f82009-06-10 13:36:04 -0700741 WindowToken atoken =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800742 mTokenMap.get(((WindowState)pos).mClient.asBinder());
743 if (atoken != null) {
744 final int NC = atoken.windows.size();
745 if (NC > 0) {
746 WindowState bottom = atoken.windows.get(0);
747 if (bottom.mSubLayer < 0) {
748 pos = bottom;
749 }
750 }
751 }
752 placeWindowBefore(pos, win);
753 } else {
Dianne Hackborna8f60182009-09-01 19:01:50 -0700754 // Continue looking down until we find the first
755 // token that has windows.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 while (i >= 0) {
757 AppWindowToken t = mAppTokens.get(i);
758 final int NW = t.windows.size();
759 if (NW > 0) {
760 pos = t.windows.get(NW-1);
761 break;
762 }
763 i--;
764 }
765 if (pos != null) {
766 // Move in front of any windows attached to this
767 // one.
768 WindowToken atoken =
769 mTokenMap.get(((WindowState)pos).mClient.asBinder());
770 if (atoken != null) {
771 final int NC = atoken.windows.size();
772 if (NC > 0) {
773 WindowState top = atoken.windows.get(NC-1);
774 if (top.mSubLayer >= 0) {
775 pos = top;
776 }
777 }
778 }
779 placeWindowAfter(pos, win);
780 } else {
781 // Just search for the start of this layer.
782 final int myLayer = win.mBaseLayer;
783 for (i=0; i<N; i++) {
784 WindowState w = (WindowState)localmWindows.get(i);
785 if (w.mBaseLayer > myLayer) {
786 break;
787 }
788 }
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700789 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
790 TAG, "Adding window " + win + " at "
791 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 localmWindows.add(i, win);
793 }
794 }
795 }
796 } else {
797 // Figure out where window should go, based on layer.
798 final int myLayer = win.mBaseLayer;
799 for (i=N-1; i>=0; i--) {
800 if (((WindowState)localmWindows.get(i)).mBaseLayer <= myLayer) {
801 i++;
802 break;
803 }
804 }
805 if (i < 0) i = 0;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700806 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Log.v(
807 TAG, "Adding window " + win + " at "
808 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800809 localmWindows.add(i, win);
810 }
811 if (addToToken) {
812 token.windows.add(tokenWindowsPos, win);
813 }
814
815 } else {
816 // Figure out this window's ordering relative to the window
817 // it is attached to.
818 final int NA = token.windows.size();
819 final int sublayer = win.mSubLayer;
820 int largestSublayer = Integer.MIN_VALUE;
821 WindowState windowWithLargestSublayer = null;
822 for (i=0; i<NA; i++) {
823 WindowState w = token.windows.get(i);
824 final int wSublayer = w.mSubLayer;
825 if (wSublayer >= largestSublayer) {
826 largestSublayer = wSublayer;
827 windowWithLargestSublayer = w;
828 }
829 if (sublayer < 0) {
830 // For negative sublayers, we go below all windows
831 // in the same sublayer.
832 if (wSublayer >= sublayer) {
833 if (addToToken) {
834 token.windows.add(i, win);
835 }
836 placeWindowBefore(
837 wSublayer >= 0 ? attached : w, win);
838 break;
839 }
840 } else {
841 // For positive sublayers, we go above all windows
842 // in the same sublayer.
843 if (wSublayer > sublayer) {
844 if (addToToken) {
845 token.windows.add(i, win);
846 }
847 placeWindowBefore(w, win);
848 break;
849 }
850 }
851 }
852 if (i >= NA) {
853 if (addToToken) {
854 token.windows.add(win);
855 }
856 if (sublayer < 0) {
857 placeWindowBefore(attached, win);
858 } else {
859 placeWindowAfter(largestSublayer >= 0
860 ? windowWithLargestSublayer
861 : attached,
862 win);
863 }
864 }
865 }
Romain Guy06882f82009-06-10 13:36:04 -0700866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 if (win.mAppToken != null && addToToken) {
868 win.mAppToken.allAppWindows.add(win);
869 }
870 }
Romain Guy06882f82009-06-10 13:36:04 -0700871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 static boolean canBeImeTarget(WindowState w) {
873 final int fl = w.mAttrs.flags
874 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
875 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
876 return w.isVisibleOrAdding();
877 }
878 return false;
879 }
Romain Guy06882f82009-06-10 13:36:04 -0700880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800881 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
882 final ArrayList localmWindows = mWindows;
883 final int N = localmWindows.size();
884 WindowState w = null;
885 int i = N;
886 while (i > 0) {
887 i--;
888 w = (WindowState)localmWindows.get(i);
Romain Guy06882f82009-06-10 13:36:04 -0700889
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 //Log.i(TAG, "Checking window @" + i + " " + w + " fl=0x"
891 // + Integer.toHexString(w.mAttrs.flags));
892 if (canBeImeTarget(w)) {
893 //Log.i(TAG, "Putting input method here!");
Romain Guy06882f82009-06-10 13:36:04 -0700894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800895 // Yet more tricksyness! If this window is a "starting"
896 // window, we do actually want to be on top of it, but
897 // it is not -really- where input will go. So if the caller
898 // is not actually looking to move the IME, look down below
899 // for a real window to target...
900 if (!willMove
901 && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
902 && i > 0) {
903 WindowState wb = (WindowState)localmWindows.get(i-1);
904 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
905 i--;
906 w = wb;
907 }
908 }
909 break;
910 }
911 }
Romain Guy06882f82009-06-10 13:36:04 -0700912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 mUpcomingInputMethodTarget = w;
Romain Guy06882f82009-06-10 13:36:04 -0700914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800915 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Desired input method target="
916 + w + " willMove=" + willMove);
Romain Guy06882f82009-06-10 13:36:04 -0700917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 if (willMove && w != null) {
919 final WindowState curTarget = mInputMethodTarget;
920 if (curTarget != null && curTarget.mAppToken != null) {
Romain Guy06882f82009-06-10 13:36:04 -0700921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 // Now some fun for dealing with window animations that
923 // modify the Z order. We need to look at all windows below
924 // the current target that are in this app, finding the highest
925 // visible one in layering.
926 AppWindowToken token = curTarget.mAppToken;
927 WindowState highestTarget = null;
928 int highestPos = 0;
929 if (token.animating || token.animation != null) {
930 int pos = 0;
931 pos = localmWindows.indexOf(curTarget);
932 while (pos >= 0) {
933 WindowState win = (WindowState)localmWindows.get(pos);
934 if (win.mAppToken != token) {
935 break;
936 }
937 if (!win.mRemoved) {
938 if (highestTarget == null || win.mAnimLayer >
939 highestTarget.mAnimLayer) {
940 highestTarget = win;
941 highestPos = pos;
942 }
943 }
944 pos--;
945 }
946 }
Romain Guy06882f82009-06-10 13:36:04 -0700947
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800948 if (highestTarget != null) {
Romain Guy06882f82009-06-10 13:36:04 -0700949 if (DEBUG_INPUT_METHOD) Log.v(TAG, "mNextAppTransition="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800950 + mNextAppTransition + " " + highestTarget
951 + " animating=" + highestTarget.isAnimating()
952 + " layer=" + highestTarget.mAnimLayer
953 + " new layer=" + w.mAnimLayer);
Romain Guy06882f82009-06-10 13:36:04 -0700954
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700955 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 // If we are currently setting up for an animation,
957 // hold everything until we can find out what will happen.
958 mInputMethodTargetWaitingAnim = true;
959 mInputMethodTarget = highestTarget;
960 return highestPos + 1;
961 } else if (highestTarget.isAnimating() &&
962 highestTarget.mAnimLayer > w.mAnimLayer) {
963 // If the window we are currently targeting is involved
964 // with an animation, and it is on top of the next target
965 // we will be over, then hold off on moving until
966 // that is done.
967 mInputMethodTarget = highestTarget;
968 return highestPos + 1;
969 }
970 }
971 }
972 }
Romain Guy06882f82009-06-10 13:36:04 -0700973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 //Log.i(TAG, "Placing input method @" + (i+1));
975 if (w != null) {
976 if (willMove) {
977 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700978 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800979 if (DEBUG_INPUT_METHOD) Log.w(TAG, "Moving IM target from "
980 + mInputMethodTarget + " to " + w, e);
981 mInputMethodTarget = w;
982 if (w.mAppToken != null) {
983 setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
984 } else {
985 setInputMethodAnimLayerAdjustment(0);
986 }
987 }
988 return i+1;
989 }
990 if (willMove) {
991 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700992 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 if (DEBUG_INPUT_METHOD) Log.w(TAG, "Moving IM target from "
994 + mInputMethodTarget + " to null", e);
995 mInputMethodTarget = null;
996 setInputMethodAnimLayerAdjustment(0);
997 }
998 return -1;
999 }
Romain Guy06882f82009-06-10 13:36:04 -07001000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 void addInputMethodWindowToListLocked(WindowState win) {
1002 int pos = findDesiredInputMethodWindowIndexLocked(true);
1003 if (pos >= 0) {
1004 win.mTargetAppToken = mInputMethodTarget.mAppToken;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001005 if (DEBUG_WINDOW_MOVEMENT) Log.v(
1006 TAG, "Adding input method window " + win + " at " + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 mWindows.add(pos, win);
1008 moveInputMethodDialogsLocked(pos+1);
1009 return;
1010 }
1011 win.mTargetAppToken = null;
1012 addWindowToListInOrderLocked(win, true);
1013 moveInputMethodDialogsLocked(pos);
1014 }
Romain Guy06882f82009-06-10 13:36:04 -07001015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 void setInputMethodAnimLayerAdjustment(int adj) {
1017 if (DEBUG_LAYERS) Log.v(TAG, "Setting im layer adj to " + adj);
1018 mInputMethodAnimLayerAdjustment = adj;
1019 WindowState imw = mInputMethodWindow;
1020 if (imw != null) {
1021 imw.mAnimLayer = imw.mLayer + adj;
1022 if (DEBUG_LAYERS) Log.v(TAG, "IM win " + imw
1023 + " anim layer: " + imw.mAnimLayer);
1024 int wi = imw.mChildWindows.size();
1025 while (wi > 0) {
1026 wi--;
1027 WindowState cw = (WindowState)imw.mChildWindows.get(wi);
1028 cw.mAnimLayer = cw.mLayer + adj;
1029 if (DEBUG_LAYERS) Log.v(TAG, "IM win " + cw
1030 + " anim layer: " + cw.mAnimLayer);
1031 }
1032 }
1033 int di = mInputMethodDialogs.size();
1034 while (di > 0) {
1035 di --;
1036 imw = mInputMethodDialogs.get(di);
1037 imw.mAnimLayer = imw.mLayer + adj;
1038 if (DEBUG_LAYERS) Log.v(TAG, "IM win " + imw
1039 + " anim layer: " + imw.mAnimLayer);
1040 }
1041 }
Romain Guy06882f82009-06-10 13:36:04 -07001042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1044 int wpos = mWindows.indexOf(win);
1045 if (wpos >= 0) {
1046 if (wpos < interestingPos) interestingPos--;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001047 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Temp removing at " + wpos + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 mWindows.remove(wpos);
1049 int NC = win.mChildWindows.size();
1050 while (NC > 0) {
1051 NC--;
1052 WindowState cw = (WindowState)win.mChildWindows.get(NC);
1053 int cpos = mWindows.indexOf(cw);
1054 if (cpos >= 0) {
1055 if (cpos < interestingPos) interestingPos--;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001056 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Temp removing child at "
1057 + cpos + ": " + cw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001058 mWindows.remove(cpos);
1059 }
1060 }
1061 }
1062 return interestingPos;
1063 }
Romain Guy06882f82009-06-10 13:36:04 -07001064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 private void reAddWindowToListInOrderLocked(WindowState win) {
1066 addWindowToListInOrderLocked(win, false);
1067 // This is a hack to get all of the child windows added as well
1068 // at the right position. Child windows should be rare and
1069 // this case should be rare, so it shouldn't be that big a deal.
1070 int wpos = mWindows.indexOf(win);
1071 if (wpos >= 0) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001072 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "ReAdd removing from " + wpos
1073 + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001074 mWindows.remove(wpos);
1075 reAddWindowLocked(wpos, win);
1076 }
1077 }
Romain Guy06882f82009-06-10 13:36:04 -07001078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 void logWindowList(String prefix) {
1080 int N = mWindows.size();
1081 while (N > 0) {
1082 N--;
1083 Log.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
1084 }
1085 }
Romain Guy06882f82009-06-10 13:36:04 -07001086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 void moveInputMethodDialogsLocked(int pos) {
1088 ArrayList<WindowState> dialogs = mInputMethodDialogs;
Romain Guy06882f82009-06-10 13:36:04 -07001089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 final int N = dialogs.size();
1091 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
1092 for (int i=0; i<N; i++) {
1093 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1094 }
1095 if (DEBUG_INPUT_METHOD) {
1096 Log.v(TAG, "Window list w/pos=" + pos);
1097 logWindowList(" ");
1098 }
Romain Guy06882f82009-06-10 13:36:04 -07001099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 if (pos >= 0) {
1101 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1102 if (pos < mWindows.size()) {
1103 WindowState wp = (WindowState)mWindows.get(pos);
1104 if (wp == mInputMethodWindow) {
1105 pos++;
1106 }
1107 }
1108 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
1109 for (int i=0; i<N; i++) {
1110 WindowState win = dialogs.get(i);
1111 win.mTargetAppToken = targetAppToken;
1112 pos = reAddWindowLocked(pos, win);
1113 }
1114 if (DEBUG_INPUT_METHOD) {
1115 Log.v(TAG, "Final window list:");
1116 logWindowList(" ");
1117 }
1118 return;
1119 }
1120 for (int i=0; i<N; i++) {
1121 WindowState win = dialogs.get(i);
1122 win.mTargetAppToken = null;
1123 reAddWindowToListInOrderLocked(win);
1124 if (DEBUG_INPUT_METHOD) {
1125 Log.v(TAG, "No IM target, final list:");
1126 logWindowList(" ");
1127 }
1128 }
1129 }
Romain Guy06882f82009-06-10 13:36:04 -07001130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1132 final WindowState imWin = mInputMethodWindow;
1133 final int DN = mInputMethodDialogs.size();
1134 if (imWin == null && DN == 0) {
1135 return false;
1136 }
Romain Guy06882f82009-06-10 13:36:04 -07001137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1139 if (imPos >= 0) {
1140 // In this case, the input method windows are to be placed
1141 // immediately above the window they are targeting.
Romain Guy06882f82009-06-10 13:36:04 -07001142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143 // First check to see if the input method windows are already
1144 // located here, and contiguous.
1145 final int N = mWindows.size();
1146 WindowState firstImWin = imPos < N
1147 ? (WindowState)mWindows.get(imPos) : null;
Romain Guy06882f82009-06-10 13:36:04 -07001148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149 // Figure out the actual input method window that should be
1150 // at the bottom of their stack.
1151 WindowState baseImWin = imWin != null
1152 ? imWin : mInputMethodDialogs.get(0);
1153 if (baseImWin.mChildWindows.size() > 0) {
1154 WindowState cw = (WindowState)baseImWin.mChildWindows.get(0);
1155 if (cw.mSubLayer < 0) baseImWin = cw;
1156 }
Romain Guy06882f82009-06-10 13:36:04 -07001157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 if (firstImWin == baseImWin) {
1159 // The windows haven't moved... but are they still contiguous?
1160 // First find the top IM window.
1161 int pos = imPos+1;
1162 while (pos < N) {
1163 if (!((WindowState)mWindows.get(pos)).mIsImWindow) {
1164 break;
1165 }
1166 pos++;
1167 }
1168 pos++;
1169 // Now there should be no more input method windows above.
1170 while (pos < N) {
1171 if (((WindowState)mWindows.get(pos)).mIsImWindow) {
1172 break;
1173 }
1174 pos++;
1175 }
1176 if (pos >= N) {
1177 // All is good!
1178 return false;
1179 }
1180 }
Romain Guy06882f82009-06-10 13:36:04 -07001181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 if (imWin != null) {
1183 if (DEBUG_INPUT_METHOD) {
1184 Log.v(TAG, "Moving IM from " + imPos);
1185 logWindowList(" ");
1186 }
1187 imPos = tmpRemoveWindowLocked(imPos, imWin);
1188 if (DEBUG_INPUT_METHOD) {
1189 Log.v(TAG, "List after moving with new pos " + imPos + ":");
1190 logWindowList(" ");
1191 }
1192 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1193 reAddWindowLocked(imPos, imWin);
1194 if (DEBUG_INPUT_METHOD) {
1195 Log.v(TAG, "List after moving IM to " + imPos + ":");
1196 logWindowList(" ");
1197 }
1198 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1199 } else {
1200 moveInputMethodDialogsLocked(imPos);
1201 }
Romain Guy06882f82009-06-10 13:36:04 -07001202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 } else {
1204 // In this case, the input method windows go in a fixed layer,
1205 // because they aren't currently associated with a focus window.
Romain Guy06882f82009-06-10 13:36:04 -07001206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001207 if (imWin != null) {
1208 if (DEBUG_INPUT_METHOD) Log.v(TAG, "Moving IM from " + imPos);
1209 tmpRemoveWindowLocked(0, imWin);
1210 imWin.mTargetAppToken = null;
1211 reAddWindowToListInOrderLocked(imWin);
1212 if (DEBUG_INPUT_METHOD) {
1213 Log.v(TAG, "List with no IM target:");
1214 logWindowList(" ");
1215 }
1216 if (DN > 0) moveInputMethodDialogsLocked(-1);;
1217 } else {
1218 moveInputMethodDialogsLocked(-1);;
1219 }
Romain Guy06882f82009-06-10 13:36:04 -07001220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001221 }
Romain Guy06882f82009-06-10 13:36:04 -07001222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 if (needAssignLayers) {
1224 assignLayersLocked();
1225 }
Romain Guy06882f82009-06-10 13:36:04 -07001226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 return true;
1228 }
Romain Guy06882f82009-06-10 13:36:04 -07001229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 void adjustInputMethodDialogsLocked() {
1231 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
1232 }
Romain Guy06882f82009-06-10 13:36:04 -07001233
Dianne Hackborn25994b42009-09-04 14:21:19 -07001234 final boolean isWallpaperVisible(WindowState wallpaperTarget) {
1235 if (DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper vis: target obscured="
1236 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1237 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1238 ? wallpaperTarget.mAppToken.animation : null)
1239 + " upper=" + mUpperWallpaperTarget
1240 + " lower=" + mLowerWallpaperTarget);
1241 return (wallpaperTarget != null
1242 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1243 && wallpaperTarget.mAppToken.animation != null)))
1244 || mUpperWallpaperTarget != null
1245 || mLowerWallpaperTarget != null;
1246 }
1247
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001248 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1249 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
1250
1251 int adjustWallpaperWindowsLocked() {
1252 int changed = 0;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001253
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001254 final int dw = mDisplay.getWidth();
1255 final int dh = mDisplay.getHeight();
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001256
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001257 // First find top-most window that has asked to be on top of the
1258 // wallpaper; all wallpapers go behind it.
1259 final ArrayList localmWindows = mWindows;
1260 int N = localmWindows.size();
1261 WindowState w = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001262 WindowState foundW = null;
1263 int foundI = 0;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001264 WindowState topCurW = null;
1265 int topCurI = 0;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001266 int i = N;
1267 while (i > 0) {
1268 i--;
1269 w = (WindowState)localmWindows.get(i);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001270 if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
1271 if (topCurW == null) {
1272 topCurW = w;
1273 topCurI = i;
1274 }
1275 continue;
1276 }
1277 topCurW = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001278 if (w.mAppToken != null) {
1279 // If this window's app token is hidden and not animating,
1280 // it is of no interest to us.
1281 if (w.mAppToken.hidden && w.mAppToken.animation == null) {
1282 if (DEBUG_WALLPAPER) Log.v(TAG,
1283 "Skipping hidden or animating token: " + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001284 topCurW = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001285 continue;
1286 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001287 }
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001288 if (DEBUG_WALLPAPER) Log.v(TAG, "Win " + w + ": readyfordisplay="
1289 + w.isReadyForDisplay() + " drawpending=" + w.mDrawPending
1290 + " commitdrawpending=" + w.mCommitDrawPending);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001291 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07001292 && (mWallpaperTarget == w
1293 || (!w.mDrawPending && !w.mCommitDrawPending))) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001294 if (DEBUG_WALLPAPER) Log.v(TAG,
1295 "Found wallpaper activity: #" + i + "=" + w);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001296 foundW = w;
1297 foundI = i;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001298 if (w == mWallpaperTarget && ((w.mAppToken != null
1299 && w.mAppToken.animation != null)
1300 || w.mAnimation != null)) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001301 // The current wallpaper target is animating, so we'll
1302 // look behind it for another possible target and figure
1303 // out what is going on below.
1304 if (DEBUG_WALLPAPER) Log.v(TAG, "Win " + w
1305 + ": token animating, looking behind.");
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001306 continue;
1307 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001308 break;
1309 }
1310 }
1311
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001312 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001313 // If we are currently waiting for an app transition, and either
1314 // the current target or the next target are involved with it,
1315 // then hold off on doing anything with the wallpaper.
1316 // Note that we are checking here for just whether the target
1317 // is part of an app token... which is potentially overly aggressive
1318 // (the app token may not be involved in the transition), but good
1319 // enough (we'll just wait until whatever transition is pending
1320 // executes).
1321 if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001322 if (DEBUG_WALLPAPER) Log.v(TAG,
1323 "Wallpaper not changing: waiting for app anim in current target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001324 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001325 }
1326 if (foundW != null && foundW.mAppToken != null) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001327 if (DEBUG_WALLPAPER) Log.v(TAG,
1328 "Wallpaper not changing: waiting for app anim in found target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001329 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001330 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001331 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001332
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001333 if (mWallpaperTarget != foundW) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001334 if (DEBUG_WALLPAPER) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001335 Log.v(TAG, "New wallpaper target: " + foundW
1336 + " oldTarget: " + mWallpaperTarget);
1337 }
1338
1339 mLowerWallpaperTarget = null;
1340 mUpperWallpaperTarget = null;
1341
1342 WindowState oldW = mWallpaperTarget;
1343 mWallpaperTarget = foundW;
1344
1345 // Now what is happening... if the current and new targets are
1346 // animating, then we are in our super special mode!
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001347 if (foundW != null && oldW != null) {
1348 boolean oldAnim = oldW.mAnimation != null
1349 || (oldW.mAppToken != null && oldW.mAppToken.animation != null);
1350 boolean foundAnim = foundW.mAnimation != null
1351 || (foundW.mAppToken != null && foundW.mAppToken.animation != null);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001352 if (DEBUG_WALLPAPER) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001353 Log.v(TAG, "New animation: " + foundAnim
1354 + " old animation: " + oldAnim);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001355 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001356 if (foundAnim && oldAnim) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001357 int oldI = localmWindows.indexOf(oldW);
1358 if (DEBUG_WALLPAPER) {
1359 Log.v(TAG, "New i: " + foundI + " old i: " + oldI);
1360 }
1361 if (oldI >= 0) {
1362 if (DEBUG_WALLPAPER) {
1363 Log.v(TAG, "Animating wallpapers: old#" + oldI
1364 + "=" + oldW + "; new#" + foundI
1365 + "=" + foundW);
1366 }
1367
1368 // Set the new target correctly.
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001369 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001370 if (DEBUG_WALLPAPER) {
1371 Log.v(TAG, "Old wallpaper still the target.");
1372 }
1373 mWallpaperTarget = oldW;
1374 }
1375
1376 // Now set the upper and lower wallpaper targets
1377 // correctly, and make sure that we are positioning
1378 // the wallpaper below the lower.
1379 if (foundI > oldI) {
1380 // The new target is on top of the old one.
1381 if (DEBUG_WALLPAPER) {
1382 Log.v(TAG, "Found target above old target.");
1383 }
1384 mUpperWallpaperTarget = foundW;
1385 mLowerWallpaperTarget = oldW;
1386 foundW = oldW;
1387 foundI = oldI;
1388 } else {
1389 // The new target is below the old one.
1390 if (DEBUG_WALLPAPER) {
1391 Log.v(TAG, "Found target below old target.");
1392 }
1393 mUpperWallpaperTarget = oldW;
1394 mLowerWallpaperTarget = foundW;
1395 }
1396 }
1397 }
1398 }
1399
Dianne Hackborn6b1cb352009-09-28 18:27:26 -07001400 } else if (mLowerWallpaperTarget != null) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001401 // Is it time to stop animating?
Dianne Hackborn6b1cb352009-09-28 18:27:26 -07001402 boolean lowerAnimating = mLowerWallpaperTarget.mAnimation != null
1403 || (mLowerWallpaperTarget.mAppToken != null
1404 && mLowerWallpaperTarget.mAppToken.animation != null);
1405 boolean upperAnimating = mUpperWallpaperTarget.mAnimation != null
1406 || (mUpperWallpaperTarget.mAppToken != null
1407 && mUpperWallpaperTarget.mAppToken.animation != null);
1408 if (!lowerAnimating || !upperAnimating) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001409 if (DEBUG_WALLPAPER) {
1410 Log.v(TAG, "No longer animating wallpaper targets!");
1411 }
1412 mLowerWallpaperTarget = null;
1413 mUpperWallpaperTarget = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001414 }
1415 }
1416
1417 boolean visible = foundW != null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001418 if (visible) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001419 // The window is visible to the compositor... but is it visible
1420 // to the user? That is what the wallpaper cares about.
Dianne Hackborn25994b42009-09-04 14:21:19 -07001421 visible = isWallpaperVisible(foundW);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001422 if (DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper visibility: " + visible);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001423
1424 // If the wallpaper target is animating, we may need to copy
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001425 // its layer adjustment. Only do this if we are not transfering
1426 // between two wallpaper targets.
1427 mWallpaperAnimLayerAdjustment =
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001428 (mLowerWallpaperTarget == null && foundW.mAppToken != null)
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001429 ? foundW.mAppToken.animLayerAdjustment : 0;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001430
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001431 final int maxLayer = mPolicy.getMaxWallpaperLayer()
1432 * TYPE_LAYER_MULTIPLIER
1433 + TYPE_LAYER_OFFSET;
1434
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001435 // Now w is the window we are supposed to be behind... but we
1436 // need to be sure to also be behind any of its attached windows,
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001437 // AND any starting window associated with it, AND below the
1438 // maximum layer the policy allows for wallpapers.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001439 while (foundI > 0) {
1440 WindowState wb = (WindowState)localmWindows.get(foundI-1);
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001441 if (wb.mBaseLayer < maxLayer &&
1442 wb.mAttachedWindow != foundW &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001443 (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001444 wb.mToken != foundW.mToken)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001445 // This window is not related to the previous one in any
1446 // interesting way, so stop here.
1447 break;
1448 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001449 foundW = wb;
1450 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001451 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07001452 } else {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001453 if (DEBUG_WALLPAPER) Log.v(TAG, "No wallpaper target");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001454 }
1455
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001456 if (foundW == null && topCurW != null) {
1457 // There is no wallpaper target, so it goes at the bottom.
1458 // We will assume it is the same place as last time, if known.
1459 foundW = topCurW;
1460 foundI = topCurI+1;
1461 } else {
1462 // Okay i is the position immediately above the wallpaper. Look at
1463 // what is below it for later.
1464 foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
1465 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001466
Dianne Hackborn284ac932009-08-28 10:34:25 -07001467 if (visible) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001468 if (mWallpaperTarget.mWallpaperX >= 0) {
1469 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001470 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001471 }
1472 if (mWallpaperTarget.mWallpaperY >= 0) {
1473 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001474 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001475 }
Dianne Hackborn284ac932009-08-28 10:34:25 -07001476 }
1477
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001478 // Start stepping backwards from here, ensuring that our wallpaper windows
1479 // are correctly placed.
1480 int curTokenIndex = mWallpaperTokens.size();
1481 while (curTokenIndex > 0) {
1482 curTokenIndex--;
1483 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001484 if (token.hidden == visible) {
1485 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1486 token.hidden = !visible;
1487 // Need to do a layout to ensure the wallpaper now has the
1488 // correct size.
1489 mLayoutNeeded = true;
1490 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07001491
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001492 int curWallpaperIndex = token.windows.size();
1493 while (curWallpaperIndex > 0) {
1494 curWallpaperIndex--;
1495 WindowState wallpaper = token.windows.get(curWallpaperIndex);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001496
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001497 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001498 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001499 }
1500
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001501 // First, make sure the client has the current visibility
1502 // state.
1503 if (wallpaper.mWallpaperVisible != visible) {
1504 wallpaper.mWallpaperVisible = visible;
1505 try {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001506 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Log.v(TAG,
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001507 "Setting visibility of wallpaper " + wallpaper
1508 + ": " + visible);
1509 wallpaper.mClient.dispatchAppVisibility(visible);
1510 } catch (RemoteException e) {
1511 }
1512 }
1513
1514 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001515 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper win "
1516 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001517
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001518 // First, if this window is at the current index, then all
1519 // is well.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001520 if (wallpaper == foundW) {
1521 foundI--;
1522 foundW = foundI > 0
1523 ? (WindowState)localmWindows.get(foundI-1) : null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001524 continue;
1525 }
1526
1527 // The window didn't match... the current wallpaper window,
1528 // wherever it is, is in the wrong place, so make sure it is
1529 // not in the list.
1530 int oldIndex = localmWindows.indexOf(wallpaper);
1531 if (oldIndex >= 0) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001532 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Wallpaper removing at "
1533 + oldIndex + ": " + wallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001534 localmWindows.remove(oldIndex);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001535 if (oldIndex < foundI) {
1536 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001537 }
1538 }
1539
1540 // Now stick it in.
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001541 if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
1542 "Moving wallpaper " + wallpaper
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001543 + " from " + oldIndex + " to " + foundI);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001544
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001545 localmWindows.add(foundI, wallpaper);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001546 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001547 }
1548 }
1549
1550 return changed;
1551 }
1552
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001553 void setWallpaperAnimLayerAdjustmentLocked(int adj) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001554 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Log.v(TAG,
1555 "Setting wallpaper layer adj to " + adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001556 mWallpaperAnimLayerAdjustment = adj;
1557 int curTokenIndex = mWallpaperTokens.size();
1558 while (curTokenIndex > 0) {
1559 curTokenIndex--;
1560 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1561 int curWallpaperIndex = token.windows.size();
1562 while (curWallpaperIndex > 0) {
1563 curWallpaperIndex--;
1564 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1565 wallpaper.mAnimLayer = wallpaper.mLayer + adj;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001566 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper win "
1567 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001568 }
1569 }
1570 }
1571
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001572 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1573 boolean sync) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001574 boolean changed = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001575 boolean rawChanged = false;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001576 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001577 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001578 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1579 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1580 changed = wallpaperWin.mXOffset != offset;
1581 if (changed) {
1582 if (DEBUG_WALLPAPER) Log.v(TAG, "Update wallpaper "
1583 + wallpaperWin + " x: " + offset);
1584 wallpaperWin.mXOffset = offset;
1585 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001586 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001587 wallpaperWin.mWallpaperX = wpx;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001588 wallpaperWin.mWallpaperXStep = wpxs;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001589 rawChanged = true;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001590 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001591
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001592 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001593 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001594 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1595 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
1596 if (wallpaperWin.mYOffset != offset) {
1597 if (DEBUG_WALLPAPER) Log.v(TAG, "Update wallpaper "
1598 + wallpaperWin + " y: " + offset);
1599 changed = true;
1600 wallpaperWin.mYOffset = offset;
1601 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001602 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001603 wallpaperWin.mWallpaperY = wpy;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001604 wallpaperWin.mWallpaperYStep = wpys;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001605 rawChanged = true;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001606 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001607
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001608 if (rawChanged) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001609 try {
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001610 if (DEBUG_WALLPAPER) Log.v(TAG, "Report new wp offset "
1611 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1612 + " y=" + wallpaperWin.mWallpaperY);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001613 if (sync) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001614 mWaitingOnWallpaper = wallpaperWin;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001615 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001616 wallpaperWin.mClient.dispatchWallpaperOffsets(
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001617 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
1618 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001619 if (sync) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001620 if (mWaitingOnWallpaper != null) {
1621 long start = SystemClock.uptimeMillis();
1622 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
1623 < start) {
1624 try {
1625 if (DEBUG_WALLPAPER) Log.v(TAG,
1626 "Waiting for offset complete...");
1627 mWindowMap.wait(WALLPAPER_TIMEOUT);
1628 } catch (InterruptedException e) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001629 }
Dianne Hackborn75804932009-10-20 20:15:20 -07001630 if (DEBUG_WALLPAPER) Log.v(TAG, "Offset complete!");
1631 if ((start+WALLPAPER_TIMEOUT)
1632 < SystemClock.uptimeMillis()) {
1633 Log.i(TAG, "Timeout waiting for wallpaper to offset: "
1634 + wallpaperWin);
1635 mLastWallpaperTimeoutTime = start;
1636 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001637 }
Dianne Hackborn75804932009-10-20 20:15:20 -07001638 mWaitingOnWallpaper = null;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001639 }
1640 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001641 } catch (RemoteException e) {
1642 }
1643 }
1644
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001645 return changed;
1646 }
1647
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001648 void wallpaperOffsetsComplete(IBinder window) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001649 synchronized (mWindowMap) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001650 if (mWaitingOnWallpaper != null &&
1651 mWaitingOnWallpaper.mClient.asBinder() == window) {
1652 mWaitingOnWallpaper = null;
Dianne Hackborn75804932009-10-20 20:15:20 -07001653 mWindowMap.notifyAll();
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001654 }
1655 }
1656 }
1657
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001658 boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001659 final int dw = mDisplay.getWidth();
1660 final int dh = mDisplay.getHeight();
1661
1662 boolean changed = false;
1663
1664 WindowState target = mWallpaperTarget;
1665 if (target != null) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001666 if (target.mWallpaperX >= 0) {
1667 mLastWallpaperX = target.mWallpaperX;
1668 } else if (changingTarget.mWallpaperX >= 0) {
1669 mLastWallpaperX = changingTarget.mWallpaperX;
1670 }
1671 if (target.mWallpaperY >= 0) {
1672 mLastWallpaperY = target.mWallpaperY;
1673 } else if (changingTarget.mWallpaperY >= 0) {
1674 mLastWallpaperY = changingTarget.mWallpaperY;
1675 }
1676 }
1677
1678 int curTokenIndex = mWallpaperTokens.size();
1679 while (curTokenIndex > 0) {
1680 curTokenIndex--;
1681 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1682 int curWallpaperIndex = token.windows.size();
1683 while (curWallpaperIndex > 0) {
1684 curWallpaperIndex--;
1685 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1686 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
1687 wallpaper.computeShownFrameLocked();
1688 changed = true;
1689 // We only want to be synchronous with one wallpaper.
1690 sync = false;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001691 }
1692 }
1693 }
1694
1695 return changed;
1696 }
1697
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001698 void updateWallpaperVisibilityLocked() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07001699 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001700 final int dw = mDisplay.getWidth();
1701 final int dh = mDisplay.getHeight();
1702
1703 int curTokenIndex = mWallpaperTokens.size();
1704 while (curTokenIndex > 0) {
1705 curTokenIndex--;
1706 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001707 if (token.hidden == visible) {
1708 token.hidden = !visible;
1709 // Need to do a layout to ensure the wallpaper now has the
1710 // correct size.
1711 mLayoutNeeded = true;
1712 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07001713
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001714 int curWallpaperIndex = token.windows.size();
1715 while (curWallpaperIndex > 0) {
1716 curWallpaperIndex--;
1717 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1718 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001719 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001720 }
1721
1722 if (wallpaper.mWallpaperVisible != visible) {
1723 wallpaper.mWallpaperVisible = visible;
1724 try {
1725 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Log.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07001726 "Updating visibility of wallpaper " + wallpaper
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001727 + ": " + visible);
1728 wallpaper.mClient.dispatchAppVisibility(visible);
1729 } catch (RemoteException e) {
1730 }
1731 }
1732 }
1733 }
1734 }
1735
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001736 void sendPointerToWallpaperLocked(WindowState srcWin,
1737 MotionEvent pointer, long eventTime) {
1738 int curTokenIndex = mWallpaperTokens.size();
1739 while (curTokenIndex > 0) {
1740 curTokenIndex--;
1741 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1742 int curWallpaperIndex = token.windows.size();
1743 while (curWallpaperIndex > 0) {
1744 curWallpaperIndex--;
1745 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1746 if ((wallpaper.mAttrs.flags &
1747 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
1748 continue;
1749 }
1750 try {
1751 MotionEvent ev = MotionEvent.obtainNoHistory(pointer);
1752 ev.offsetLocation(srcWin.mFrame.left-wallpaper.mFrame.left,
1753 srcWin.mFrame.top-wallpaper.mFrame.top);
1754 wallpaper.mClient.dispatchPointer(ev, eventTime, false);
1755 } catch (RemoteException e) {
1756 Log.w(TAG, "Failure sending pointer to wallpaper", e);
1757 }
1758 }
1759 }
1760 }
1761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001762 public int addWindow(Session session, IWindow client,
1763 WindowManager.LayoutParams attrs, int viewVisibility,
1764 Rect outContentInsets) {
1765 int res = mPolicy.checkAddPermission(attrs);
1766 if (res != WindowManagerImpl.ADD_OKAY) {
1767 return res;
1768 }
Romain Guy06882f82009-06-10 13:36:04 -07001769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 boolean reportNewConfig = false;
1771 WindowState attachedWindow = null;
1772 WindowState win = null;
Romain Guy06882f82009-06-10 13:36:04 -07001773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 synchronized(mWindowMap) {
1775 // Instantiating a Display requires talking with the simulator,
1776 // so don't do it until we know the system is mostly up and
1777 // running.
1778 if (mDisplay == null) {
1779 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1780 mDisplay = wm.getDefaultDisplay();
1781 mQueue.setDisplay(mDisplay);
1782 reportNewConfig = true;
1783 }
Romain Guy06882f82009-06-10 13:36:04 -07001784
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 if (mWindowMap.containsKey(client.asBinder())) {
1786 Log.w(TAG, "Window " + client + " is already added");
1787 return WindowManagerImpl.ADD_DUPLICATE_ADD;
1788 }
1789
1790 if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
Romain Guy06882f82009-06-10 13:36:04 -07001791 attachedWindow = windowForClientLocked(null, attrs.token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 if (attachedWindow == null) {
1793 Log.w(TAG, "Attempted to add window with token that is not a window: "
1794 + attrs.token + ". Aborting.");
1795 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1796 }
1797 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1798 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
1799 Log.w(TAG, "Attempted to add window with token that is a sub-window: "
1800 + attrs.token + ". Aborting.");
1801 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1802 }
1803 }
1804
1805 boolean addToken = false;
1806 WindowToken token = mTokenMap.get(attrs.token);
1807 if (token == null) {
1808 if (attrs.type >= FIRST_APPLICATION_WINDOW
1809 && attrs.type <= LAST_APPLICATION_WINDOW) {
1810 Log.w(TAG, "Attempted to add application window with unknown token "
1811 + attrs.token + ". Aborting.");
1812 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1813 }
1814 if (attrs.type == TYPE_INPUT_METHOD) {
1815 Log.w(TAG, "Attempted to add input method window with unknown token "
1816 + attrs.token + ". Aborting.");
1817 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1818 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001819 if (attrs.type == TYPE_WALLPAPER) {
1820 Log.w(TAG, "Attempted to add wallpaper window with unknown token "
1821 + attrs.token + ". Aborting.");
1822 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001824 token = new WindowToken(attrs.token, -1, false);
1825 addToken = true;
1826 } else if (attrs.type >= FIRST_APPLICATION_WINDOW
1827 && attrs.type <= LAST_APPLICATION_WINDOW) {
1828 AppWindowToken atoken = token.appWindowToken;
1829 if (atoken == null) {
1830 Log.w(TAG, "Attempted to add window with non-application token "
1831 + token + ". Aborting.");
1832 return WindowManagerImpl.ADD_NOT_APP_TOKEN;
1833 } else if (atoken.removed) {
1834 Log.w(TAG, "Attempted to add window with exiting application token "
1835 + token + ". Aborting.");
1836 return WindowManagerImpl.ADD_APP_EXITING;
1837 }
1838 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1839 // No need for this guy!
1840 if (localLOGV) Log.v(
1841 TAG, "**** NO NEED TO START: " + attrs.getTitle());
1842 return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
1843 }
1844 } else if (attrs.type == TYPE_INPUT_METHOD) {
1845 if (token.windowType != TYPE_INPUT_METHOD) {
1846 Log.w(TAG, "Attempted to add input method window with bad token "
1847 + attrs.token + ". Aborting.");
1848 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1849 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001850 } else if (attrs.type == TYPE_WALLPAPER) {
1851 if (token.windowType != TYPE_WALLPAPER) {
1852 Log.w(TAG, "Attempted to add wallpaper window with bad token "
1853 + attrs.token + ". Aborting.");
1854 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001856 }
1857
1858 win = new WindowState(session, client, token,
1859 attachedWindow, attrs, viewVisibility);
1860 if (win.mDeathRecipient == null) {
1861 // Client has apparently died, so there is no reason to
1862 // continue.
1863 Log.w(TAG, "Adding window client " + client.asBinder()
1864 + " that is dead, aborting.");
1865 return WindowManagerImpl.ADD_APP_EXITING;
1866 }
1867
1868 mPolicy.adjustWindowParamsLw(win.mAttrs);
Romain Guy06882f82009-06-10 13:36:04 -07001869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001870 res = mPolicy.prepareAddWindowLw(win, attrs);
1871 if (res != WindowManagerImpl.ADD_OKAY) {
1872 return res;
1873 }
1874
1875 // From now on, no exceptions or errors allowed!
1876
1877 res = WindowManagerImpl.ADD_OKAY;
Romain Guy06882f82009-06-10 13:36:04 -07001878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001879 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07001880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 if (addToken) {
1882 mTokenMap.put(attrs.token, token);
1883 mTokenList.add(token);
1884 }
1885 win.attach();
1886 mWindowMap.put(client.asBinder(), win);
1887
1888 if (attrs.type == TYPE_APPLICATION_STARTING &&
1889 token.appWindowToken != null) {
1890 token.appWindowToken.startingWindow = win;
1891 }
1892
1893 boolean imMayMove = true;
Romain Guy06882f82009-06-10 13:36:04 -07001894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001895 if (attrs.type == TYPE_INPUT_METHOD) {
1896 mInputMethodWindow = win;
1897 addInputMethodWindowToListLocked(win);
1898 imMayMove = false;
1899 } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
1900 mInputMethodDialogs.add(win);
1901 addWindowToListInOrderLocked(win, true);
1902 adjustInputMethodDialogsLocked();
1903 imMayMove = false;
1904 } else {
1905 addWindowToListInOrderLocked(win, true);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001906 if (attrs.type == TYPE_WALLPAPER) {
1907 mLastWallpaperTimeoutTime = 0;
1908 adjustWallpaperWindowsLocked();
1909 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001910 adjustWallpaperWindowsLocked();
1911 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 }
Romain Guy06882f82009-06-10 13:36:04 -07001913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 win.mEnterAnimationPending = true;
Romain Guy06882f82009-06-10 13:36:04 -07001915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
Romain Guy06882f82009-06-10 13:36:04 -07001917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001918 if (mInTouchMode) {
1919 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
1920 }
1921 if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
1922 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
1923 }
Romain Guy06882f82009-06-10 13:36:04 -07001924
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08001925 boolean focusChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001926 if (win.canReceiveKeys()) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08001927 if ((focusChanged=updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS))
1928 == true) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001929 imMayMove = false;
1930 }
1931 }
Romain Guy06882f82009-06-10 13:36:04 -07001932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 if (imMayMove) {
Romain Guy06882f82009-06-10 13:36:04 -07001934 moveInputMethodWindowsIfNeededLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 }
Romain Guy06882f82009-06-10 13:36:04 -07001936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001937 assignLayersLocked();
1938 // Don't do layout here, the window must call
1939 // relayout to be displayed, so we'll do it there.
Romain Guy06882f82009-06-10 13:36:04 -07001940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941 //dump();
1942
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08001943 if (focusChanged) {
1944 if (mCurrentFocus != null) {
1945 mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
1946 }
1947 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001948 if (localLOGV) Log.v(
1949 TAG, "New client " + client.asBinder()
1950 + ": window=" + win);
1951 }
1952
1953 // sendNewConfiguration() checks caller permissions so we must call it with
1954 // privilege. updateOrientationFromAppTokens() clears and resets the caller
1955 // identity anyway, so it's safe to just clear & restore around this whole
1956 // block.
1957 final long origId = Binder.clearCallingIdentity();
1958 if (reportNewConfig) {
1959 sendNewConfiguration();
1960 } else {
1961 // Update Orientation after adding a window, only if the window needs to be
1962 // displayed right away
1963 if (win.isVisibleOrAdding()) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07001964 if (updateOrientationFromAppTokensUnchecked(null, null) != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001965 sendNewConfiguration();
1966 }
1967 }
1968 }
1969 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07001970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001971 return res;
1972 }
Romain Guy06882f82009-06-10 13:36:04 -07001973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001974 public void removeWindow(Session session, IWindow client) {
1975 synchronized(mWindowMap) {
1976 WindowState win = windowForClientLocked(session, client);
1977 if (win == null) {
1978 return;
1979 }
1980 removeWindowLocked(session, win);
1981 }
1982 }
Romain Guy06882f82009-06-10 13:36:04 -07001983
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001984 public void removeWindowLocked(Session session, WindowState win) {
1985
1986 if (localLOGV || DEBUG_FOCUS) Log.v(
1987 TAG, "Remove " + win + " client="
1988 + Integer.toHexString(System.identityHashCode(
1989 win.mClient.asBinder()))
1990 + ", surface=" + win.mSurface);
1991
1992 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07001993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994 if (DEBUG_APP_TRANSITIONS) Log.v(
1995 TAG, "Remove " + win + ": mSurface=" + win.mSurface
1996 + " mExiting=" + win.mExiting
1997 + " isAnimating=" + win.isAnimating()
1998 + " app-animation="
1999 + (win.mAppToken != null ? win.mAppToken.animation : null)
2000 + " inPendingTransaction="
2001 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2002 + " mDisplayFrozen=" + mDisplayFrozen);
2003 // Visibility of the removed window. Will be used later to update orientation later on.
2004 boolean wasVisible = false;
2005 // First, see if we need to run an animation. If we do, we have
2006 // to hold off on removing the window until the animation is done.
2007 // If the display is frozen, just remove immediately, since the
2008 // animation wouldn't be seen.
2009 if (win.mSurface != null && !mDisplayFrozen) {
2010 // If we are not currently running the exit animation, we
2011 // need to see about starting one.
2012 if (wasVisible=win.isWinVisibleLw()) {
Romain Guy06882f82009-06-10 13:36:04 -07002013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002014 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2015 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2016 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2017 }
2018 // Try starting an animation.
2019 if (applyAnimationLocked(win, transit, false)) {
2020 win.mExiting = true;
2021 }
2022 }
2023 if (win.mExiting || win.isAnimating()) {
2024 // The exit animation is running... wait for it!
2025 //Log.i(TAG, "*** Running exit animation...");
2026 win.mExiting = true;
2027 win.mRemoveOnExit = true;
2028 mLayoutNeeded = true;
2029 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
2030 performLayoutAndPlaceSurfacesLocked();
2031 if (win.mAppToken != null) {
2032 win.mAppToken.updateReportedVisibilityLocked();
2033 }
2034 //dump();
2035 Binder.restoreCallingIdentity(origId);
2036 return;
2037 }
2038 }
2039
2040 removeWindowInnerLocked(session, win);
2041 // Removing a visible window will effect the computed orientation
2042 // So just update orientation if needed.
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002043 if (wasVisible && computeForcedAppOrientationLocked()
2044 != mForcedAppOrientation) {
2045 mH.sendMessage(mH.obtainMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 }
2047 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2048 Binder.restoreCallingIdentity(origId);
2049 }
Romain Guy06882f82009-06-10 13:36:04 -07002050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002051 private void removeWindowInnerLocked(Session session, WindowState win) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07002052 mKeyWaiter.finishedKey(session, win.mClient, true,
2053 KeyWaiter.RETURN_NOTHING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 mKeyWaiter.releasePendingPointerLocked(win.mSession);
2055 mKeyWaiter.releasePendingTrackballLocked(win.mSession);
Romain Guy06882f82009-06-10 13:36:04 -07002056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 win.mRemoved = true;
Romain Guy06882f82009-06-10 13:36:04 -07002058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002059 if (mInputMethodTarget == win) {
2060 moveInputMethodWindowsIfNeededLocked(false);
2061 }
Romain Guy06882f82009-06-10 13:36:04 -07002062
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002063 if (false) {
2064 RuntimeException e = new RuntimeException("here");
2065 e.fillInStackTrace();
2066 Log.w(TAG, "Removing window " + win, e);
2067 }
2068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 mPolicy.removeWindowLw(win);
2070 win.removeLocked();
2071
2072 mWindowMap.remove(win.mClient.asBinder());
2073 mWindows.remove(win);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07002074 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Final remove of window: " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075
2076 if (mInputMethodWindow == win) {
2077 mInputMethodWindow = null;
2078 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2079 mInputMethodDialogs.remove(win);
2080 }
Romain Guy06882f82009-06-10 13:36:04 -07002081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 final WindowToken token = win.mToken;
2083 final AppWindowToken atoken = win.mAppToken;
2084 token.windows.remove(win);
2085 if (atoken != null) {
2086 atoken.allAppWindows.remove(win);
2087 }
2088 if (localLOGV) Log.v(
2089 TAG, "**** Removing window " + win + ": count="
2090 + token.windows.size());
2091 if (token.windows.size() == 0) {
2092 if (!token.explicit) {
2093 mTokenMap.remove(token.token);
2094 mTokenList.remove(token);
2095 } else if (atoken != null) {
2096 atoken.firstWindowDrawn = false;
2097 }
2098 }
2099
2100 if (atoken != null) {
2101 if (atoken.startingWindow == win) {
2102 atoken.startingWindow = null;
2103 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2104 // If this is the last window and we had requested a starting
2105 // transition window, well there is no point now.
2106 atoken.startingData = null;
2107 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2108 // If this is the last window except for a starting transition
2109 // window, we need to get rid of the starting transition.
2110 if (DEBUG_STARTING_WINDOW) {
2111 Log.v(TAG, "Schedule remove starting " + token
2112 + ": no more real windows");
2113 }
2114 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
2115 mH.sendMessage(m);
2116 }
2117 }
Romain Guy06882f82009-06-10 13:36:04 -07002118
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002119 if (win.mAttrs.type == TYPE_WALLPAPER) {
2120 mLastWallpaperTimeoutTime = 0;
2121 adjustWallpaperWindowsLocked();
2122 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07002123 adjustWallpaperWindowsLocked();
2124 }
2125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 if (!mInLayout) {
2127 assignLayersLocked();
2128 mLayoutNeeded = true;
2129 performLayoutAndPlaceSurfacesLocked();
2130 if (win.mAppToken != null) {
2131 win.mAppToken.updateReportedVisibilityLocked();
2132 }
2133 }
2134 }
2135
2136 private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2137 long origId = Binder.clearCallingIdentity();
2138 try {
2139 synchronized (mWindowMap) {
2140 WindowState w = windowForClientLocked(session, client);
2141 if ((w != null) && (w.mSurface != null)) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002142 if (SHOW_TRANSACTIONS) Log.i(TAG, ">>> OPEN TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 Surface.openTransaction();
2144 try {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002145 if (SHOW_TRANSACTIONS) Log.i(
2146 TAG, " SURFACE " + w.mSurface
2147 + ": transparentRegionHint=" + region);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 w.mSurface.setTransparentRegionHint(region);
2149 } finally {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002150 if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 Surface.closeTransaction();
2152 }
2153 }
2154 }
2155 } finally {
2156 Binder.restoreCallingIdentity(origId);
2157 }
2158 }
2159
2160 void setInsetsWindow(Session session, IWindow client,
Romain Guy06882f82009-06-10 13:36:04 -07002161 int touchableInsets, Rect contentInsets,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002162 Rect visibleInsets) {
2163 long origId = Binder.clearCallingIdentity();
2164 try {
2165 synchronized (mWindowMap) {
2166 WindowState w = windowForClientLocked(session, client);
2167 if (w != null) {
2168 w.mGivenInsetsPending = false;
2169 w.mGivenContentInsets.set(contentInsets);
2170 w.mGivenVisibleInsets.set(visibleInsets);
2171 w.mTouchableInsets = touchableInsets;
2172 mLayoutNeeded = true;
2173 performLayoutAndPlaceSurfacesLocked();
2174 }
2175 }
2176 } finally {
2177 Binder.restoreCallingIdentity(origId);
2178 }
2179 }
Romain Guy06882f82009-06-10 13:36:04 -07002180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 public void getWindowDisplayFrame(Session session, IWindow client,
2182 Rect outDisplayFrame) {
2183 synchronized(mWindowMap) {
2184 WindowState win = windowForClientLocked(session, client);
2185 if (win == null) {
2186 outDisplayFrame.setEmpty();
2187 return;
2188 }
2189 outDisplayFrame.set(win.mDisplayFrame);
2190 }
2191 }
2192
Marco Nelissenbf6956b2009-11-09 15:21:13 -08002193 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2194 float xStep, float yStep) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002195 if (window.mWallpaperX != x || window.mWallpaperY != y) {
2196 window.mWallpaperX = x;
2197 window.mWallpaperY = y;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08002198 window.mWallpaperXStep = xStep;
2199 window.mWallpaperYStep = yStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07002200 if (updateWallpaperOffsetLocked(window, true)) {
2201 performLayoutAndPlaceSurfacesLocked();
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002202 }
2203 }
2204 }
2205
Dianne Hackborn75804932009-10-20 20:15:20 -07002206 void wallpaperCommandComplete(IBinder window, Bundle result) {
2207 synchronized (mWindowMap) {
2208 if (mWaitingOnWallpaper != null &&
2209 mWaitingOnWallpaper.mClient.asBinder() == window) {
2210 mWaitingOnWallpaper = null;
2211 mWindowMap.notifyAll();
2212 }
2213 }
2214 }
2215
2216 public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2217 String action, int x, int y, int z, Bundle extras, boolean sync) {
2218 if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2219 || window == mUpperWallpaperTarget) {
2220 boolean doWait = sync;
2221 int curTokenIndex = mWallpaperTokens.size();
2222 while (curTokenIndex > 0) {
2223 curTokenIndex--;
2224 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2225 int curWallpaperIndex = token.windows.size();
2226 while (curWallpaperIndex > 0) {
2227 curWallpaperIndex--;
2228 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2229 try {
2230 wallpaper.mClient.dispatchWallpaperCommand(action,
2231 x, y, z, extras, sync);
2232 // We only want to be synchronous with one wallpaper.
2233 sync = false;
2234 } catch (RemoteException e) {
2235 }
2236 }
2237 }
2238
2239 if (doWait) {
2240 // XXX Need to wait for result.
2241 }
2242 }
2243
2244 return null;
2245 }
2246
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 public int relayoutWindow(Session session, IWindow client,
2248 WindowManager.LayoutParams attrs, int requestedWidth,
2249 int requestedHeight, int viewVisibility, boolean insetsPending,
2250 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
2251 Surface outSurface) {
2252 boolean displayed = false;
2253 boolean inTouchMode;
2254 Configuration newConfig = null;
2255 long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 synchronized(mWindowMap) {
2258 WindowState win = windowForClientLocked(session, client);
2259 if (win == null) {
2260 return 0;
2261 }
2262 win.mRequestedWidth = requestedWidth;
2263 win.mRequestedHeight = requestedHeight;
2264
2265 if (attrs != null) {
2266 mPolicy.adjustWindowParamsLw(attrs);
2267 }
Romain Guy06882f82009-06-10 13:36:04 -07002268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 int attrChanges = 0;
2270 int flagChanges = 0;
2271 if (attrs != null) {
2272 flagChanges = win.mAttrs.flags ^= attrs.flags;
2273 attrChanges = win.mAttrs.copyFrom(attrs);
2274 }
2275
2276 if (localLOGV) Log.v(
2277 TAG, "Relayout given client " + client.asBinder()
2278 + " (" + win.mAttrs.getTitle() + ")");
2279
2280
2281 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2282 win.mAlpha = attrs.alpha;
2283 }
2284
2285 final boolean scaledWindow =
2286 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2287
2288 if (scaledWindow) {
2289 // requested{Width|Height} Surface's physical size
2290 // attrs.{width|height} Size on screen
2291 win.mHScale = (attrs.width != requestedWidth) ?
2292 (attrs.width / (float)requestedWidth) : 1.0f;
2293 win.mVScale = (attrs.height != requestedHeight) ?
2294 (attrs.height / (float)requestedHeight) : 1.0f;
2295 }
2296
2297 boolean imMayMove = (flagChanges&(
2298 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
2299 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07002300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002301 boolean focusMayChange = win.mViewVisibility != viewVisibility
2302 || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
2303 || (!win.mRelayoutCalled);
Romain Guy06882f82009-06-10 13:36:04 -07002304
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002305 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2306 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
2307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002308 win.mRelayoutCalled = true;
2309 final int oldVisibility = win.mViewVisibility;
2310 win.mViewVisibility = viewVisibility;
2311 if (viewVisibility == View.VISIBLE &&
2312 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2313 displayed = !win.isVisibleLw();
2314 if (win.mExiting) {
2315 win.mExiting = false;
2316 win.mAnimation = null;
2317 }
2318 if (win.mDestroying) {
2319 win.mDestroying = false;
2320 mDestroySurface.remove(win);
2321 }
2322 if (oldVisibility == View.GONE) {
2323 win.mEnterAnimationPending = true;
2324 }
2325 if (displayed && win.mSurface != null && !win.mDrawPending
2326 && !win.mCommitDrawPending && !mDisplayFrozen) {
2327 applyEnterAnimationLocked(win);
2328 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07002329 if (displayed && (win.mAttrs.flags
2330 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2331 win.mTurnOnScreen = true;
2332 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002333 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2334 // To change the format, we need to re-build the surface.
2335 win.destroySurfaceLocked();
2336 displayed = true;
2337 }
2338 try {
2339 Surface surface = win.createSurfaceLocked();
2340 if (surface != null) {
2341 outSurface.copyFrom(surface);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002342 win.mReportDestroySurface = false;
2343 win.mSurfacePendingDestroy = false;
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002344 if (SHOW_TRANSACTIONS) Log.i(TAG,
2345 " OUT SURFACE " + outSurface + ": copied");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002346 } else {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002347 // For some reason there isn't a surface. Clear the
2348 // caller's object so they see the same state.
2349 outSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002350 }
2351 } catch (Exception e) {
2352 Log.w(TAG, "Exception thrown when creating surface for client "
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002353 + client + " (" + win.mAttrs.getTitle() + ")",
2354 e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002355 Binder.restoreCallingIdentity(origId);
2356 return 0;
2357 }
2358 if (displayed) {
2359 focusMayChange = true;
2360 }
2361 if (win.mAttrs.type == TYPE_INPUT_METHOD
2362 && mInputMethodWindow == null) {
2363 mInputMethodWindow = win;
2364 imMayMove = true;
2365 }
2366 } else {
2367 win.mEnterAnimationPending = false;
2368 if (win.mSurface != null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002369 if (DEBUG_VISIBILITY) Log.i(TAG, "Relayout invis " + win
2370 + ": mExiting=" + win.mExiting
2371 + " mSurfacePendingDestroy=" + win.mSurfacePendingDestroy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002372 // If we are not currently running the exit animation, we
2373 // need to see about starting one.
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002374 if (!win.mExiting || win.mSurfacePendingDestroy) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 // Try starting an animation; if there isn't one, we
2376 // can destroy the surface right away.
2377 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2378 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2379 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2380 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002381 if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002382 applyAnimationLocked(win, transit, false)) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002383 focusMayChange = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002384 win.mExiting = true;
2385 mKeyWaiter.finishedKey(session, client, true,
2386 KeyWaiter.RETURN_NOTHING);
2387 } else if (win.isAnimating()) {
2388 // Currently in a hide animation... turn this into
2389 // an exit.
2390 win.mExiting = true;
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07002391 } else if (win == mWallpaperTarget) {
2392 // If the wallpaper is currently behind this
2393 // window, we need to change both of them inside
2394 // of a transaction to avoid artifacts.
2395 win.mExiting = true;
2396 win.mAnimating = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 } else {
2398 if (mInputMethodWindow == win) {
2399 mInputMethodWindow = null;
2400 }
2401 win.destroySurfaceLocked();
2402 }
2403 }
2404 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002405
2406 if (win.mSurface == null || (win.getAttrs().flags
2407 & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0
2408 || win.mSurfacePendingDestroy) {
2409 // We are being called from a local process, which
2410 // means outSurface holds its current surface. Ensure the
2411 // surface object is cleared, but we don't want it actually
2412 // destroyed at this point.
2413 win.mSurfacePendingDestroy = false;
2414 outSurface.release();
2415 if (DEBUG_VISIBILITY) Log.i(TAG, "Releasing surface in: " + win);
2416 } else if (win.mSurface != null) {
2417 if (DEBUG_VISIBILITY) Log.i(TAG,
2418 "Keeping surface, will report destroy: " + win);
2419 win.mReportDestroySurface = true;
2420 outSurface.copyFrom(win.mSurface);
2421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002422 }
2423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002424 if (focusMayChange) {
2425 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2426 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002427 imMayMove = false;
2428 }
2429 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2430 }
Romain Guy06882f82009-06-10 13:36:04 -07002431
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002432 // updateFocusedWindowLocked() already assigned layers so we only need to
2433 // reassign them at this point if the IM window state gets shuffled
2434 boolean assignLayers = false;
Romain Guy06882f82009-06-10 13:36:04 -07002435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 if (imMayMove) {
2437 if (moveInputMethodWindowsIfNeededLocked(false)) {
2438 assignLayers = true;
2439 }
2440 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002441 if (wallpaperMayMove) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002442 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002443 assignLayers = true;
2444 }
2445 }
Romain Guy06882f82009-06-10 13:36:04 -07002446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002447 mLayoutNeeded = true;
2448 win.mGivenInsetsPending = insetsPending;
2449 if (assignLayers) {
2450 assignLayersLocked();
2451 }
The Android Open Source Project10592532009-03-18 17:39:46 -07002452 newConfig = updateOrientationFromAppTokensLocked(null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002453 performLayoutAndPlaceSurfacesLocked();
Dianne Hackborn284ac932009-08-28 10:34:25 -07002454 if (displayed && win.mIsWallpaper) {
2455 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002456 mDisplay.getHeight(), false);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002457 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002458 if (win.mAppToken != null) {
2459 win.mAppToken.updateReportedVisibilityLocked();
2460 }
2461 outFrame.set(win.mFrame);
2462 outContentInsets.set(win.mContentInsets);
2463 outVisibleInsets.set(win.mVisibleInsets);
2464 if (localLOGV) Log.v(
2465 TAG, "Relayout given client " + client.asBinder()
Romain Guy06882f82009-06-10 13:36:04 -07002466 + ", requestedWidth=" + requestedWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 + ", requestedHeight=" + requestedHeight
2468 + ", viewVisibility=" + viewVisibility
2469 + "\nRelayout returning frame=" + outFrame
2470 + ", surface=" + outSurface);
2471
2472 if (localLOGV || DEBUG_FOCUS) Log.v(
2473 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2474
2475 inTouchMode = mInTouchMode;
2476 }
2477
2478 if (newConfig != null) {
2479 sendNewConfiguration();
2480 }
Romain Guy06882f82009-06-10 13:36:04 -07002481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002482 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07002483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002484 return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
2485 | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
2486 }
2487
2488 public void finishDrawingWindow(Session session, IWindow client) {
2489 final long origId = Binder.clearCallingIdentity();
2490 synchronized(mWindowMap) {
2491 WindowState win = windowForClientLocked(session, client);
2492 if (win != null && win.finishDrawingLocked()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07002493 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2494 adjustWallpaperWindowsLocked();
2495 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496 mLayoutNeeded = true;
2497 performLayoutAndPlaceSurfacesLocked();
2498 }
2499 }
2500 Binder.restoreCallingIdentity(origId);
2501 }
2502
2503 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
2504 if (DEBUG_ANIM) Log.v(TAG, "Loading animations: params package="
2505 + (lp != null ? lp.packageName : null)
2506 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
2507 if (lp != null && lp.windowAnimations != 0) {
2508 // If this is a system resource, don't try to load it from the
2509 // application resources. It is nice to avoid loading application
2510 // resources if we can.
2511 String packageName = lp.packageName != null ? lp.packageName : "android";
2512 int resId = lp.windowAnimations;
2513 if ((resId&0xFF000000) == 0x01000000) {
2514 packageName = "android";
2515 }
2516 if (DEBUG_ANIM) Log.v(TAG, "Loading animations: picked package="
2517 + packageName);
2518 return AttributeCache.instance().get(packageName, resId,
2519 com.android.internal.R.styleable.WindowAnimation);
2520 }
2521 return null;
2522 }
Romain Guy06882f82009-06-10 13:36:04 -07002523
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002524 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
2525 if (DEBUG_ANIM) Log.v(TAG, "Loading animations: params package="
2526 + packageName + " resId=0x" + Integer.toHexString(resId));
2527 if (packageName != null) {
2528 if ((resId&0xFF000000) == 0x01000000) {
2529 packageName = "android";
2530 }
2531 if (DEBUG_ANIM) Log.v(TAG, "Loading animations: picked package="
2532 + packageName);
2533 return AttributeCache.instance().get(packageName, resId,
2534 com.android.internal.R.styleable.WindowAnimation);
2535 }
2536 return null;
2537 }
2538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002539 private void applyEnterAnimationLocked(WindowState win) {
2540 int transit = WindowManagerPolicy.TRANSIT_SHOW;
2541 if (win.mEnterAnimationPending) {
2542 win.mEnterAnimationPending = false;
2543 transit = WindowManagerPolicy.TRANSIT_ENTER;
2544 }
2545
2546 applyAnimationLocked(win, transit, true);
2547 }
2548
2549 private boolean applyAnimationLocked(WindowState win,
2550 int transit, boolean isEntrance) {
2551 if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
2552 // If we are trying to apply an animation, but already running
2553 // an animation of the same type, then just leave that one alone.
2554 return true;
2555 }
Romain Guy06882f82009-06-10 13:36:04 -07002556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 // Only apply an animation if the display isn't frozen. If it is
2558 // frozen, there is no reason to animate and it can cause strange
2559 // artifacts when we unfreeze the display if some different animation
2560 // is running.
2561 if (!mDisplayFrozen) {
2562 int anim = mPolicy.selectAnimationLw(win, transit);
2563 int attr = -1;
2564 Animation a = null;
2565 if (anim != 0) {
2566 a = AnimationUtils.loadAnimation(mContext, anim);
2567 } else {
2568 switch (transit) {
2569 case WindowManagerPolicy.TRANSIT_ENTER:
2570 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
2571 break;
2572 case WindowManagerPolicy.TRANSIT_EXIT:
2573 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
2574 break;
2575 case WindowManagerPolicy.TRANSIT_SHOW:
2576 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
2577 break;
2578 case WindowManagerPolicy.TRANSIT_HIDE:
2579 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
2580 break;
2581 }
2582 if (attr >= 0) {
2583 a = loadAnimation(win.mAttrs, attr);
2584 }
2585 }
2586 if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: win=" + win
2587 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
2588 + " mAnimation=" + win.mAnimation
2589 + " isEntrance=" + isEntrance);
2590 if (a != null) {
2591 if (DEBUG_ANIM) {
2592 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07002593 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002594 Log.v(TAG, "Loaded animation " + a + " for " + win, e);
2595 }
2596 win.setAnimation(a);
2597 win.mAnimationIsEntrance = isEntrance;
2598 }
2599 } else {
2600 win.clearAnimation();
2601 }
2602
2603 return win.mAnimation != null;
2604 }
2605
2606 private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
2607 int anim = 0;
2608 Context context = mContext;
2609 if (animAttr >= 0) {
2610 AttributeCache.Entry ent = getCachedAnimations(lp);
2611 if (ent != null) {
2612 context = ent.context;
2613 anim = ent.array.getResourceId(animAttr, 0);
2614 }
2615 }
2616 if (anim != 0) {
2617 return AnimationUtils.loadAnimation(context, anim);
2618 }
2619 return null;
2620 }
Romain Guy06882f82009-06-10 13:36:04 -07002621
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002622 private Animation loadAnimation(String packageName, int resId) {
2623 int anim = 0;
2624 Context context = mContext;
2625 if (resId >= 0) {
2626 AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
2627 if (ent != null) {
2628 context = ent.context;
2629 anim = resId;
2630 }
2631 }
2632 if (anim != 0) {
2633 return AnimationUtils.loadAnimation(context, anim);
2634 }
2635 return null;
2636 }
2637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002638 private boolean applyAnimationLocked(AppWindowToken wtoken,
2639 WindowManager.LayoutParams lp, int transit, boolean enter) {
2640 // Only apply an animation if the display isn't frozen. If it is
2641 // frozen, there is no reason to animate and it can cause strange
2642 // artifacts when we unfreeze the display if some different animation
2643 // is running.
2644 if (!mDisplayFrozen) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002645 Animation a;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07002646 if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002647 a = new FadeInOutAnimation(enter);
2648 if (DEBUG_ANIM) Log.v(TAG,
2649 "applying FadeInOutAnimation for a window in compatibility mode");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002650 } else if (mNextAppTransitionPackage != null) {
2651 a = loadAnimation(mNextAppTransitionPackage, enter ?
2652 mNextAppTransitionEnter : mNextAppTransitionExit);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002653 } else {
2654 int animAttr = 0;
2655 switch (transit) {
2656 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
2657 animAttr = enter
2658 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
2659 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
2660 break;
2661 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
2662 animAttr = enter
2663 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
2664 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
2665 break;
2666 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
2667 animAttr = enter
2668 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
2669 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
2670 break;
2671 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
2672 animAttr = enter
2673 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
2674 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
2675 break;
2676 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
2677 animAttr = enter
2678 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
2679 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
2680 break;
2681 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
2682 animAttr = enter
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07002683 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002684 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
2685 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002686 case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002687 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002688 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation
2689 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002690 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002691 case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002692 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002693 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation
2694 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
2695 break;
2696 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN:
2697 animAttr = enter
2698 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation
2699 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
2700 break;
2701 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE:
2702 animAttr = enter
2703 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation
2704 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002705 break;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002706 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002707 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002708 if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: wtoken=" + wtoken
2709 + " anim=" + a
2710 + " animAttr=0x" + Integer.toHexString(animAttr)
2711 + " transit=" + transit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 if (a != null) {
2714 if (DEBUG_ANIM) {
2715 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07002716 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002717 Log.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
2718 }
2719 wtoken.setAnimation(a);
2720 }
2721 } else {
2722 wtoken.clearAnimation();
2723 }
2724
2725 return wtoken.animation != null;
2726 }
2727
2728 // -------------------------------------------------------------
2729 // Application Window Tokens
2730 // -------------------------------------------------------------
2731
2732 public void validateAppTokens(List tokens) {
2733 int v = tokens.size()-1;
2734 int m = mAppTokens.size()-1;
2735 while (v >= 0 && m >= 0) {
2736 AppWindowToken wtoken = mAppTokens.get(m);
2737 if (wtoken.removed) {
2738 m--;
2739 continue;
2740 }
2741 if (tokens.get(v) != wtoken.token) {
2742 Log.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
2743 + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
2744 }
2745 v--;
2746 m--;
2747 }
2748 while (v >= 0) {
2749 Log.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
2750 v--;
2751 }
2752 while (m >= 0) {
2753 AppWindowToken wtoken = mAppTokens.get(m);
2754 if (!wtoken.removed) {
2755 Log.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
2756 }
2757 m--;
2758 }
2759 }
2760
2761 boolean checkCallingPermission(String permission, String func) {
2762 // Quick check: if the calling permission is me, it's all okay.
2763 if (Binder.getCallingPid() == Process.myPid()) {
2764 return true;
2765 }
Romain Guy06882f82009-06-10 13:36:04 -07002766
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002767 if (mContext.checkCallingPermission(permission)
2768 == PackageManager.PERMISSION_GRANTED) {
2769 return true;
2770 }
2771 String msg = "Permission Denial: " + func + " from pid="
2772 + Binder.getCallingPid()
2773 + ", uid=" + Binder.getCallingUid()
2774 + " requires " + permission;
2775 Log.w(TAG, msg);
2776 return false;
2777 }
Romain Guy06882f82009-06-10 13:36:04 -07002778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002779 AppWindowToken findAppWindowToken(IBinder token) {
2780 WindowToken wtoken = mTokenMap.get(token);
2781 if (wtoken == null) {
2782 return null;
2783 }
2784 return wtoken.appWindowToken;
2785 }
Romain Guy06882f82009-06-10 13:36:04 -07002786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002787 public void addWindowToken(IBinder token, int type) {
2788 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2789 "addWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002790 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002791 }
Romain Guy06882f82009-06-10 13:36:04 -07002792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002793 synchronized(mWindowMap) {
2794 WindowToken wtoken = mTokenMap.get(token);
2795 if (wtoken != null) {
2796 Log.w(TAG, "Attempted to add existing input method token: " + token);
2797 return;
2798 }
2799 wtoken = new WindowToken(token, type, true);
2800 mTokenMap.put(token, wtoken);
2801 mTokenList.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002802 if (type == TYPE_WALLPAPER) {
2803 mWallpaperTokens.add(wtoken);
2804 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002805 }
2806 }
Romain Guy06882f82009-06-10 13:36:04 -07002807
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002808 public void removeWindowToken(IBinder token) {
2809 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2810 "removeWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002811 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002812 }
2813
2814 final long origId = Binder.clearCallingIdentity();
2815 synchronized(mWindowMap) {
2816 WindowToken wtoken = mTokenMap.remove(token);
2817 mTokenList.remove(wtoken);
2818 if (wtoken != null) {
2819 boolean delayed = false;
2820 if (!wtoken.hidden) {
2821 wtoken.hidden = true;
Romain Guy06882f82009-06-10 13:36:04 -07002822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002823 final int N = wtoken.windows.size();
2824 boolean changed = false;
Romain Guy06882f82009-06-10 13:36:04 -07002825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826 for (int i=0; i<N; i++) {
2827 WindowState win = wtoken.windows.get(i);
2828
2829 if (win.isAnimating()) {
2830 delayed = true;
2831 }
Romain Guy06882f82009-06-10 13:36:04 -07002832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002833 if (win.isVisibleNow()) {
2834 applyAnimationLocked(win,
2835 WindowManagerPolicy.TRANSIT_EXIT, false);
2836 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
2837 KeyWaiter.RETURN_NOTHING);
2838 changed = true;
2839 }
2840 }
2841
2842 if (changed) {
2843 mLayoutNeeded = true;
2844 performLayoutAndPlaceSurfacesLocked();
2845 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2846 }
Romain Guy06882f82009-06-10 13:36:04 -07002847
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002848 if (delayed) {
2849 mExitingTokens.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002850 } else if (wtoken.windowType == TYPE_WALLPAPER) {
2851 mWallpaperTokens.remove(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002852 }
2853 }
Romain Guy06882f82009-06-10 13:36:04 -07002854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002855 } else {
2856 Log.w(TAG, "Attempted to remove non-existing token: " + token);
2857 }
2858 }
2859 Binder.restoreCallingIdentity(origId);
2860 }
2861
2862 public void addAppToken(int addPos, IApplicationToken token,
2863 int groupId, int requestedOrientation, boolean fullscreen) {
2864 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2865 "addAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002866 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002867 }
Romain Guy06882f82009-06-10 13:36:04 -07002868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002869 synchronized(mWindowMap) {
2870 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
2871 if (wtoken != null) {
2872 Log.w(TAG, "Attempted to add existing app token: " + token);
2873 return;
2874 }
2875 wtoken = new AppWindowToken(token);
2876 wtoken.groupId = groupId;
2877 wtoken.appFullscreen = fullscreen;
2878 wtoken.requestedOrientation = requestedOrientation;
2879 mAppTokens.add(addPos, wtoken);
Dave Bortcfe65242009-04-09 14:51:04 -07002880 if (localLOGV) Log.v(TAG, "Adding new app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002881 mTokenMap.put(token.asBinder(), wtoken);
2882 mTokenList.add(wtoken);
Romain Guy06882f82009-06-10 13:36:04 -07002883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002884 // Application tokens start out hidden.
2885 wtoken.hidden = true;
2886 wtoken.hiddenRequested = true;
Romain Guy06882f82009-06-10 13:36:04 -07002887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 //dump();
2889 }
2890 }
Romain Guy06882f82009-06-10 13:36:04 -07002891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 public void setAppGroupId(IBinder token, int groupId) {
2893 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2894 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002895 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002896 }
2897
2898 synchronized(mWindowMap) {
2899 AppWindowToken wtoken = findAppWindowToken(token);
2900 if (wtoken == null) {
2901 Log.w(TAG, "Attempted to set group id of non-existing app token: " + token);
2902 return;
2903 }
2904 wtoken.groupId = groupId;
2905 }
2906 }
Romain Guy06882f82009-06-10 13:36:04 -07002907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002908 public int getOrientationFromWindowsLocked() {
2909 int pos = mWindows.size() - 1;
2910 while (pos >= 0) {
2911 WindowState wtoken = (WindowState) mWindows.get(pos);
2912 pos--;
2913 if (wtoken.mAppToken != null) {
2914 // We hit an application window. so the orientation will be determined by the
2915 // app window. No point in continuing further.
2916 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2917 }
2918 if (!wtoken.isVisibleLw()) {
2919 continue;
2920 }
2921 int req = wtoken.mAttrs.screenOrientation;
2922 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
2923 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
2924 continue;
2925 } else {
2926 return req;
2927 }
2928 }
2929 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2930 }
Romain Guy06882f82009-06-10 13:36:04 -07002931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 public int getOrientationFromAppTokensLocked() {
2933 int pos = mAppTokens.size() - 1;
2934 int curGroup = 0;
2935 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Owen Lin3413b892009-05-01 17:12:32 -07002936 boolean findingBehind = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937 boolean haveGroup = false;
The Android Open Source Project4df24232009-03-05 14:34:35 -08002938 boolean lastFullscreen = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 while (pos >= 0) {
2940 AppWindowToken wtoken = mAppTokens.get(pos);
2941 pos--;
Owen Lin3413b892009-05-01 17:12:32 -07002942 // if we're about to tear down this window and not seek for
2943 // the behind activity, don't use it for orientation
2944 if (!findingBehind
2945 && (!wtoken.hidden && wtoken.hiddenRequested)) {
The Android Open Source Project10592532009-03-18 17:39:46 -07002946 continue;
2947 }
2948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 if (!haveGroup) {
2950 // We ignore any hidden applications on the top.
2951 if (wtoken.hiddenRequested || wtoken.willBeHidden) {
2952 continue;
2953 }
2954 haveGroup = true;
2955 curGroup = wtoken.groupId;
2956 lastOrientation = wtoken.requestedOrientation;
2957 } else if (curGroup != wtoken.groupId) {
2958 // If we have hit a new application group, and the bottom
2959 // of the previous group didn't explicitly say to use
The Android Open Source Project4df24232009-03-05 14:34:35 -08002960 // the orientation behind it, and the last app was
2961 // full screen, then we'll stick with the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002962 // user's orientation.
The Android Open Source Project4df24232009-03-05 14:34:35 -08002963 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
2964 && lastFullscreen) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002965 return lastOrientation;
2966 }
2967 }
2968 int or = wtoken.requestedOrientation;
Owen Lin3413b892009-05-01 17:12:32 -07002969 // If this application is fullscreen, and didn't explicitly say
2970 // to use the orientation behind it, then just take whatever
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002971 // orientation it has and ignores whatever is under it.
The Android Open Source Project4df24232009-03-05 14:34:35 -08002972 lastFullscreen = wtoken.appFullscreen;
Romain Guy06882f82009-06-10 13:36:04 -07002973 if (lastFullscreen
Owen Lin3413b892009-05-01 17:12:32 -07002974 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 return or;
2976 }
2977 // If this application has requested an explicit orientation,
2978 // then use it.
2979 if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
2980 or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
2981 or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
2982 or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
2983 or == ActivityInfo.SCREEN_ORIENTATION_USER) {
2984 return or;
2985 }
Owen Lin3413b892009-05-01 17:12:32 -07002986 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 }
2988 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
2989 }
Romain Guy06882f82009-06-10 13:36:04 -07002990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991 public Configuration updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07002992 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002993 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2994 "updateOrientationFromAppTokens()")) {
2995 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
2996 }
2997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002998 Configuration config;
2999 long ident = Binder.clearCallingIdentity();
Dianne Hackborncfaef692009-06-15 14:24:44 -07003000 config = updateOrientationFromAppTokensUnchecked(currentConfig,
3001 freezeThisOneIfNeeded);
3002 Binder.restoreCallingIdentity(ident);
3003 return config;
3004 }
3005
3006 Configuration updateOrientationFromAppTokensUnchecked(
3007 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
3008 Configuration config;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003009 synchronized(mWindowMap) {
The Android Open Source Project10592532009-03-18 17:39:46 -07003010 config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded);
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003011 if (config != null) {
3012 mLayoutNeeded = true;
3013 performLayoutAndPlaceSurfacesLocked();
3014 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003016 return config;
3017 }
Romain Guy06882f82009-06-10 13:36:04 -07003018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 /*
3020 * The orientation is computed from non-application windows first. If none of
3021 * the non-application windows specify orientation, the orientation is computed from
Romain Guy06882f82009-06-10 13:36:04 -07003022 * application tokens.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003023 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3024 * android.os.IBinder)
3025 */
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003026 Configuration updateOrientationFromAppTokensLocked(
The Android Open Source Project10592532009-03-18 17:39:46 -07003027 Configuration appConfig, IBinder freezeThisOneIfNeeded) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003028 boolean changed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003029 long ident = Binder.clearCallingIdentity();
3030 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003031 int req = computeForcedAppOrientationLocked();
Romain Guy06882f82009-06-10 13:36:04 -07003032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 if (req != mForcedAppOrientation) {
3034 changed = true;
3035 mForcedAppOrientation = req;
3036 //send a message to Policy indicating orientation change to take
3037 //action like disabling/enabling sensors etc.,
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003038 mPolicy.setCurrentOrientationLw(req);
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 if (changed) {
3042 changed = setRotationUncheckedLocked(
Dianne Hackborn321ae682009-03-27 16:16:03 -07003043 WindowManagerPolicy.USE_LAST_ROTATION,
3044 mLastRotationFlags & (~Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003045 if (changed) {
3046 if (freezeThisOneIfNeeded != null) {
3047 AppWindowToken wtoken = findAppWindowToken(
3048 freezeThisOneIfNeeded);
3049 if (wtoken != null) {
3050 startAppFreezingScreenLocked(wtoken,
3051 ActivityInfo.CONFIG_ORIENTATION);
3052 }
3053 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07003054 return computeNewConfigurationLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 }
3056 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003057
3058 // No obvious action we need to take, but if our current
3059 // state mismatches the activity maanager's, update it
3060 if (appConfig != null) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07003061 mTempConfiguration.setToDefaults();
3062 if (computeNewConfigurationLocked(mTempConfiguration)) {
3063 if (appConfig.diff(mTempConfiguration) != 0) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07003064 return new Configuration(mTempConfiguration);
3065 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003066 }
3067 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003068 } finally {
3069 Binder.restoreCallingIdentity(ident);
3070 }
Romain Guy06882f82009-06-10 13:36:04 -07003071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003072 return null;
3073 }
Romain Guy06882f82009-06-10 13:36:04 -07003074
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003075 int computeForcedAppOrientationLocked() {
3076 int req = getOrientationFromWindowsLocked();
3077 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3078 req = getOrientationFromAppTokensLocked();
3079 }
3080 return req;
3081 }
Romain Guy06882f82009-06-10 13:36:04 -07003082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003083 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3084 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3085 "setAppOrientation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003086 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003087 }
Romain Guy06882f82009-06-10 13:36:04 -07003088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003089 synchronized(mWindowMap) {
3090 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3091 if (wtoken == null) {
3092 Log.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
3093 return;
3094 }
Romain Guy06882f82009-06-10 13:36:04 -07003095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003096 wtoken.requestedOrientation = requestedOrientation;
3097 }
3098 }
Romain Guy06882f82009-06-10 13:36:04 -07003099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003100 public int getAppOrientation(IApplicationToken token) {
3101 synchronized(mWindowMap) {
3102 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3103 if (wtoken == null) {
3104 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3105 }
Romain Guy06882f82009-06-10 13:36:04 -07003106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003107 return wtoken.requestedOrientation;
3108 }
3109 }
Romain Guy06882f82009-06-10 13:36:04 -07003110
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3112 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3113 "setFocusedApp()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003114 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003115 }
3116
3117 synchronized(mWindowMap) {
3118 boolean changed = false;
3119 if (token == null) {
3120 if (DEBUG_FOCUS) Log.v(TAG, "Clearing focused app, was " + mFocusedApp);
3121 changed = mFocusedApp != null;
3122 mFocusedApp = null;
3123 mKeyWaiter.tickle();
3124 } else {
3125 AppWindowToken newFocus = findAppWindowToken(token);
3126 if (newFocus == null) {
3127 Log.w(TAG, "Attempted to set focus to non-existing app token: " + token);
3128 return;
3129 }
3130 changed = mFocusedApp != newFocus;
3131 mFocusedApp = newFocus;
3132 if (DEBUG_FOCUS) Log.v(TAG, "Set focused app to: " + mFocusedApp);
3133 mKeyWaiter.tickle();
3134 }
3135
3136 if (moveFocusNow && changed) {
3137 final long origId = Binder.clearCallingIdentity();
3138 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3139 Binder.restoreCallingIdentity(origId);
3140 }
3141 }
3142 }
3143
3144 public void prepareAppTransition(int transit) {
3145 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3146 "prepareAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003147 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 }
Romain Guy06882f82009-06-10 13:36:04 -07003149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003150 synchronized(mWindowMap) {
3151 if (DEBUG_APP_TRANSITIONS) Log.v(
3152 TAG, "Prepare app transition: transit=" + transit
3153 + " mNextAppTransition=" + mNextAppTransition);
3154 if (!mDisplayFrozen) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003155 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
3156 || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003157 mNextAppTransition = transit;
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07003158 } else if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
3159 && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) {
3160 // Opening a new task always supersedes a close for the anim.
3161 mNextAppTransition = transit;
3162 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
3163 && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) {
3164 // Opening a new activity always supersedes a close for the anim.
3165 mNextAppTransition = transit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003166 }
3167 mAppTransitionReady = false;
3168 mAppTransitionTimeout = false;
3169 mStartingIconInTransition = false;
3170 mSkipAppTransitionAnimation = false;
3171 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3172 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT),
3173 5000);
3174 }
3175 }
3176 }
3177
3178 public int getPendingAppTransition() {
3179 return mNextAppTransition;
3180 }
Romain Guy06882f82009-06-10 13:36:04 -07003181
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003182 public void overridePendingAppTransition(String packageName,
3183 int enterAnim, int exitAnim) {
Dianne Hackborn8b571a82009-09-25 16:09:43 -07003184 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003185 mNextAppTransitionPackage = packageName;
3186 mNextAppTransitionEnter = enterAnim;
3187 mNextAppTransitionExit = exitAnim;
3188 }
3189 }
3190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003191 public void executeAppTransition() {
3192 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3193 "executeAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003194 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003195 }
Romain Guy06882f82009-06-10 13:36:04 -07003196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003197 synchronized(mWindowMap) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003198 if (DEBUG_APP_TRANSITIONS) {
3199 RuntimeException e = new RuntimeException("here");
3200 e.fillInStackTrace();
3201 Log.w(TAG, "Execute app transition: mNextAppTransition="
3202 + mNextAppTransition, e);
3203 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003204 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003205 mAppTransitionReady = true;
3206 final long origId = Binder.clearCallingIdentity();
3207 performLayoutAndPlaceSurfacesLocked();
3208 Binder.restoreCallingIdentity(origId);
3209 }
3210 }
3211 }
3212
3213 public void setAppStartingWindow(IBinder token, String pkg,
3214 int theme, CharSequence nonLocalizedLabel, int labelRes, int icon,
3215 IBinder transferFrom, boolean createIfNeeded) {
3216 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3217 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003218 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003219 }
3220
3221 synchronized(mWindowMap) {
3222 if (DEBUG_STARTING_WINDOW) Log.v(
3223 TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
3224 + " transferFrom=" + transferFrom);
Romain Guy06882f82009-06-10 13:36:04 -07003225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003226 AppWindowToken wtoken = findAppWindowToken(token);
3227 if (wtoken == null) {
3228 Log.w(TAG, "Attempted to set icon of non-existing app token: " + token);
3229 return;
3230 }
3231
3232 // If the display is frozen, we won't do anything until the
3233 // actual window is displayed so there is no reason to put in
3234 // the starting window.
3235 if (mDisplayFrozen) {
3236 return;
3237 }
Romain Guy06882f82009-06-10 13:36:04 -07003238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003239 if (wtoken.startingData != null) {
3240 return;
3241 }
Romain Guy06882f82009-06-10 13:36:04 -07003242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003243 if (transferFrom != null) {
3244 AppWindowToken ttoken = findAppWindowToken(transferFrom);
3245 if (ttoken != null) {
3246 WindowState startingWindow = ttoken.startingWindow;
3247 if (startingWindow != null) {
3248 if (mStartingIconInTransition) {
3249 // In this case, the starting icon has already
3250 // been displayed, so start letting windows get
3251 // shown immediately without any more transitions.
3252 mSkipAppTransitionAnimation = true;
3253 }
3254 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
3255 "Moving existing starting from " + ttoken
3256 + " to " + wtoken);
3257 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07003258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003259 // Transfer the starting window over to the new
3260 // token.
3261 wtoken.startingData = ttoken.startingData;
3262 wtoken.startingView = ttoken.startingView;
3263 wtoken.startingWindow = startingWindow;
3264 ttoken.startingData = null;
3265 ttoken.startingView = null;
3266 ttoken.startingWindow = null;
3267 ttoken.startingMoved = true;
3268 startingWindow.mToken = wtoken;
Dianne Hackbornef49c572009-03-24 19:27:32 -07003269 startingWindow.mRootToken = wtoken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003270 startingWindow.mAppToken = wtoken;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003271 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
3272 "Removing starting window: " + startingWindow);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273 mWindows.remove(startingWindow);
3274 ttoken.windows.remove(startingWindow);
3275 ttoken.allAppWindows.remove(startingWindow);
3276 addWindowToListInOrderLocked(startingWindow, true);
Romain Guy06882f82009-06-10 13:36:04 -07003277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003278 // Propagate other interesting state between the
3279 // tokens. If the old token is displayed, we should
3280 // immediately force the new one to be displayed. If
3281 // it is animating, we need to move that animation to
3282 // the new one.
3283 if (ttoken.allDrawn) {
3284 wtoken.allDrawn = true;
3285 }
3286 if (ttoken.firstWindowDrawn) {
3287 wtoken.firstWindowDrawn = true;
3288 }
3289 if (!ttoken.hidden) {
3290 wtoken.hidden = false;
3291 wtoken.hiddenRequested = false;
3292 wtoken.willBeHidden = false;
3293 }
3294 if (wtoken.clientHidden != ttoken.clientHidden) {
3295 wtoken.clientHidden = ttoken.clientHidden;
3296 wtoken.sendAppVisibilityToClients();
3297 }
3298 if (ttoken.animation != null) {
3299 wtoken.animation = ttoken.animation;
3300 wtoken.animating = ttoken.animating;
3301 wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
3302 ttoken.animation = null;
3303 ttoken.animLayerAdjustment = 0;
3304 wtoken.updateLayers();
3305 ttoken.updateLayers();
3306 }
Romain Guy06882f82009-06-10 13:36:04 -07003307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003308 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 mLayoutNeeded = true;
3310 performLayoutAndPlaceSurfacesLocked();
3311 Binder.restoreCallingIdentity(origId);
3312 return;
3313 } else if (ttoken.startingData != null) {
3314 // The previous app was getting ready to show a
3315 // starting window, but hasn't yet done so. Steal it!
3316 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
3317 "Moving pending starting from " + ttoken
3318 + " to " + wtoken);
3319 wtoken.startingData = ttoken.startingData;
3320 ttoken.startingData = null;
3321 ttoken.startingMoved = true;
3322 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3323 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3324 // want to process the message ASAP, before any other queued
3325 // messages.
3326 mH.sendMessageAtFrontOfQueue(m);
3327 return;
3328 }
3329 }
3330 }
3331
3332 // There is no existing starting window, and the caller doesn't
3333 // want us to create one, so that's it!
3334 if (!createIfNeeded) {
3335 return;
3336 }
Romain Guy06882f82009-06-10 13:36:04 -07003337
Dianne Hackborn284ac932009-08-28 10:34:25 -07003338 // If this is a translucent or wallpaper window, then don't
3339 // show a starting window -- the current effect (a full-screen
3340 // opaque starting window that fades away to the real contents
3341 // when it is ready) does not work for this.
3342 if (theme != 0) {
3343 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
3344 com.android.internal.R.styleable.Window);
3345 if (ent.array.getBoolean(
3346 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
3347 return;
3348 }
3349 if (ent.array.getBoolean(
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07003350 com.android.internal.R.styleable.Window_windowIsFloating, false)) {
3351 return;
3352 }
3353 if (ent.array.getBoolean(
Dianne Hackborn284ac932009-08-28 10:34:25 -07003354 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
3355 return;
3356 }
3357 }
3358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 mStartingIconInTransition = true;
3360 wtoken.startingData = new StartingData(
3361 pkg, theme, nonLocalizedLabel,
3362 labelRes, icon);
3363 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3364 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3365 // want to process the message ASAP, before any other queued
3366 // messages.
3367 mH.sendMessageAtFrontOfQueue(m);
3368 }
3369 }
3370
3371 public void setAppWillBeHidden(IBinder token) {
3372 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3373 "setAppWillBeHidden()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003374 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003375 }
3376
3377 AppWindowToken wtoken;
3378
3379 synchronized(mWindowMap) {
3380 wtoken = findAppWindowToken(token);
3381 if (wtoken == null) {
3382 Log.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
3383 return;
3384 }
3385 wtoken.willBeHidden = true;
3386 }
3387 }
Romain Guy06882f82009-06-10 13:36:04 -07003388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
3390 boolean visible, int transit, boolean performLayout) {
3391 boolean delayed = false;
3392
3393 if (wtoken.clientHidden == visible) {
3394 wtoken.clientHidden = !visible;
3395 wtoken.sendAppVisibilityToClients();
3396 }
Romain Guy06882f82009-06-10 13:36:04 -07003397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003398 wtoken.willBeHidden = false;
3399 if (wtoken.hidden == visible) {
3400 final int N = wtoken.allAppWindows.size();
3401 boolean changed = false;
3402 if (DEBUG_APP_TRANSITIONS) Log.v(
3403 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
3404 + " performLayout=" + performLayout);
Romain Guy06882f82009-06-10 13:36:04 -07003405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003406 boolean runningAppAnimation = false;
Romain Guy06882f82009-06-10 13:36:04 -07003407
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003408 if (transit != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003409 if (wtoken.animation == sDummyAnimation) {
3410 wtoken.animation = null;
3411 }
3412 applyAnimationLocked(wtoken, lp, transit, visible);
3413 changed = true;
3414 if (wtoken.animation != null) {
3415 delayed = runningAppAnimation = true;
3416 }
3417 }
Romain Guy06882f82009-06-10 13:36:04 -07003418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003419 for (int i=0; i<N; i++) {
3420 WindowState win = wtoken.allAppWindows.get(i);
3421 if (win == wtoken.startingWindow) {
3422 continue;
3423 }
3424
3425 if (win.isAnimating()) {
3426 delayed = true;
3427 }
Romain Guy06882f82009-06-10 13:36:04 -07003428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003429 //Log.i(TAG, "Window " + win + ": vis=" + win.isVisible());
3430 //win.dump(" ");
3431 if (visible) {
3432 if (!win.isVisibleNow()) {
3433 if (!runningAppAnimation) {
3434 applyAnimationLocked(win,
3435 WindowManagerPolicy.TRANSIT_ENTER, true);
3436 }
3437 changed = true;
3438 }
3439 } else if (win.isVisibleNow()) {
3440 if (!runningAppAnimation) {
3441 applyAnimationLocked(win,
3442 WindowManagerPolicy.TRANSIT_EXIT, false);
3443 }
3444 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
3445 KeyWaiter.RETURN_NOTHING);
3446 changed = true;
3447 }
3448 }
3449
3450 wtoken.hidden = wtoken.hiddenRequested = !visible;
3451 if (!visible) {
3452 unsetAppFreezingScreenLocked(wtoken, true, true);
3453 } else {
3454 // If we are being set visible, and the starting window is
3455 // not yet displayed, then make sure it doesn't get displayed.
3456 WindowState swin = wtoken.startingWindow;
3457 if (swin != null && (swin.mDrawPending
3458 || swin.mCommitDrawPending)) {
3459 swin.mPolicyVisibility = false;
3460 swin.mPolicyVisibilityAfterAnim = false;
3461 }
3462 }
Romain Guy06882f82009-06-10 13:36:04 -07003463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003464 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "setTokenVisibilityLocked: " + wtoken
3465 + ": hidden=" + wtoken.hidden + " hiddenRequested="
3466 + wtoken.hiddenRequested);
Romain Guy06882f82009-06-10 13:36:04 -07003467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 if (changed && performLayout) {
3469 mLayoutNeeded = true;
3470 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471 performLayoutAndPlaceSurfacesLocked();
3472 }
3473 }
3474
3475 if (wtoken.animation != null) {
3476 delayed = true;
3477 }
Romain Guy06882f82009-06-10 13:36:04 -07003478
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 return delayed;
3480 }
3481
3482 public void setAppVisibility(IBinder token, boolean visible) {
3483 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3484 "setAppVisibility()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003485 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003486 }
3487
3488 AppWindowToken wtoken;
3489
3490 synchronized(mWindowMap) {
3491 wtoken = findAppWindowToken(token);
3492 if (wtoken == null) {
3493 Log.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
3494 return;
3495 }
3496
3497 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
3498 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003499 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003500 Log.v(TAG, "setAppVisibility(" + token + ", " + visible
3501 + "): mNextAppTransition=" + mNextAppTransition
3502 + " hidden=" + wtoken.hidden
3503 + " hiddenRequested=" + wtoken.hiddenRequested, e);
3504 }
Romain Guy06882f82009-06-10 13:36:04 -07003505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003506 // If we are preparing an app transition, then delay changing
3507 // the visibility of this token until we execute that transition.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003508 if (!mDisplayFrozen && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003509 // Already in requested state, don't do anything more.
3510 if (wtoken.hiddenRequested != visible) {
3511 return;
3512 }
3513 wtoken.hiddenRequested = !visible;
Romain Guy06882f82009-06-10 13:36:04 -07003514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 if (DEBUG_APP_TRANSITIONS) Log.v(
3516 TAG, "Setting dummy animation on: " + wtoken);
3517 wtoken.setDummyAnimation();
3518 mOpeningApps.remove(wtoken);
3519 mClosingApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003520 wtoken.waitingToShow = wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 wtoken.inPendingTransaction = true;
3522 if (visible) {
3523 mOpeningApps.add(wtoken);
3524 wtoken.allDrawn = false;
3525 wtoken.startingDisplayed = false;
3526 wtoken.startingMoved = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -07003527 wtoken.waitingToShow = true;
Romain Guy06882f82009-06-10 13:36:04 -07003528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003529 if (wtoken.clientHidden) {
3530 // In the case where we are making an app visible
3531 // but holding off for a transition, we still need
3532 // to tell the client to make its windows visible so
3533 // they get drawn. Otherwise, we will wait on
3534 // performing the transition until all windows have
3535 // been drawn, they never will be, and we are sad.
3536 wtoken.clientHidden = false;
3537 wtoken.sendAppVisibilityToClients();
3538 }
3539 } else {
3540 mClosingApps.add(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003541 wtoken.waitingToHide = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003542 }
3543 return;
3544 }
Romain Guy06882f82009-06-10 13:36:04 -07003545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003546 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003547 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003548 wtoken.updateReportedVisibilityLocked();
3549 Binder.restoreCallingIdentity(origId);
3550 }
3551 }
3552
3553 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
3554 boolean unfreezeSurfaceNow, boolean force) {
3555 if (wtoken.freezingScreen) {
3556 if (DEBUG_ORIENTATION) Log.v(TAG, "Clear freezing of " + wtoken
3557 + " force=" + force);
3558 final int N = wtoken.allAppWindows.size();
3559 boolean unfrozeWindows = false;
3560 for (int i=0; i<N; i++) {
3561 WindowState w = wtoken.allAppWindows.get(i);
3562 if (w.mAppFreezing) {
3563 w.mAppFreezing = false;
3564 if (w.mSurface != null && !w.mOrientationChanging) {
3565 w.mOrientationChanging = true;
3566 }
3567 unfrozeWindows = true;
3568 }
3569 }
3570 if (force || unfrozeWindows) {
3571 if (DEBUG_ORIENTATION) Log.v(TAG, "No longer freezing: " + wtoken);
3572 wtoken.freezingScreen = false;
3573 mAppsFreezingScreen--;
3574 }
3575 if (unfreezeSurfaceNow) {
3576 if (unfrozeWindows) {
3577 mLayoutNeeded = true;
3578 performLayoutAndPlaceSurfacesLocked();
3579 }
3580 if (mAppsFreezingScreen == 0 && !mWindowsFreezingScreen) {
3581 stopFreezingDisplayLocked();
3582 }
3583 }
3584 }
3585 }
Romain Guy06882f82009-06-10 13:36:04 -07003586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003587 public void startAppFreezingScreenLocked(AppWindowToken wtoken,
3588 int configChanges) {
3589 if (DEBUG_ORIENTATION) {
3590 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003591 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003592 Log.i(TAG, "Set freezing of " + wtoken.appToken
3593 + ": hidden=" + wtoken.hidden + " freezing="
3594 + wtoken.freezingScreen, e);
3595 }
3596 if (!wtoken.hiddenRequested) {
3597 if (!wtoken.freezingScreen) {
3598 wtoken.freezingScreen = true;
3599 mAppsFreezingScreen++;
3600 if (mAppsFreezingScreen == 1) {
3601 startFreezingDisplayLocked();
3602 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
3603 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
3604 5000);
3605 }
3606 }
3607 final int N = wtoken.allAppWindows.size();
3608 for (int i=0; i<N; i++) {
3609 WindowState w = wtoken.allAppWindows.get(i);
3610 w.mAppFreezing = true;
3611 }
3612 }
3613 }
Romain Guy06882f82009-06-10 13:36:04 -07003614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003615 public void startAppFreezingScreen(IBinder token, int configChanges) {
3616 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3617 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003618 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003619 }
3620
3621 synchronized(mWindowMap) {
3622 if (configChanges == 0 && !mDisplayFrozen) {
3623 if (DEBUG_ORIENTATION) Log.v(TAG, "Skipping set freeze of " + token);
3624 return;
3625 }
Romain Guy06882f82009-06-10 13:36:04 -07003626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 AppWindowToken wtoken = findAppWindowToken(token);
3628 if (wtoken == null || wtoken.appToken == null) {
3629 Log.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
3630 return;
3631 }
3632 final long origId = Binder.clearCallingIdentity();
3633 startAppFreezingScreenLocked(wtoken, configChanges);
3634 Binder.restoreCallingIdentity(origId);
3635 }
3636 }
Romain Guy06882f82009-06-10 13:36:04 -07003637
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003638 public void stopAppFreezingScreen(IBinder token, boolean force) {
3639 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3640 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003641 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 }
3643
3644 synchronized(mWindowMap) {
3645 AppWindowToken wtoken = findAppWindowToken(token);
3646 if (wtoken == null || wtoken.appToken == null) {
3647 return;
3648 }
3649 final long origId = Binder.clearCallingIdentity();
3650 if (DEBUG_ORIENTATION) Log.v(TAG, "Clear freezing of " + token
3651 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
3652 unsetAppFreezingScreenLocked(wtoken, true, force);
3653 Binder.restoreCallingIdentity(origId);
3654 }
3655 }
Romain Guy06882f82009-06-10 13:36:04 -07003656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003657 public void removeAppToken(IBinder token) {
3658 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3659 "removeAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003660 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003661 }
3662
3663 AppWindowToken wtoken = null;
3664 AppWindowToken startingToken = null;
3665 boolean delayed = false;
3666
3667 final long origId = Binder.clearCallingIdentity();
3668 synchronized(mWindowMap) {
3669 WindowToken basewtoken = mTokenMap.remove(token);
3670 mTokenList.remove(basewtoken);
3671 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
3672 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "Removing app token: " + wtoken);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003673 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 wtoken.inPendingTransaction = false;
3675 mOpeningApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003676 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003677 if (mClosingApps.contains(wtoken)) {
3678 delayed = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003679 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003680 mClosingApps.add(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003681 wtoken.waitingToHide = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003682 delayed = true;
3683 }
3684 if (DEBUG_APP_TRANSITIONS) Log.v(
3685 TAG, "Removing app " + wtoken + " delayed=" + delayed
3686 + " animation=" + wtoken.animation
3687 + " animating=" + wtoken.animating);
3688 if (delayed) {
3689 // set the token aside because it has an active animation to be finished
3690 mExitingAppTokens.add(wtoken);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003691 } else {
3692 // Make sure there is no animation running on this token,
3693 // so any windows associated with it will be removed as
3694 // soon as their animations are complete
3695 wtoken.animation = null;
3696 wtoken.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003697 }
3698 mAppTokens.remove(wtoken);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003699 if (mLastEnterAnimToken == wtoken) {
3700 mLastEnterAnimToken = null;
3701 mLastEnterAnimParams = null;
3702 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003703 wtoken.removed = true;
3704 if (wtoken.startingData != null) {
3705 startingToken = wtoken;
3706 }
3707 unsetAppFreezingScreenLocked(wtoken, true, true);
3708 if (mFocusedApp == wtoken) {
3709 if (DEBUG_FOCUS) Log.v(TAG, "Removing focused app token:" + wtoken);
3710 mFocusedApp = null;
3711 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3712 mKeyWaiter.tickle();
3713 }
3714 } else {
3715 Log.w(TAG, "Attempted to remove non-existing app token: " + token);
3716 }
Romain Guy06882f82009-06-10 13:36:04 -07003717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003718 if (!delayed && wtoken != null) {
3719 wtoken.updateReportedVisibilityLocked();
3720 }
3721 }
3722 Binder.restoreCallingIdentity(origId);
3723
3724 if (startingToken != null) {
3725 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Schedule remove starting "
3726 + startingToken + ": app token removed");
3727 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
3728 mH.sendMessage(m);
3729 }
3730 }
3731
3732 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
3733 final int NW = token.windows.size();
3734 for (int i=0; i<NW; i++) {
3735 WindowState win = token.windows.get(i);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003736 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Tmp removing app window " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003737 mWindows.remove(win);
3738 int j = win.mChildWindows.size();
3739 while (j > 0) {
3740 j--;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003741 WindowState cwin = (WindowState)win.mChildWindows.get(j);
3742 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
3743 "Tmp removing child window " + cwin);
3744 mWindows.remove(cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003745 }
3746 }
3747 return NW > 0;
3748 }
3749
3750 void dumpAppTokensLocked() {
3751 for (int i=mAppTokens.size()-1; i>=0; i--) {
3752 Log.v(TAG, " #" + i + ": " + mAppTokens.get(i).token);
3753 }
3754 }
Romain Guy06882f82009-06-10 13:36:04 -07003755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003756 void dumpWindowsLocked() {
3757 for (int i=mWindows.size()-1; i>=0; i--) {
3758 Log.v(TAG, " #" + i + ": " + mWindows.get(i));
3759 }
3760 }
Romain Guy06882f82009-06-10 13:36:04 -07003761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003762 private int findWindowOffsetLocked(int tokenPos) {
3763 final int NW = mWindows.size();
3764
3765 if (tokenPos >= mAppTokens.size()) {
3766 int i = NW;
3767 while (i > 0) {
3768 i--;
3769 WindowState win = (WindowState)mWindows.get(i);
3770 if (win.getAppToken() != null) {
3771 return i+1;
3772 }
3773 }
3774 }
3775
3776 while (tokenPos > 0) {
3777 // Find the first app token below the new position that has
3778 // a window displayed.
3779 final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
3780 if (DEBUG_REORDER) Log.v(TAG, "Looking for lower windows @ "
3781 + tokenPos + " -- " + wtoken.token);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003782 if (wtoken.sendingToBottom) {
3783 if (DEBUG_REORDER) Log.v(TAG,
3784 "Skipping token -- currently sending to bottom");
3785 tokenPos--;
3786 continue;
3787 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003788 int i = wtoken.windows.size();
3789 while (i > 0) {
3790 i--;
3791 WindowState win = wtoken.windows.get(i);
3792 int j = win.mChildWindows.size();
3793 while (j > 0) {
3794 j--;
3795 WindowState cwin = (WindowState)win.mChildWindows.get(j);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003796 if (cwin.mSubLayer >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003797 for (int pos=NW-1; pos>=0; pos--) {
3798 if (mWindows.get(pos) == cwin) {
3799 if (DEBUG_REORDER) Log.v(TAG,
3800 "Found child win @" + (pos+1));
3801 return pos+1;
3802 }
3803 }
3804 }
3805 }
3806 for (int pos=NW-1; pos>=0; pos--) {
3807 if (mWindows.get(pos) == win) {
3808 if (DEBUG_REORDER) Log.v(TAG, "Found win @" + (pos+1));
3809 return pos+1;
3810 }
3811 }
3812 }
3813 tokenPos--;
3814 }
3815
3816 return 0;
3817 }
3818
3819 private final int reAddWindowLocked(int index, WindowState win) {
3820 final int NCW = win.mChildWindows.size();
3821 boolean added = false;
3822 for (int j=0; j<NCW; j++) {
3823 WindowState cwin = (WindowState)win.mChildWindows.get(j);
3824 if (!added && cwin.mSubLayer >= 0) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003825 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Re-adding child window at "
3826 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003827 mWindows.add(index, win);
3828 index++;
3829 added = true;
3830 }
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003831 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Re-adding window at "
3832 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003833 mWindows.add(index, cwin);
3834 index++;
3835 }
3836 if (!added) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003837 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG, "Re-adding window at "
3838 + index + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003839 mWindows.add(index, win);
3840 index++;
3841 }
3842 return index;
3843 }
Romain Guy06882f82009-06-10 13:36:04 -07003844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003845 private final int reAddAppWindowsLocked(int index, WindowToken token) {
3846 final int NW = token.windows.size();
3847 for (int i=0; i<NW; i++) {
3848 index = reAddWindowLocked(index, token.windows.get(i));
3849 }
3850 return index;
3851 }
3852
3853 public void moveAppToken(int index, IBinder token) {
3854 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3855 "moveAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003856 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003857 }
3858
3859 synchronized(mWindowMap) {
3860 if (DEBUG_REORDER) Log.v(TAG, "Initial app tokens:");
3861 if (DEBUG_REORDER) dumpAppTokensLocked();
3862 final AppWindowToken wtoken = findAppWindowToken(token);
3863 if (wtoken == null || !mAppTokens.remove(wtoken)) {
3864 Log.w(TAG, "Attempting to reorder token that doesn't exist: "
3865 + token + " (" + wtoken + ")");
3866 return;
3867 }
3868 mAppTokens.add(index, wtoken);
3869 if (DEBUG_REORDER) Log.v(TAG, "Moved " + token + " to " + index + ":");
3870 if (DEBUG_REORDER) dumpAppTokensLocked();
Romain Guy06882f82009-06-10 13:36:04 -07003871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003872 final long origId = Binder.clearCallingIdentity();
3873 if (DEBUG_REORDER) Log.v(TAG, "Removing windows in " + token + ":");
3874 if (DEBUG_REORDER) dumpWindowsLocked();
3875 if (tmpRemoveAppWindowsLocked(wtoken)) {
3876 if (DEBUG_REORDER) Log.v(TAG, "Adding windows back in:");
3877 if (DEBUG_REORDER) dumpWindowsLocked();
3878 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
3879 if (DEBUG_REORDER) Log.v(TAG, "Final window list:");
3880 if (DEBUG_REORDER) dumpWindowsLocked();
3881 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 mLayoutNeeded = true;
3883 performLayoutAndPlaceSurfacesLocked();
3884 }
3885 Binder.restoreCallingIdentity(origId);
3886 }
3887 }
3888
3889 private void removeAppTokensLocked(List<IBinder> tokens) {
3890 // XXX This should be done more efficiently!
3891 // (take advantage of the fact that both lists should be
3892 // ordered in the same way.)
3893 int N = tokens.size();
3894 for (int i=0; i<N; i++) {
3895 IBinder token = tokens.get(i);
3896 final AppWindowToken wtoken = findAppWindowToken(token);
3897 if (!mAppTokens.remove(wtoken)) {
3898 Log.w(TAG, "Attempting to reorder token that doesn't exist: "
3899 + token + " (" + wtoken + ")");
3900 i--;
3901 N--;
3902 }
3903 }
3904 }
3905
Dianne Hackborna8f60182009-09-01 19:01:50 -07003906 private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos,
3907 boolean updateFocusAndLayout) {
3908 // First remove all of the windows from the list.
3909 tmpRemoveAppWindowsLocked(wtoken);
3910
3911 // Where to start adding?
3912 int pos = findWindowOffsetLocked(tokenPos);
3913
3914 // And now add them back at the correct place.
3915 pos = reAddAppWindowsLocked(pos, wtoken);
3916
3917 if (updateFocusAndLayout) {
3918 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
3919 assignLayersLocked();
3920 }
3921 mLayoutNeeded = true;
3922 performLayoutAndPlaceSurfacesLocked();
3923 }
3924 }
3925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
3927 // First remove all of the windows from the list.
3928 final int N = tokens.size();
3929 int i;
3930 for (i=0; i<N; i++) {
3931 WindowToken token = mTokenMap.get(tokens.get(i));
3932 if (token != null) {
3933 tmpRemoveAppWindowsLocked(token);
3934 }
3935 }
3936
3937 // Where to start adding?
3938 int pos = findWindowOffsetLocked(tokenPos);
3939
3940 // And now add them back at the correct place.
3941 for (i=0; i<N; i++) {
3942 WindowToken token = mTokenMap.get(tokens.get(i));
3943 if (token != null) {
3944 pos = reAddAppWindowsLocked(pos, token);
3945 }
3946 }
3947
Dianne Hackborna8f60182009-09-01 19:01:50 -07003948 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
3949 assignLayersLocked();
3950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003951 mLayoutNeeded = true;
3952 performLayoutAndPlaceSurfacesLocked();
3953
3954 //dump();
3955 }
3956
3957 public void moveAppTokensToTop(List<IBinder> tokens) {
3958 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3959 "moveAppTokensToTop()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003960 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 }
3962
3963 final long origId = Binder.clearCallingIdentity();
3964 synchronized(mWindowMap) {
3965 removeAppTokensLocked(tokens);
3966 final int N = tokens.size();
3967 for (int i=0; i<N; i++) {
3968 AppWindowToken wt = findAppWindowToken(tokens.get(i));
3969 if (wt != null) {
3970 mAppTokens.add(wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003971 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07003972 mToTopApps.remove(wt);
3973 mToBottomApps.remove(wt);
3974 mToTopApps.add(wt);
3975 wt.sendingToBottom = false;
3976 wt.sendingToTop = true;
3977 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003978 }
3979 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07003980
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003981 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07003982 moveAppWindowsLocked(tokens, mAppTokens.size());
3983 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003984 }
3985 Binder.restoreCallingIdentity(origId);
3986 }
3987
3988 public void moveAppTokensToBottom(List<IBinder> tokens) {
3989 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3990 "moveAppTokensToBottom()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003991 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003992 }
3993
3994 final long origId = Binder.clearCallingIdentity();
3995 synchronized(mWindowMap) {
3996 removeAppTokensLocked(tokens);
3997 final int N = tokens.size();
3998 int pos = 0;
3999 for (int i=0; i<N; i++) {
4000 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4001 if (wt != null) {
4002 mAppTokens.add(pos, wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004003 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004004 mToTopApps.remove(wt);
4005 mToBottomApps.remove(wt);
4006 mToBottomApps.add(i, wt);
4007 wt.sendingToTop = false;
4008 wt.sendingToBottom = true;
4009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004010 pos++;
4011 }
4012 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07004013
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004014 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004015 moveAppWindowsLocked(tokens, 0);
4016 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004017 }
4018 Binder.restoreCallingIdentity(origId);
4019 }
4020
4021 // -------------------------------------------------------------
4022 // Misc IWindowSession methods
4023 // -------------------------------------------------------------
Romain Guy06882f82009-06-10 13:36:04 -07004024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004025 public void disableKeyguard(IBinder token, String tag) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004026 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004027 != PackageManager.PERMISSION_GRANTED) {
4028 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4029 }
Mike Lockwooddd884682009-10-11 16:57:08 -04004030 synchronized (mKeyguardDisabled) {
4031 mKeyguardDisabled.acquire(token, tag);
4032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004033 }
4034
4035 public void reenableKeyguard(IBinder token) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004036 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004037 != PackageManager.PERMISSION_GRANTED) {
4038 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4039 }
4040 synchronized (mKeyguardDisabled) {
4041 mKeyguardDisabled.release(token);
4042
4043 if (!mKeyguardDisabled.isAcquired()) {
4044 // if we are the last one to reenable the keyguard wait until
4045 // we have actaully finished reenabling until returning
4046 mWaitingUntilKeyguardReenabled = true;
4047 while (mWaitingUntilKeyguardReenabled) {
4048 try {
4049 mKeyguardDisabled.wait();
4050 } catch (InterruptedException e) {
4051 Thread.currentThread().interrupt();
4052 }
4053 }
4054 }
4055 }
4056 }
4057
4058 /**
4059 * @see android.app.KeyguardManager#exitKeyguardSecurely
4060 */
4061 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004062 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 != PackageManager.PERMISSION_GRANTED) {
4064 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4065 }
4066 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
4067 public void onKeyguardExitResult(boolean success) {
4068 try {
4069 callback.onKeyguardExitResult(success);
4070 } catch (RemoteException e) {
4071 // Client has died, we don't care.
4072 }
4073 }
4074 });
4075 }
4076
4077 public boolean inKeyguardRestrictedInputMode() {
4078 return mPolicy.inKeyguardRestrictedKeyInputMode();
4079 }
Romain Guy06882f82009-06-10 13:36:04 -07004080
Dianne Hackbornffa42482009-09-23 22:20:11 -07004081 public void closeSystemDialogs(String reason) {
4082 synchronized(mWindowMap) {
4083 for (int i=mWindows.size()-1; i>=0; i--) {
4084 WindowState w = (WindowState)mWindows.get(i);
4085 if (w.mSurface != null) {
4086 try {
4087 w.mClient.closeSystemDialogs(reason);
4088 } catch (RemoteException e) {
4089 }
4090 }
4091 }
4092 }
4093 }
4094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004095 static float fixScale(float scale) {
4096 if (scale < 0) scale = 0;
4097 else if (scale > 20) scale = 20;
4098 return Math.abs(scale);
4099 }
Romain Guy06882f82009-06-10 13:36:04 -07004100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 public void setAnimationScale(int which, float scale) {
4102 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4103 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004104 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004105 }
4106
4107 if (scale < 0) scale = 0;
4108 else if (scale > 20) scale = 20;
4109 scale = Math.abs(scale);
4110 switch (which) {
4111 case 0: mWindowAnimationScale = fixScale(scale); break;
4112 case 1: mTransitionAnimationScale = fixScale(scale); break;
4113 }
Romain Guy06882f82009-06-10 13:36:04 -07004114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115 // Persist setting
4116 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4117 }
Romain Guy06882f82009-06-10 13:36:04 -07004118
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004119 public void setAnimationScales(float[] scales) {
4120 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4121 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004122 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004123 }
4124
4125 if (scales != null) {
4126 if (scales.length >= 1) {
4127 mWindowAnimationScale = fixScale(scales[0]);
4128 }
4129 if (scales.length >= 2) {
4130 mTransitionAnimationScale = fixScale(scales[1]);
4131 }
4132 }
Romain Guy06882f82009-06-10 13:36:04 -07004133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004134 // Persist setting
4135 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4136 }
Romain Guy06882f82009-06-10 13:36:04 -07004137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004138 public float getAnimationScale(int which) {
4139 switch (which) {
4140 case 0: return mWindowAnimationScale;
4141 case 1: return mTransitionAnimationScale;
4142 }
4143 return 0;
4144 }
Romain Guy06882f82009-06-10 13:36:04 -07004145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004146 public float[] getAnimationScales() {
4147 return new float[] { mWindowAnimationScale, mTransitionAnimationScale };
4148 }
Romain Guy06882f82009-06-10 13:36:04 -07004149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004150 public int getSwitchState(int sw) {
4151 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4152 "getSwitchState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004153 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004154 }
4155 return KeyInputQueue.getSwitchState(sw);
4156 }
Romain Guy06882f82009-06-10 13:36:04 -07004157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 public int getSwitchStateForDevice(int devid, int sw) {
4159 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4160 "getSwitchStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004161 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004162 }
4163 return KeyInputQueue.getSwitchState(devid, sw);
4164 }
Romain Guy06882f82009-06-10 13:36:04 -07004165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004166 public int getScancodeState(int sw) {
4167 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4168 "getScancodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004169 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004171 return mQueue.getScancodeState(sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 }
Romain Guy06882f82009-06-10 13:36:04 -07004173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 public int getScancodeStateForDevice(int devid, int sw) {
4175 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4176 "getScancodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004177 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004178 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004179 return mQueue.getScancodeState(devid, sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004180 }
Romain Guy06882f82009-06-10 13:36:04 -07004181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004182 public int getKeycodeState(int sw) {
4183 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4184 "getKeycodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004185 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004186 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004187 return mQueue.getKeycodeState(sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004188 }
Romain Guy06882f82009-06-10 13:36:04 -07004189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 public int getKeycodeStateForDevice(int devid, int sw) {
4191 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4192 "getKeycodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004193 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004195 return mQueue.getKeycodeState(devid, sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196 }
Romain Guy06882f82009-06-10 13:36:04 -07004197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004198 public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
4199 return KeyInputQueue.hasKeys(keycodes, keyExists);
4200 }
Romain Guy06882f82009-06-10 13:36:04 -07004201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004202 public void enableScreenAfterBoot() {
4203 synchronized(mWindowMap) {
4204 if (mSystemBooted) {
4205 return;
4206 }
4207 mSystemBooted = true;
4208 }
Romain Guy06882f82009-06-10 13:36:04 -07004209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004210 performEnableScreen();
4211 }
Romain Guy06882f82009-06-10 13:36:04 -07004212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004213 public void enableScreenIfNeededLocked() {
4214 if (mDisplayEnabled) {
4215 return;
4216 }
4217 if (!mSystemBooted) {
4218 return;
4219 }
4220 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
4221 }
Romain Guy06882f82009-06-10 13:36:04 -07004222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 public void performEnableScreen() {
4224 synchronized(mWindowMap) {
4225 if (mDisplayEnabled) {
4226 return;
4227 }
4228 if (!mSystemBooted) {
4229 return;
4230 }
Romain Guy06882f82009-06-10 13:36:04 -07004231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232 // Don't enable the screen until all existing windows
4233 // have been drawn.
4234 final int N = mWindows.size();
4235 for (int i=0; i<N; i++) {
4236 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07004237 if (w.isVisibleLw() && !w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004238 return;
4239 }
4240 }
Romain Guy06882f82009-06-10 13:36:04 -07004241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004242 mDisplayEnabled = true;
4243 if (false) {
4244 Log.i(TAG, "ENABLING SCREEN!");
4245 StringWriter sw = new StringWriter();
4246 PrintWriter pw = new PrintWriter(sw);
4247 this.dump(null, pw, null);
4248 Log.i(TAG, sw.toString());
4249 }
4250 try {
4251 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
4252 if (surfaceFlinger != null) {
4253 //Log.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
4254 Parcel data = Parcel.obtain();
4255 data.writeInterfaceToken("android.ui.ISurfaceComposer");
4256 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
4257 data, null, 0);
4258 data.recycle();
4259 }
4260 } catch (RemoteException ex) {
4261 Log.e(TAG, "Boot completed: SurfaceFlinger is dead!");
4262 }
4263 }
Romain Guy06882f82009-06-10 13:36:04 -07004264
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 mPolicy.enableScreenAfterBoot();
Romain Guy06882f82009-06-10 13:36:04 -07004266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004267 // Make sure the last requested orientation has been applied.
Dianne Hackborn321ae682009-03-27 16:16:03 -07004268 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
4269 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004270 }
Romain Guy06882f82009-06-10 13:36:04 -07004271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004272 public void setInTouchMode(boolean mode) {
4273 synchronized(mWindowMap) {
4274 mInTouchMode = mode;
4275 }
4276 }
4277
Romain Guy06882f82009-06-10 13:36:04 -07004278 public void setRotation(int rotation,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004279 boolean alwaysSendConfiguration, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004280 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004281 "setRotation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004282 throw new SecurityException("Requires SET_ORIENTATION permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004283 }
4284
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004285 setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 }
Romain Guy06882f82009-06-10 13:36:04 -07004287
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004288 public void setRotationUnchecked(int rotation,
4289 boolean alwaysSendConfiguration, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 if(DEBUG_ORIENTATION) Log.v(TAG,
4291 "alwaysSendConfiguration set to "+alwaysSendConfiguration);
Romain Guy06882f82009-06-10 13:36:04 -07004292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004293 long origId = Binder.clearCallingIdentity();
4294 boolean changed;
4295 synchronized(mWindowMap) {
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004296 changed = setRotationUncheckedLocked(rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004297 }
Romain Guy06882f82009-06-10 13:36:04 -07004298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004299 if (changed) {
4300 sendNewConfiguration();
4301 synchronized(mWindowMap) {
4302 mLayoutNeeded = true;
4303 performLayoutAndPlaceSurfacesLocked();
4304 }
4305 } else if (alwaysSendConfiguration) {
4306 //update configuration ignoring orientation change
4307 sendNewConfiguration();
4308 }
Romain Guy06882f82009-06-10 13:36:04 -07004309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 Binder.restoreCallingIdentity(origId);
4311 }
Romain Guy06882f82009-06-10 13:36:04 -07004312
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004313 public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004314 boolean changed;
4315 if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
4316 rotation = mRequestedRotation;
4317 } else {
4318 mRequestedRotation = rotation;
Dianne Hackborn321ae682009-03-27 16:16:03 -07004319 mLastRotationFlags = animFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 }
4321 if (DEBUG_ORIENTATION) Log.v(TAG, "Overwriting rotation value from " + rotation);
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07004322 rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004323 mRotation, mDisplayEnabled);
4324 if (DEBUG_ORIENTATION) Log.v(TAG, "new rotation is set to " + rotation);
4325 changed = mDisplayEnabled && mRotation != rotation;
Romain Guy06882f82009-06-10 13:36:04 -07004326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004327 if (changed) {
Romain Guy06882f82009-06-10 13:36:04 -07004328 if (DEBUG_ORIENTATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004329 "Rotation changed to " + rotation
4330 + " from " + mRotation
4331 + " (forceApp=" + mForcedAppOrientation
4332 + ", req=" + mRequestedRotation + ")");
4333 mRotation = rotation;
4334 mWindowsFreezingScreen = true;
4335 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
4336 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
4337 2000);
4338 startFreezingDisplayLocked();
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004339 Log.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 mQueue.setOrientation(rotation);
4341 if (mDisplayEnabled) {
Dianne Hackborn321ae682009-03-27 16:16:03 -07004342 Surface.setOrientation(0, rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343 }
4344 for (int i=mWindows.size()-1; i>=0; i--) {
4345 WindowState w = (WindowState)mWindows.get(i);
4346 if (w.mSurface != null) {
4347 w.mOrientationChanging = true;
4348 }
4349 }
4350 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
4351 try {
4352 mRotationWatchers.get(i).onRotationChanged(rotation);
4353 } catch (RemoteException e) {
4354 }
4355 }
4356 } //end if changed
Romain Guy06882f82009-06-10 13:36:04 -07004357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004358 return changed;
4359 }
Romain Guy06882f82009-06-10 13:36:04 -07004360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004361 public int getRotation() {
4362 return mRotation;
4363 }
4364
4365 public int watchRotation(IRotationWatcher watcher) {
4366 final IBinder watcherBinder = watcher.asBinder();
4367 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4368 public void binderDied() {
4369 synchronized (mWindowMap) {
4370 for (int i=0; i<mRotationWatchers.size(); i++) {
4371 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004372 IRotationWatcher removed = mRotationWatchers.remove(i);
4373 if (removed != null) {
4374 removed.asBinder().unlinkToDeath(this, 0);
4375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 i--;
4377 }
4378 }
4379 }
4380 }
4381 };
Romain Guy06882f82009-06-10 13:36:04 -07004382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004383 synchronized (mWindowMap) {
4384 try {
4385 watcher.asBinder().linkToDeath(dr, 0);
4386 mRotationWatchers.add(watcher);
4387 } catch (RemoteException e) {
4388 // Client died, no cleanup needed.
4389 }
Romain Guy06882f82009-06-10 13:36:04 -07004390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004391 return mRotation;
4392 }
4393 }
4394
4395 /**
4396 * Starts the view server on the specified port.
4397 *
4398 * @param port The port to listener to.
4399 *
4400 * @return True if the server was successfully started, false otherwise.
4401 *
4402 * @see com.android.server.ViewServer
4403 * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT
4404 */
4405 public boolean startViewServer(int port) {
Romain Guy06882f82009-06-10 13:36:04 -07004406 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004407 return false;
4408 }
4409
4410 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4411 return false;
4412 }
4413
4414 if (port < 1024) {
4415 return false;
4416 }
4417
4418 if (mViewServer != null) {
4419 if (!mViewServer.isRunning()) {
4420 try {
4421 return mViewServer.start();
4422 } catch (IOException e) {
Romain Guy06882f82009-06-10 13:36:04 -07004423 Log.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 }
4425 }
4426 return false;
4427 }
4428
4429 try {
4430 mViewServer = new ViewServer(this, port);
4431 return mViewServer.start();
4432 } catch (IOException e) {
4433 Log.w(TAG, "View server did not start");
4434 }
4435 return false;
4436 }
4437
Romain Guy06882f82009-06-10 13:36:04 -07004438 private boolean isSystemSecure() {
4439 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4440 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4441 }
4442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 /**
4444 * Stops the view server if it exists.
4445 *
4446 * @return True if the server stopped, false if it wasn't started or
4447 * couldn't be stopped.
4448 *
4449 * @see com.android.server.ViewServer
4450 */
4451 public boolean stopViewServer() {
Romain Guy06882f82009-06-10 13:36:04 -07004452 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004453 return false;
4454 }
4455
4456 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4457 return false;
4458 }
4459
4460 if (mViewServer != null) {
4461 return mViewServer.stop();
4462 }
4463 return false;
4464 }
4465
4466 /**
4467 * Indicates whether the view server is running.
4468 *
4469 * @return True if the server is running, false otherwise.
4470 *
4471 * @see com.android.server.ViewServer
4472 */
4473 public boolean isViewServerRunning() {
Romain Guy06882f82009-06-10 13:36:04 -07004474 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 return false;
4476 }
4477
4478 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4479 return false;
4480 }
4481
4482 return mViewServer != null && mViewServer.isRunning();
4483 }
4484
4485 /**
4486 * Lists all availble windows in the system. The listing is written in the
4487 * specified Socket's output stream with the following syntax:
4488 * windowHashCodeInHexadecimal windowName
4489 * Each line of the ouput represents a different window.
4490 *
4491 * @param client The remote client to send the listing to.
4492 * @return False if an error occured, true otherwise.
4493 */
4494 boolean viewServerListWindows(Socket client) {
Romain Guy06882f82009-06-10 13:36:04 -07004495 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004496 return false;
4497 }
4498
4499 boolean result = true;
4500
4501 Object[] windows;
4502 synchronized (mWindowMap) {
4503 windows = new Object[mWindows.size()];
4504 //noinspection unchecked
4505 windows = mWindows.toArray(windows);
4506 }
4507
4508 BufferedWriter out = null;
4509
4510 // Any uncaught exception will crash the system process
4511 try {
4512 OutputStream clientStream = client.getOutputStream();
4513 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4514
4515 final int count = windows.length;
4516 for (int i = 0; i < count; i++) {
4517 final WindowState w = (WindowState) windows[i];
4518 out.write(Integer.toHexString(System.identityHashCode(w)));
4519 out.write(' ');
4520 out.append(w.mAttrs.getTitle());
4521 out.write('\n');
4522 }
4523
4524 out.write("DONE.\n");
4525 out.flush();
4526 } catch (Exception e) {
4527 result = false;
4528 } finally {
4529 if (out != null) {
4530 try {
4531 out.close();
4532 } catch (IOException e) {
4533 result = false;
4534 }
4535 }
4536 }
4537
4538 return result;
4539 }
4540
4541 /**
4542 * Sends a command to a target window. The result of the command, if any, will be
4543 * written in the output stream of the specified socket.
4544 *
4545 * The parameters must follow this syntax:
4546 * windowHashcode extra
4547 *
4548 * Where XX is the length in characeters of the windowTitle.
4549 *
4550 * The first parameter is the target window. The window with the specified hashcode
4551 * will be the target. If no target can be found, nothing happens. The extra parameters
4552 * will be delivered to the target window and as parameters to the command itself.
4553 *
4554 * @param client The remote client to sent the result, if any, to.
4555 * @param command The command to execute.
4556 * @param parameters The command parameters.
4557 *
4558 * @return True if the command was successfully delivered, false otherwise. This does
4559 * not indicate whether the command itself was successful.
4560 */
4561 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
Romain Guy06882f82009-06-10 13:36:04 -07004562 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004563 return false;
4564 }
4565
4566 boolean success = true;
4567 Parcel data = null;
4568 Parcel reply = null;
4569
4570 // Any uncaught exception will crash the system process
4571 try {
4572 // Find the hashcode of the window
4573 int index = parameters.indexOf(' ');
4574 if (index == -1) {
4575 index = parameters.length();
4576 }
4577 final String code = parameters.substring(0, index);
4578 int hashCode = "ffffffff".equals(code) ? -1 : Integer.parseInt(code, 16);
4579
4580 // Extract the command's parameter after the window description
4581 if (index < parameters.length()) {
4582 parameters = parameters.substring(index + 1);
4583 } else {
4584 parameters = "";
4585 }
4586
4587 final WindowManagerService.WindowState window = findWindow(hashCode);
4588 if (window == null) {
4589 return false;
4590 }
4591
4592 data = Parcel.obtain();
4593 data.writeInterfaceToken("android.view.IWindow");
4594 data.writeString(command);
4595 data.writeString(parameters);
4596 data.writeInt(1);
4597 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4598
4599 reply = Parcel.obtain();
4600
4601 final IBinder binder = window.mClient.asBinder();
4602 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4603 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4604
4605 reply.readException();
4606
4607 } catch (Exception e) {
4608 Log.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
4609 success = false;
4610 } finally {
4611 if (data != null) {
4612 data.recycle();
4613 }
4614 if (reply != null) {
4615 reply.recycle();
4616 }
4617 }
4618
4619 return success;
4620 }
4621
4622 private WindowState findWindow(int hashCode) {
4623 if (hashCode == -1) {
4624 return getFocusedWindow();
4625 }
4626
4627 synchronized (mWindowMap) {
4628 final ArrayList windows = mWindows;
4629 final int count = windows.size();
4630
4631 for (int i = 0; i < count; i++) {
4632 WindowState w = (WindowState) windows.get(i);
4633 if (System.identityHashCode(w) == hashCode) {
4634 return w;
4635 }
4636 }
4637 }
4638
4639 return null;
4640 }
4641
4642 /*
4643 * Instruct the Activity Manager to fetch the current configuration and broadcast
4644 * that to config-changed listeners if appropriate.
4645 */
4646 void sendNewConfiguration() {
4647 try {
4648 mActivityManager.updateConfiguration(null);
4649 } catch (RemoteException e) {
4650 }
4651 }
Romain Guy06882f82009-06-10 13:36:04 -07004652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004653 public Configuration computeNewConfiguration() {
4654 synchronized (mWindowMap) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07004655 return computeNewConfigurationLocked();
4656 }
4657 }
Romain Guy06882f82009-06-10 13:36:04 -07004658
Dianne Hackbornc485a602009-03-24 22:39:49 -07004659 Configuration computeNewConfigurationLocked() {
4660 Configuration config = new Configuration();
4661 if (!computeNewConfigurationLocked(config)) {
4662 return null;
4663 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07004664 return config;
4665 }
Romain Guy06882f82009-06-10 13:36:04 -07004666
Dianne Hackbornc485a602009-03-24 22:39:49 -07004667 boolean computeNewConfigurationLocked(Configuration config) {
4668 if (mDisplay == null) {
4669 return false;
4670 }
4671 mQueue.getInputConfiguration(config);
4672 final int dw = mDisplay.getWidth();
4673 final int dh = mDisplay.getHeight();
4674 int orientation = Configuration.ORIENTATION_SQUARE;
4675 if (dw < dh) {
4676 orientation = Configuration.ORIENTATION_PORTRAIT;
4677 } else if (dw > dh) {
4678 orientation = Configuration.ORIENTATION_LANDSCAPE;
4679 }
4680 config.orientation = orientation;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004681
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07004682 DisplayMetrics dm = new DisplayMetrics();
4683 mDisplay.getMetrics(dm);
4684 CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
4685
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004686 if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07004687 // Note we only do this once because at this point we don't
4688 // expect the screen to change in this way at runtime, and want
4689 // to avoid all of this computation for every config change.
Dianne Hackborn723738c2009-06-25 19:48:04 -07004690 int longSize = dw;
4691 int shortSize = dh;
4692 if (longSize < shortSize) {
4693 int tmp = longSize;
4694 longSize = shortSize;
4695 shortSize = tmp;
4696 }
4697 longSize = (int)(longSize/dm.density);
4698 shortSize = (int)(shortSize/dm.density);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07004699
Dianne Hackborn723738c2009-06-25 19:48:04 -07004700 // These semi-magic numbers define our compatibility modes for
4701 // applications with different screens. Don't change unless you
4702 // make sure to test lots and lots of apps!
4703 if (longSize < 470) {
4704 // This is shorter than an HVGA normal density screen (which
4705 // is 480 pixels on its long side).
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004706 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
4707 | Configuration.SCREENLAYOUT_LONG_NO;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004708 } else {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004709 // Is this a large screen?
4710 if (longSize > 640 && shortSize >= 480) {
4711 // VGA or larger screens at medium density are the point
4712 // at which we consider it to be a large screen.
4713 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
4714 } else {
4715 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
4716
4717 // If this screen is wider than normal HVGA, or taller
4718 // than FWVGA, then for old apps we want to run in size
4719 // compatibility mode.
4720 if (shortSize > 321 || longSize > 570) {
4721 mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
4722 }
4723 }
4724
4725 // Is this a long screen?
4726 if (((longSize*3)/5) >= (shortSize-1)) {
4727 // Anything wider than WVGA (5:3) is considering to be long.
4728 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
4729 } else {
4730 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
4731 }
Dianne Hackborn723738c2009-06-25 19:48:04 -07004732 }
4733 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004734 config.screenLayout = mScreenLayout;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004735
Dianne Hackbornc485a602009-03-24 22:39:49 -07004736 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
4737 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
4738 mPolicy.adjustConfigurationLw(config);
4739 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004740 }
Romain Guy06882f82009-06-10 13:36:04 -07004741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004742 // -------------------------------------------------------------
4743 // Input Events and Focus Management
4744 // -------------------------------------------------------------
4745
4746 private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
Michael Chane96440f2009-05-06 10:27:36 -07004747 long curTime = SystemClock.uptimeMillis();
4748
Michael Chane10de972009-05-18 11:24:50 -07004749 if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
Michael Chane96440f2009-05-06 10:27:36 -07004750 if (mLastTouchEventType == eventType &&
4751 (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
4752 return;
4753 }
4754 mLastUserActivityCallTime = curTime;
4755 mLastTouchEventType = eventType;
4756 }
4757
4758 if (targetWin == null
4759 || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
4760 mPowerManager.userActivity(curTime, false, eventType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004761 }
4762 }
4763
4764 // tells if it's a cheek event or not -- this function is stateful
4765 private static final int EVENT_NONE = 0;
4766 private static final int EVENT_UNKNOWN = 0;
4767 private static final int EVENT_CHEEK = 0;
4768 private static final int EVENT_IGNORE_DURATION = 300; // ms
4769 private static final float CHEEK_THRESHOLD = 0.6f;
4770 private int mEventState = EVENT_NONE;
4771 private float mEventSize;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07004772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004773 private int eventType(MotionEvent ev) {
4774 float size = ev.getSize();
4775 switch (ev.getAction()) {
4776 case MotionEvent.ACTION_DOWN:
4777 mEventSize = size;
4778 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT;
4779 case MotionEvent.ACTION_UP:
4780 if (size > mEventSize) mEventSize = size;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07004781 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004782 case MotionEvent.ACTION_MOVE:
4783 final int N = ev.getHistorySize();
4784 if (size > mEventSize) mEventSize = size;
4785 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
4786 for (int i=0; i<N; i++) {
4787 size = ev.getHistoricalSize(i);
4788 if (size > mEventSize) mEventSize = size;
4789 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
4790 }
4791 if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) {
4792 return TOUCH_EVENT;
4793 } else {
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07004794 return LONG_TOUCH_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004795 }
4796 default:
4797 // not good
4798 return OTHER_EVENT;
4799 }
4800 }
4801
4802 /**
4803 * @return Returns true if event was dispatched, false if it was dropped for any reason
4804 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07004805 private int dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004806 if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Log.v(TAG,
4807 "dispatchPointer " + ev);
4808
Michael Chan53071d62009-05-13 17:29:48 -07004809 if (MEASURE_LATENCY) {
4810 lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
4811 }
4812
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004813 Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07004814 ev, true, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815
Michael Chan53071d62009-05-13 17:29:48 -07004816 if (MEASURE_LATENCY) {
4817 lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
4818 }
4819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004820 int action = ev.getAction();
Romain Guy06882f82009-06-10 13:36:04 -07004821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004822 if (action == MotionEvent.ACTION_UP) {
4823 // let go of our target
4824 mKeyWaiter.mMotionTarget = null;
4825 mPowerManager.logPointerUpEvent();
4826 } else if (action == MotionEvent.ACTION_DOWN) {
4827 mPowerManager.logPointerDownEvent();
4828 }
4829
4830 if (targetObj == null) {
4831 // In this case we are either dropping the event, or have received
4832 // a move or up without a down. It is common to receive move
4833 // events in such a way, since this means the user is moving the
4834 // pointer without actually pressing down. All other cases should
4835 // be atypical, so let's log them.
Michael Chane96440f2009-05-06 10:27:36 -07004836 if (action != MotionEvent.ACTION_MOVE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004837 Log.w(TAG, "No window to dispatch pointer action " + ev.getAction());
4838 }
4839 if (qev != null) {
4840 mQueue.recycleEvent(qev);
4841 }
4842 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004843 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004844 }
4845 if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
4846 if (qev != null) {
4847 mQueue.recycleEvent(qev);
4848 }
4849 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004850 return INJECT_SUCCEEDED;
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 WindowState target = (WindowState)targetObj;
Romain Guy06882f82009-06-10 13:36:04 -07004854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004855 final long eventTime = ev.getEventTime();
Michael Chan53071d62009-05-13 17:29:48 -07004856 final long eventTimeNano = ev.getEventTimeNano();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004857
4858 //Log.i(TAG, "Sending " + ev + " to " + target);
4859
4860 if (uid != 0 && uid != target.mSession.mUid) {
4861 if (mContext.checkPermission(
4862 android.Manifest.permission.INJECT_EVENTS, pid, uid)
4863 != PackageManager.PERMISSION_GRANTED) {
4864 Log.w(TAG, "Permission denied: injecting pointer event from pid "
4865 + pid + " uid " + uid + " to window " + target
4866 + " owned by uid " + target.mSession.mUid);
4867 if (qev != null) {
4868 mQueue.recycleEvent(qev);
4869 }
4870 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004871 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004872 }
4873 }
4874
Michael Chan53071d62009-05-13 17:29:48 -07004875 if (MEASURE_LATENCY) {
4876 lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano);
4877 }
4878
Romain Guy06882f82009-06-10 13:36:04 -07004879 if ((target.mAttrs.flags &
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004880 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
4881 //target wants to ignore fat touch events
4882 boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev);
4883 //explicit flag to return without processing event further
4884 boolean returnFlag = false;
4885 if((action == MotionEvent.ACTION_DOWN)) {
4886 mFatTouch = false;
4887 if(cheekPress) {
4888 mFatTouch = true;
4889 returnFlag = true;
4890 }
4891 } else {
4892 if(action == MotionEvent.ACTION_UP) {
4893 if(mFatTouch) {
4894 //earlier even was invalid doesnt matter if current up is cheekpress or not
4895 mFatTouch = false;
4896 returnFlag = true;
4897 } else if(cheekPress) {
4898 //cancel the earlier event
4899 ev.setAction(MotionEvent.ACTION_CANCEL);
4900 action = MotionEvent.ACTION_CANCEL;
4901 }
4902 } else if(action == MotionEvent.ACTION_MOVE) {
4903 if(mFatTouch) {
4904 //two cases here
4905 //an invalid down followed by 0 or moves(valid or invalid)
Romain Guy06882f82009-06-10 13:36:04 -07004906 //a valid down, invalid move, more moves. want to ignore till up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004907 returnFlag = true;
4908 } else if(cheekPress) {
4909 //valid down followed by invalid moves
4910 //an invalid move have to cancel earlier action
4911 ev.setAction(MotionEvent.ACTION_CANCEL);
4912 action = MotionEvent.ACTION_CANCEL;
4913 if (DEBUG_INPUT) Log.v(TAG, "Sending cancel for invalid ACTION_MOVE");
4914 //note that the subsequent invalid moves will not get here
4915 mFatTouch = true;
4916 }
4917 }
4918 } //else if action
4919 if(returnFlag) {
4920 //recycle que, ev
4921 if (qev != null) {
4922 mQueue.recycleEvent(qev);
4923 }
4924 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07004925 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004926 }
4927 } //end if target
Michael Chane96440f2009-05-06 10:27:36 -07004928
Michael Chan9f028e62009-08-04 17:37:46 -07004929 // Enable this for testing the "right" value
4930 if (false && action == MotionEvent.ACTION_DOWN) {
Michael Chane96440f2009-05-06 10:27:36 -07004931 int max_events_per_sec = 35;
4932 try {
4933 max_events_per_sec = Integer.parseInt(SystemProperties
4934 .get("windowsmgr.max_events_per_sec"));
4935 if (max_events_per_sec < 1) {
4936 max_events_per_sec = 35;
4937 }
4938 } catch (NumberFormatException e) {
4939 }
4940 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
4941 }
4942
4943 /*
4944 * Throttle events to minimize CPU usage when there's a flood of events
4945 * e.g. constant contact with the screen
4946 */
4947 if (action == MotionEvent.ACTION_MOVE) {
4948 long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents;
4949 long now = SystemClock.uptimeMillis();
4950 if (now < nextEventTime) {
4951 try {
4952 Thread.sleep(nextEventTime - now);
4953 } catch (InterruptedException e) {
4954 }
4955 mLastTouchEventTime = nextEventTime;
4956 } else {
4957 mLastTouchEventTime = now;
4958 }
4959 }
4960
Michael Chan53071d62009-05-13 17:29:48 -07004961 if (MEASURE_LATENCY) {
4962 lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano);
4963 }
4964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004965 synchronized(mWindowMap) {
4966 if (qev != null && action == MotionEvent.ACTION_MOVE) {
4967 mKeyWaiter.bindTargetWindowLocked(target,
4968 KeyWaiter.RETURN_PENDING_POINTER, qev);
4969 ev = null;
4970 } else {
4971 if (action == MotionEvent.ACTION_DOWN) {
4972 WindowState out = mKeyWaiter.mOutsideTouchTargets;
4973 if (out != null) {
4974 MotionEvent oev = MotionEvent.obtain(ev);
4975 oev.setAction(MotionEvent.ACTION_OUTSIDE);
4976 do {
4977 final Rect frame = out.mFrame;
4978 oev.offsetLocation(-(float)frame.left, -(float)frame.top);
4979 try {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07004980 out.mClient.dispatchPointer(oev, eventTime, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004981 } catch (android.os.RemoteException e) {
4982 Log.i(TAG, "WINDOW DIED during outside motion dispatch: " + out);
4983 }
4984 oev.offsetLocation((float)frame.left, (float)frame.top);
4985 out = out.mNextOutsideTouch;
4986 } while (out != null);
4987 mKeyWaiter.mOutsideTouchTargets = null;
4988 }
4989 }
4990 final Rect frame = target.mFrame;
4991 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
4992 mKeyWaiter.bindTargetWindowLocked(target);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07004993
4994 // If we are on top of the wallpaper, then the wallpaper also
4995 // gets to see this movement.
4996 if (mWallpaperTarget == target) {
4997 sendPointerToWallpaperLocked(target, ev, eventTime);
4998 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004999 }
5000 }
Romain Guy06882f82009-06-10 13:36:04 -07005001
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005002 // finally offset the event to the target's coordinate system and
5003 // dispatch the event.
5004 try {
5005 if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
5006 Log.v(TAG, "Delivering pointer " + qev + " to " + target);
5007 }
Michael Chan53071d62009-05-13 17:29:48 -07005008
5009 if (MEASURE_LATENCY) {
5010 lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
5011 }
5012
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005013 target.mClient.dispatchPointer(ev, eventTime, true);
Michael Chan53071d62009-05-13 17:29:48 -07005014
5015 if (MEASURE_LATENCY) {
5016 lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
5017 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07005018 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005019 } catch (android.os.RemoteException e) {
5020 Log.i(TAG, "WINDOW DIED during motion dispatch: " + target);
5021 mKeyWaiter.mMotionTarget = null;
5022 try {
5023 removeWindow(target.mSession, target.mClient);
5024 } catch (java.util.NoSuchElementException ex) {
5025 // This will happen if the window has already been
5026 // removed.
5027 }
5028 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07005029 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005030 }
Romain Guy06882f82009-06-10 13:36:04 -07005031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005032 /**
5033 * @return Returns true if event was dispatched, false if it was dropped for any reason
5034 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005035 private int dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005036 if (DEBUG_INPUT) Log.v(
5037 TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">");
Romain Guy06882f82009-06-10 13:36:04 -07005038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005039 Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005040 ev, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005041 if (focusObj == null) {
5042 Log.w(TAG, "No focus window, dropping trackball: " + ev);
5043 if (qev != null) {
5044 mQueue.recycleEvent(qev);
5045 }
5046 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005047 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005048 }
5049 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5050 if (qev != null) {
5051 mQueue.recycleEvent(qev);
5052 }
5053 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005054 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005055 }
Romain Guy06882f82009-06-10 13:36:04 -07005056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005057 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07005058
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005059 if (uid != 0 && uid != focus.mSession.mUid) {
5060 if (mContext.checkPermission(
5061 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5062 != PackageManager.PERMISSION_GRANTED) {
5063 Log.w(TAG, "Permission denied: injecting key event from pid "
5064 + pid + " uid " + uid + " to window " + focus
5065 + " owned by uid " + focus.mSession.mUid);
5066 if (qev != null) {
5067 mQueue.recycleEvent(qev);
5068 }
5069 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005070 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005071 }
5072 }
Romain Guy06882f82009-06-10 13:36:04 -07005073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 final long eventTime = ev.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07005075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005076 synchronized(mWindowMap) {
5077 if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) {
5078 mKeyWaiter.bindTargetWindowLocked(focus,
5079 KeyWaiter.RETURN_PENDING_TRACKBALL, qev);
5080 // We don't deliver movement events to the client, we hold
5081 // them and wait for them to call back.
5082 ev = null;
5083 } else {
5084 mKeyWaiter.bindTargetWindowLocked(focus);
5085 }
5086 }
Romain Guy06882f82009-06-10 13:36:04 -07005087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005088 try {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005089 focus.mClient.dispatchTrackball(ev, eventTime, true);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005090 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005091 } catch (android.os.RemoteException e) {
5092 Log.i(TAG, "WINDOW DIED during key dispatch: " + focus);
5093 try {
5094 removeWindow(focus.mSession, focus.mClient);
5095 } catch (java.util.NoSuchElementException ex) {
5096 // This will happen if the window has already been
5097 // removed.
5098 }
5099 }
Romain Guy06882f82009-06-10 13:36:04 -07005100
Dianne Hackborncfaef692009-06-15 14:24:44 -07005101 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 }
Romain Guy06882f82009-06-10 13:36:04 -07005103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005104 /**
5105 * @return Returns true if event was dispatched, false if it was dropped for any reason
5106 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005107 private int dispatchKey(KeyEvent event, int pid, int uid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005108 if (DEBUG_INPUT) Log.v(TAG, "Dispatch key: " + event);
5109
5110 Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005111 null, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 if (focusObj == null) {
5113 Log.w(TAG, "No focus window, dropping: " + event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005114 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005115 }
5116 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005117 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005118 }
Romain Guy06882f82009-06-10 13:36:04 -07005119
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07005120 // Okay we have finished waiting for the last event to be processed.
5121 // First off, if this is a repeat event, check to see if there is
5122 // a corresponding up event in the queue. If there is, we will
5123 // just drop the repeat, because it makes no sense to repeat after
5124 // the user has released a key. (This is especially important for
5125 // long presses.)
5126 if (event.getRepeatCount() > 0 && mQueue.hasKeyUpEvent(event)) {
5127 return INJECT_SUCCEEDED;
5128 }
5129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005130 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07005131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005132 if (DEBUG_INPUT) Log.v(
5133 TAG, "Dispatching to " + focus + ": " + event);
5134
5135 if (uid != 0 && uid != focus.mSession.mUid) {
5136 if (mContext.checkPermission(
5137 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5138 != PackageManager.PERMISSION_GRANTED) {
5139 Log.w(TAG, "Permission denied: injecting key event from pid "
5140 + pid + " uid " + uid + " to window " + focus
5141 + " owned by uid " + focus.mSession.mUid);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005142 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005143 }
5144 }
Romain Guy06882f82009-06-10 13:36:04 -07005145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005146 synchronized(mWindowMap) {
5147 mKeyWaiter.bindTargetWindowLocked(focus);
5148 }
5149
5150 // NOSHIP extra state logging
5151 mKeyWaiter.recordDispatchState(event, focus);
5152 // END NOSHIP
Romain Guy06882f82009-06-10 13:36:04 -07005153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005154 try {
5155 if (DEBUG_INPUT || DEBUG_FOCUS) {
5156 Log.v(TAG, "Delivering key " + event.getKeyCode()
5157 + " to " + focus);
5158 }
5159 focus.mClient.dispatchKey(event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005160 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005161 } catch (android.os.RemoteException e) {
5162 Log.i(TAG, "WINDOW DIED during key dispatch: " + focus);
5163 try {
5164 removeWindow(focus.mSession, focus.mClient);
5165 } catch (java.util.NoSuchElementException ex) {
5166 // This will happen if the window has already been
5167 // removed.
5168 }
5169 }
Romain Guy06882f82009-06-10 13:36:04 -07005170
Dianne Hackborncfaef692009-06-15 14:24:44 -07005171 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005172 }
Romain Guy06882f82009-06-10 13:36:04 -07005173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005174 public void pauseKeyDispatching(IBinder _token) {
5175 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5176 "pauseKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005177 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005178 }
5179
5180 synchronized (mWindowMap) {
5181 WindowToken token = mTokenMap.get(_token);
5182 if (token != null) {
5183 mKeyWaiter.pauseDispatchingLocked(token);
5184 }
5185 }
5186 }
5187
5188 public void resumeKeyDispatching(IBinder _token) {
5189 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5190 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005191 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005192 }
5193
5194 synchronized (mWindowMap) {
5195 WindowToken token = mTokenMap.get(_token);
5196 if (token != null) {
5197 mKeyWaiter.resumeDispatchingLocked(token);
5198 }
5199 }
5200 }
5201
5202 public void setEventDispatching(boolean enabled) {
5203 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5204 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005205 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005206 }
5207
5208 synchronized (mWindowMap) {
5209 mKeyWaiter.setEventDispatchingLocked(enabled);
5210 }
5211 }
Romain Guy06882f82009-06-10 13:36:04 -07005212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005213 /**
5214 * Injects a keystroke event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005215 *
5216 * @param ev A motion event describing the keystroke action. (Be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005217 * {@link SystemClock#uptimeMillis()} as the timebase.)
5218 * @param sync If true, wait for the event to be completed before returning to the caller.
5219 * @return Returns true if event was dispatched, false if it was dropped for any reason
5220 */
5221 public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
5222 long downTime = ev.getDownTime();
5223 long eventTime = ev.getEventTime();
5224
5225 int action = ev.getAction();
5226 int code = ev.getKeyCode();
5227 int repeatCount = ev.getRepeatCount();
5228 int metaState = ev.getMetaState();
5229 int deviceId = ev.getDeviceId();
5230 int scancode = ev.getScanCode();
5231
5232 if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
5233 if (downTime == 0) downTime = eventTime;
5234
5235 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
The Android Open Source Project10592532009-03-18 17:39:46 -07005236 deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005237
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005238 final int pid = Binder.getCallingPid();
5239 final int uid = Binder.getCallingUid();
5240 final long ident = Binder.clearCallingIdentity();
5241 final int result = dispatchKey(newEvent, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005242 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005243 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005244 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005245 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005246 switch (result) {
5247 case INJECT_NO_PERMISSION:
5248 throw new SecurityException(
5249 "Injecting to another application requires INJECT_EVENT permission");
5250 case INJECT_SUCCEEDED:
5251 return true;
5252 }
5253 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005254 }
5255
5256 /**
5257 * Inject a pointer (touch) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005258 *
5259 * @param ev A motion event describing the pointer (touch) action. (As noted in
5260 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005261 * {@link SystemClock#uptimeMillis()} as the timebase.)
5262 * @param sync If true, wait for the event to be completed before returning to the caller.
5263 * @return Returns true if event was dispatched, false if it was dropped for any reason
5264 */
5265 public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005266 final int pid = Binder.getCallingPid();
5267 final int uid = Binder.getCallingUid();
5268 final long ident = Binder.clearCallingIdentity();
5269 final int result = dispatchPointer(null, ev, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005270 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005271 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005272 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005273 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005274 switch (result) {
5275 case INJECT_NO_PERMISSION:
5276 throw new SecurityException(
5277 "Injecting to another application requires INJECT_EVENT permission");
5278 case INJECT_SUCCEEDED:
5279 return true;
5280 }
5281 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005282 }
Romain Guy06882f82009-06-10 13:36:04 -07005283
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005284 /**
5285 * Inject a trackball (navigation device) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005286 *
5287 * @param ev A motion event describing the trackball action. (As noted in
5288 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005289 * {@link SystemClock#uptimeMillis()} as the timebase.)
5290 * @param sync If true, wait for the event to be completed before returning to the caller.
5291 * @return Returns true if event was dispatched, false if it was dropped for any reason
5292 */
5293 public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005294 final int pid = Binder.getCallingPid();
5295 final int uid = Binder.getCallingUid();
5296 final long ident = Binder.clearCallingIdentity();
5297 final int result = dispatchTrackball(null, ev, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005298 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005299 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005300 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005301 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005302 switch (result) {
5303 case INJECT_NO_PERMISSION:
5304 throw new SecurityException(
5305 "Injecting to another application requires INJECT_EVENT permission");
5306 case INJECT_SUCCEEDED:
5307 return true;
5308 }
5309 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005310 }
Romain Guy06882f82009-06-10 13:36:04 -07005311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 private WindowState getFocusedWindow() {
5313 synchronized (mWindowMap) {
5314 return getFocusedWindowLocked();
5315 }
5316 }
5317
5318 private WindowState getFocusedWindowLocked() {
5319 return mCurrentFocus;
5320 }
Romain Guy06882f82009-06-10 13:36:04 -07005321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005322 /**
5323 * This class holds the state for dispatching key events. This state
5324 * is protected by the KeyWaiter instance, NOT by the window lock. You
5325 * can be holding the main window lock while acquire the KeyWaiter lock,
5326 * but not the other way around.
5327 */
5328 final class KeyWaiter {
5329 // NOSHIP debugging
5330 public class DispatchState {
5331 private KeyEvent event;
5332 private WindowState focus;
5333 private long time;
5334 private WindowState lastWin;
5335 private IBinder lastBinder;
5336 private boolean finished;
5337 private boolean gotFirstWindow;
5338 private boolean eventDispatching;
5339 private long timeToSwitch;
5340 private boolean wasFrozen;
5341 private boolean focusPaused;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005342 private WindowState curFocus;
Romain Guy06882f82009-06-10 13:36:04 -07005343
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005344 DispatchState(KeyEvent theEvent, WindowState theFocus) {
5345 focus = theFocus;
5346 event = theEvent;
5347 time = System.currentTimeMillis();
5348 // snapshot KeyWaiter state
5349 lastWin = mLastWin;
5350 lastBinder = mLastBinder;
5351 finished = mFinished;
5352 gotFirstWindow = mGotFirstWindow;
5353 eventDispatching = mEventDispatching;
5354 timeToSwitch = mTimeToSwitch;
5355 wasFrozen = mWasFrozen;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005356 curFocus = mCurrentFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 // cache the paused state at ctor time as well
5358 if (theFocus == null || theFocus.mToken == null) {
5359 Log.i(TAG, "focus " + theFocus + " mToken is null at event dispatch!");
5360 focusPaused = false;
5361 } else {
5362 focusPaused = theFocus.mToken.paused;
5363 }
5364 }
Romain Guy06882f82009-06-10 13:36:04 -07005365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005366 public String toString() {
5367 return "{{" + event + " to " + focus + " @ " + time
5368 + " lw=" + lastWin + " lb=" + lastBinder
5369 + " fin=" + finished + " gfw=" + gotFirstWindow
5370 + " ed=" + eventDispatching + " tts=" + timeToSwitch
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005371 + " wf=" + wasFrozen + " fp=" + focusPaused
5372 + " mcf=" + mCurrentFocus + "}}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005373 }
5374 };
5375 private DispatchState mDispatchState = null;
5376 public void recordDispatchState(KeyEvent theEvent, WindowState theFocus) {
5377 mDispatchState = new DispatchState(theEvent, theFocus);
5378 }
5379 // END NOSHIP
5380
5381 public static final int RETURN_NOTHING = 0;
5382 public static final int RETURN_PENDING_POINTER = 1;
5383 public static final int RETURN_PENDING_TRACKBALL = 2;
Romain Guy06882f82009-06-10 13:36:04 -07005384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005385 final Object SKIP_TARGET_TOKEN = new Object();
5386 final Object CONSUMED_EVENT_TOKEN = new Object();
Romain Guy06882f82009-06-10 13:36:04 -07005387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005388 private WindowState mLastWin = null;
5389 private IBinder mLastBinder = null;
5390 private boolean mFinished = true;
5391 private boolean mGotFirstWindow = false;
5392 private boolean mEventDispatching = true;
5393 private long mTimeToSwitch = 0;
5394 /* package */ boolean mWasFrozen = false;
Romain Guy06882f82009-06-10 13:36:04 -07005395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005396 // Target of Motion events
5397 WindowState mMotionTarget;
Romain Guy06882f82009-06-10 13:36:04 -07005398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005399 // Windows above the target who would like to receive an "outside"
5400 // touch event for any down events outside of them.
5401 WindowState mOutsideTouchTargets;
5402
5403 /**
5404 * Wait for the last event dispatch to complete, then find the next
5405 * target that should receive the given event and wait for that one
5406 * to be ready to receive it.
5407 */
5408 Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev,
5409 MotionEvent nextMotion, boolean isPointerEvent,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005410 boolean failIfTimeout, int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005411 long startTime = SystemClock.uptimeMillis();
5412 long keyDispatchingTimeout = 5 * 1000;
5413 long waitedFor = 0;
5414
5415 while (true) {
5416 // Figure out which window we care about. It is either the
5417 // last window we are waiting to have process the event or,
5418 // if none, then the next window we think the event should go
5419 // to. Note: we retrieve mLastWin outside of the lock, so
5420 // it may change before we lock. Thus we must check it again.
5421 WindowState targetWin = mLastWin;
5422 boolean targetIsNew = targetWin == null;
5423 if (DEBUG_INPUT) Log.v(
5424 TAG, "waitForLastKey: mFinished=" + mFinished +
5425 ", mLastWin=" + mLastWin);
5426 if (targetIsNew) {
5427 Object target = findTargetWindow(nextKey, qev, nextMotion,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005428 isPointerEvent, callingPid, callingUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 if (target == SKIP_TARGET_TOKEN) {
5430 // The user has pressed a special key, and we are
5431 // dropping all pending events before it.
5432 if (DEBUG_INPUT) Log.v(TAG, "Skipping: " + nextKey
5433 + " " + nextMotion);
5434 return null;
5435 }
5436 if (target == CONSUMED_EVENT_TOKEN) {
5437 if (DEBUG_INPUT) Log.v(TAG, "Consumed: " + nextKey
5438 + " " + nextMotion);
5439 return target;
5440 }
5441 targetWin = (WindowState)target;
5442 }
Romain Guy06882f82009-06-10 13:36:04 -07005443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005444 AppWindowToken targetApp = null;
Romain Guy06882f82009-06-10 13:36:04 -07005445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005446 // Now: is it okay to send the next event to this window?
5447 synchronized (this) {
5448 // First: did we come here based on the last window not
5449 // being null, but it changed by the time we got here?
5450 // If so, try again.
5451 if (!targetIsNew && mLastWin == null) {
5452 continue;
5453 }
Romain Guy06882f82009-06-10 13:36:04 -07005454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005455 // We never dispatch events if not finished with the
5456 // last one, or the display is frozen.
5457 if (mFinished && !mDisplayFrozen) {
5458 // If event dispatching is disabled, then we
5459 // just consume the events.
5460 if (!mEventDispatching) {
5461 if (DEBUG_INPUT) Log.v(TAG,
5462 "Skipping event; dispatching disabled: "
5463 + nextKey + " " + nextMotion);
5464 return null;
5465 }
5466 if (targetWin != null) {
5467 // If this is a new target, and that target is not
5468 // paused or unresponsive, then all looks good to
5469 // handle the event.
5470 if (targetIsNew && !targetWin.mToken.paused) {
5471 return targetWin;
5472 }
Romain Guy06882f82009-06-10 13:36:04 -07005473
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 // If we didn't find a target window, and there is no
5475 // focused app window, then just eat the events.
5476 } else if (mFocusedApp == null) {
5477 if (DEBUG_INPUT) Log.v(TAG,
5478 "Skipping event; no focused app: "
5479 + nextKey + " " + nextMotion);
5480 return null;
5481 }
5482 }
Romain Guy06882f82009-06-10 13:36:04 -07005483
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005484 if (DEBUG_INPUT) Log.v(
5485 TAG, "Waiting for last key in " + mLastBinder
5486 + " target=" + targetWin
5487 + " mFinished=" + mFinished
5488 + " mDisplayFrozen=" + mDisplayFrozen
5489 + " targetIsNew=" + targetIsNew
5490 + " paused="
5491 + (targetWin != null ? targetWin.mToken.paused : false)
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005492 + " mFocusedApp=" + mFocusedApp
5493 + " mCurrentFocus=" + mCurrentFocus);
Romain Guy06882f82009-06-10 13:36:04 -07005494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005495 targetApp = targetWin != null
5496 ? targetWin.mAppToken : mFocusedApp;
Romain Guy06882f82009-06-10 13:36:04 -07005497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 long curTimeout = keyDispatchingTimeout;
5499 if (mTimeToSwitch != 0) {
5500 long now = SystemClock.uptimeMillis();
5501 if (mTimeToSwitch <= now) {
5502 // If an app switch key has been pressed, and we have
5503 // waited too long for the current app to finish
5504 // processing keys, then wait no more!
5505 doFinishedKeyLocked(true);
5506 continue;
5507 }
5508 long switchTimeout = mTimeToSwitch - now;
5509 if (curTimeout > switchTimeout) {
5510 curTimeout = switchTimeout;
5511 }
5512 }
Romain Guy06882f82009-06-10 13:36:04 -07005513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005514 try {
5515 // after that continue
5516 // processing keys, so we don't get stuck.
5517 if (DEBUG_INPUT) Log.v(
5518 TAG, "Waiting for key dispatch: " + curTimeout);
5519 wait(curTimeout);
5520 if (DEBUG_INPUT) Log.v(TAG, "Finished waiting @"
5521 + SystemClock.uptimeMillis() + " startTime="
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005522 + startTime + " switchTime=" + mTimeToSwitch
5523 + " target=" + targetWin + " mLW=" + mLastWin
5524 + " mLB=" + mLastBinder + " fin=" + mFinished
5525 + " mCurrentFocus=" + mCurrentFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526 } catch (InterruptedException e) {
5527 }
5528 }
5529
5530 // If we were frozen during configuration change, restart the
5531 // timeout checks from now; otherwise look at whether we timed
5532 // out before awakening.
5533 if (mWasFrozen) {
5534 waitedFor = 0;
5535 mWasFrozen = false;
5536 } else {
5537 waitedFor = SystemClock.uptimeMillis() - startTime;
5538 }
5539
5540 if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) {
5541 IApplicationToken at = null;
5542 synchronized (this) {
5543 Log.w(TAG, "Key dispatching timed out sending to " +
5544 (targetWin != null ? targetWin.mAttrs.getTitle()
5545 : "<null>"));
5546 // NOSHIP debugging
5547 Log.w(TAG, "Dispatch state: " + mDispatchState);
5548 Log.w(TAG, "Current state: " + new DispatchState(nextKey, targetWin));
5549 // END NOSHIP
5550 //dump();
5551 if (targetWin != null) {
5552 at = targetWin.getAppToken();
5553 } else if (targetApp != null) {
5554 at = targetApp.appToken;
5555 }
5556 }
5557
5558 boolean abort = true;
5559 if (at != null) {
5560 try {
5561 long timeout = at.getKeyDispatchingTimeout();
5562 if (timeout > waitedFor) {
5563 // we did not wait the proper amount of time for this application.
5564 // set the timeout to be the real timeout and wait again.
5565 keyDispatchingTimeout = timeout - waitedFor;
5566 continue;
5567 } else {
5568 abort = at.keyDispatchingTimedOut();
5569 }
5570 } catch (RemoteException ex) {
5571 }
5572 }
5573
5574 synchronized (this) {
5575 if (abort && (mLastWin == targetWin || targetWin == null)) {
5576 mFinished = true;
Romain Guy06882f82009-06-10 13:36:04 -07005577 if (mLastWin != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005578 if (DEBUG_INPUT) Log.v(TAG,
5579 "Window " + mLastWin +
5580 " timed out on key input");
5581 if (mLastWin.mToken.paused) {
5582 Log.w(TAG, "Un-pausing dispatching to this window");
5583 mLastWin.mToken.paused = false;
5584 }
5585 }
5586 if (mMotionTarget == targetWin) {
5587 mMotionTarget = null;
5588 }
5589 mLastWin = null;
5590 mLastBinder = null;
5591 if (failIfTimeout || targetWin == null) {
5592 return null;
5593 }
5594 } else {
5595 Log.w(TAG, "Continuing to wait for key to be dispatched");
5596 startTime = SystemClock.uptimeMillis();
5597 }
5598 }
5599 }
5600 }
5601 }
Romain Guy06882f82009-06-10 13:36:04 -07005602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005603 Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005604 MotionEvent nextMotion, boolean isPointerEvent,
5605 int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005606 mOutsideTouchTargets = null;
Romain Guy06882f82009-06-10 13:36:04 -07005607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005608 if (nextKey != null) {
5609 // Find the target window for a normal key event.
5610 final int keycode = nextKey.getKeyCode();
5611 final int repeatCount = nextKey.getRepeatCount();
5612 final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP;
5613 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode);
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005615 if (!dispatch) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005616 if (callingUid == 0 ||
5617 mContext.checkPermission(
5618 android.Manifest.permission.INJECT_EVENTS,
5619 callingPid, callingUid)
5620 == PackageManager.PERMISSION_GRANTED) {
5621 mPolicy.interceptKeyTi(null, keycode,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07005622 nextKey.getMetaState(), down, repeatCount,
5623 nextKey.getFlags());
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005624 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005625 Log.w(TAG, "Event timeout during app switch: dropping "
5626 + nextKey);
5627 return SKIP_TARGET_TOKEN;
5628 }
Romain Guy06882f82009-06-10 13:36:04 -07005629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005630 // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")");
Romain Guy06882f82009-06-10 13:36:04 -07005631
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005632 WindowState focus = null;
5633 synchronized(mWindowMap) {
5634 focus = getFocusedWindowLocked();
5635 }
Romain Guy06882f82009-06-10 13:36:04 -07005636
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005637 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
Romain Guy06882f82009-06-10 13:36:04 -07005638
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005639 if (callingUid == 0 ||
5640 (focus != null && callingUid == focus.mSession.mUid) ||
5641 mContext.checkPermission(
5642 android.Manifest.permission.INJECT_EVENTS,
5643 callingPid, callingUid)
5644 == PackageManager.PERMISSION_GRANTED) {
5645 if (mPolicy.interceptKeyTi(focus,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07005646 keycode, nextKey.getMetaState(), down, repeatCount,
5647 nextKey.getFlags())) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005648 return CONSUMED_EVENT_TOKEN;
5649 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005650 }
Romain Guy06882f82009-06-10 13:36:04 -07005651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005652 return focus;
Romain Guy06882f82009-06-10 13:36:04 -07005653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005654 } else if (!isPointerEvent) {
5655 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1);
5656 if (!dispatch) {
5657 Log.w(TAG, "Event timeout during app switch: dropping trackball "
5658 + nextMotion);
5659 return SKIP_TARGET_TOKEN;
5660 }
Romain Guy06882f82009-06-10 13:36:04 -07005661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005662 WindowState focus = null;
5663 synchronized(mWindowMap) {
5664 focus = getFocusedWindowLocked();
5665 }
Romain Guy06882f82009-06-10 13:36:04 -07005666
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
5668 return focus;
5669 }
Romain Guy06882f82009-06-10 13:36:04 -07005670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005671 if (nextMotion == null) {
5672 return SKIP_TARGET_TOKEN;
5673 }
Romain Guy06882f82009-06-10 13:36:04 -07005674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005675 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(
5676 KeyEvent.KEYCODE_UNKNOWN);
5677 if (!dispatch) {
5678 Log.w(TAG, "Event timeout during app switch: dropping pointer "
5679 + nextMotion);
5680 return SKIP_TARGET_TOKEN;
5681 }
Romain Guy06882f82009-06-10 13:36:04 -07005682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005683 // Find the target window for a pointer event.
5684 int action = nextMotion.getAction();
5685 final float xf = nextMotion.getX();
5686 final float yf = nextMotion.getY();
5687 final long eventTime = nextMotion.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07005688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005689 final boolean screenWasOff = qev != null
5690 && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07005691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005692 WindowState target = null;
Romain Guy06882f82009-06-10 13:36:04 -07005693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005694 synchronized(mWindowMap) {
5695 synchronized (this) {
5696 if (action == MotionEvent.ACTION_DOWN) {
5697 if (mMotionTarget != null) {
5698 // this is weird, we got a pen down, but we thought it was
5699 // already down!
5700 // XXX: We should probably send an ACTION_UP to the current
5701 // target.
5702 Log.w(TAG, "Pointer down received while already down in: "
5703 + mMotionTarget);
5704 mMotionTarget = null;
5705 }
Romain Guy06882f82009-06-10 13:36:04 -07005706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005707 // ACTION_DOWN is special, because we need to lock next events to
5708 // the window we'll land onto.
5709 final int x = (int)xf;
5710 final int y = (int)yf;
Romain Guy06882f82009-06-10 13:36:04 -07005711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005712 final ArrayList windows = mWindows;
5713 final int N = windows.size();
5714 WindowState topErrWindow = null;
5715 final Rect tmpRect = mTempRect;
5716 for (int i=N-1; i>=0; i--) {
5717 WindowState child = (WindowState)windows.get(i);
5718 //Log.i(TAG, "Checking dispatch to: " + child);
5719 final int flags = child.mAttrs.flags;
5720 if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
5721 if (topErrWindow == null) {
5722 topErrWindow = child;
5723 }
5724 }
5725 if (!child.isVisibleLw()) {
5726 //Log.i(TAG, "Not visible!");
5727 continue;
5728 }
5729 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
5730 //Log.i(TAG, "Not touchable!");
5731 if ((flags & WindowManager.LayoutParams
5732 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5733 child.mNextOutsideTouch = mOutsideTouchTargets;
5734 mOutsideTouchTargets = child;
5735 }
5736 continue;
5737 }
5738 tmpRect.set(child.mFrame);
5739 if (child.mTouchableInsets == ViewTreeObserver
5740 .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
5741 // The touch is inside of the window if it is
5742 // inside the frame, AND the content part of that
5743 // frame that was given by the application.
5744 tmpRect.left += child.mGivenContentInsets.left;
5745 tmpRect.top += child.mGivenContentInsets.top;
5746 tmpRect.right -= child.mGivenContentInsets.right;
5747 tmpRect.bottom -= child.mGivenContentInsets.bottom;
5748 } else if (child.mTouchableInsets == ViewTreeObserver
5749 .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
5750 // The touch is inside of the window if it is
5751 // inside the frame, AND the visible part of that
5752 // frame that was given by the application.
5753 tmpRect.left += child.mGivenVisibleInsets.left;
5754 tmpRect.top += child.mGivenVisibleInsets.top;
5755 tmpRect.right -= child.mGivenVisibleInsets.right;
5756 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
5757 }
5758 final int touchFlags = flags &
5759 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5760 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
5761 if (tmpRect.contains(x, y) || touchFlags == 0) {
5762 //Log.i(TAG, "Using this target!");
5763 if (!screenWasOff || (flags &
5764 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
5765 mMotionTarget = child;
5766 } else {
5767 //Log.i(TAG, "Waking, skip!");
5768 mMotionTarget = null;
5769 }
5770 break;
5771 }
Romain Guy06882f82009-06-10 13:36:04 -07005772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005773 if ((flags & WindowManager.LayoutParams
5774 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5775 child.mNextOutsideTouch = mOutsideTouchTargets;
5776 mOutsideTouchTargets = child;
5777 //Log.i(TAG, "Adding to outside target list: " + child);
5778 }
5779 }
5780
5781 // if there's an error window but it's not accepting
5782 // focus (typically because it is not yet visible) just
5783 // wait for it -- any other focused window may in fact
5784 // be in ANR state.
5785 if (topErrWindow != null && mMotionTarget != topErrWindow) {
5786 mMotionTarget = null;
5787 }
5788 }
Romain Guy06882f82009-06-10 13:36:04 -07005789
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005790 target = mMotionTarget;
5791 }
5792 }
Romain Guy06882f82009-06-10 13:36:04 -07005793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005794 wakeupIfNeeded(target, eventType(nextMotion));
Romain Guy06882f82009-06-10 13:36:04 -07005795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005796 // Pointer events are a little different -- if there isn't a
5797 // target found for any event, then just drop it.
5798 return target != null ? target : SKIP_TARGET_TOKEN;
5799 }
Romain Guy06882f82009-06-10 13:36:04 -07005800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005801 boolean checkShouldDispatchKey(int keycode) {
5802 synchronized (this) {
5803 if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) {
5804 mTimeToSwitch = 0;
5805 return true;
5806 }
5807 if (mTimeToSwitch != 0
5808 && mTimeToSwitch < SystemClock.uptimeMillis()) {
5809 return false;
5810 }
5811 return true;
5812 }
5813 }
Romain Guy06882f82009-06-10 13:36:04 -07005814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005815 void bindTargetWindowLocked(WindowState win,
5816 int pendingWhat, QueuedEvent pendingMotion) {
5817 synchronized (this) {
5818 bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion);
5819 }
5820 }
Romain Guy06882f82009-06-10 13:36:04 -07005821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 void bindTargetWindowLocked(WindowState win) {
5823 synchronized (this) {
5824 bindTargetWindowLockedLocked(win, RETURN_NOTHING, null);
5825 }
5826 }
5827
5828 void bindTargetWindowLockedLocked(WindowState win,
5829 int pendingWhat, QueuedEvent pendingMotion) {
5830 mLastWin = win;
5831 mLastBinder = win.mClient.asBinder();
5832 mFinished = false;
5833 if (pendingMotion != null) {
5834 final Session s = win.mSession;
5835 if (pendingWhat == RETURN_PENDING_POINTER) {
5836 releasePendingPointerLocked(s);
5837 s.mPendingPointerMove = pendingMotion;
5838 s.mPendingPointerWindow = win;
Romain Guy06882f82009-06-10 13:36:04 -07005839 if (DEBUG_INPUT) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 "bindTargetToWindow " + s.mPendingPointerMove);
5841 } else if (pendingWhat == RETURN_PENDING_TRACKBALL) {
5842 releasePendingTrackballLocked(s);
5843 s.mPendingTrackballMove = pendingMotion;
5844 s.mPendingTrackballWindow = win;
5845 }
5846 }
5847 }
Romain Guy06882f82009-06-10 13:36:04 -07005848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005849 void releasePendingPointerLocked(Session s) {
5850 if (DEBUG_INPUT) Log.v(TAG,
5851 "releasePendingPointer " + s.mPendingPointerMove);
5852 if (s.mPendingPointerMove != null) {
5853 mQueue.recycleEvent(s.mPendingPointerMove);
5854 s.mPendingPointerMove = null;
5855 }
5856 }
Romain Guy06882f82009-06-10 13:36:04 -07005857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 void releasePendingTrackballLocked(Session s) {
5859 if (s.mPendingTrackballMove != null) {
5860 mQueue.recycleEvent(s.mPendingTrackballMove);
5861 s.mPendingTrackballMove = null;
5862 }
5863 }
Romain Guy06882f82009-06-10 13:36:04 -07005864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 MotionEvent finishedKey(Session session, IWindow client, boolean force,
5866 int returnWhat) {
5867 if (DEBUG_INPUT) Log.v(
5868 TAG, "finishedKey: client=" + client + ", force=" + force);
5869
5870 if (client == null) {
5871 return null;
5872 }
5873
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005874 MotionEvent res = null;
5875 QueuedEvent qev = null;
5876 WindowState win = null;
5877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005878 synchronized (this) {
5879 if (DEBUG_INPUT) Log.v(
5880 TAG, "finishedKey: client=" + client.asBinder()
5881 + ", force=" + force + ", last=" + mLastBinder
5882 + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
5883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005884 if (returnWhat == RETURN_PENDING_POINTER) {
5885 qev = session.mPendingPointerMove;
5886 win = session.mPendingPointerWindow;
5887 session.mPendingPointerMove = null;
5888 session.mPendingPointerWindow = null;
5889 } else if (returnWhat == RETURN_PENDING_TRACKBALL) {
5890 qev = session.mPendingTrackballMove;
5891 win = session.mPendingTrackballWindow;
5892 session.mPendingTrackballMove = null;
5893 session.mPendingTrackballWindow = null;
5894 }
Romain Guy06882f82009-06-10 13:36:04 -07005895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005896 if (mLastBinder == client.asBinder()) {
5897 if (DEBUG_INPUT) Log.v(
5898 TAG, "finishedKey: last paused="
5899 + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
5900 if (mLastWin != null && (!mLastWin.mToken.paused || force
5901 || !mEventDispatching)) {
5902 doFinishedKeyLocked(false);
5903 } else {
5904 // Make sure to wake up anyone currently waiting to
5905 // dispatch a key, so they can re-evaluate their
5906 // current situation.
5907 mFinished = true;
5908 notifyAll();
5909 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005910 }
Romain Guy06882f82009-06-10 13:36:04 -07005911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005912 if (qev != null) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005913 res = (MotionEvent)qev.event;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005914 if (DEBUG_INPUT) Log.v(TAG,
5915 "Returning pending motion: " + res);
5916 mQueue.recycleEvent(qev);
5917 if (win != null && returnWhat == RETURN_PENDING_POINTER) {
5918 res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
5919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005920 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005921 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005922
5923 if (res != null && returnWhat == RETURN_PENDING_POINTER) {
5924 synchronized (mWindowMap) {
5925 if (mWallpaperTarget == win) {
5926 sendPointerToWallpaperLocked(win, res, res.getEventTime());
5927 }
5928 }
5929 }
5930
5931 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005932 }
5933
5934 void tickle() {
5935 synchronized (this) {
5936 notifyAll();
5937 }
5938 }
Romain Guy06882f82009-06-10 13:36:04 -07005939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005940 void handleNewWindowLocked(WindowState newWindow) {
5941 if (!newWindow.canReceiveKeys()) {
5942 return;
5943 }
5944 synchronized (this) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005945 if (DEBUG_INPUT) Log.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005946 TAG, "New key dispatch window: win="
5947 + newWindow.mClient.asBinder()
5948 + ", last=" + mLastBinder
5949 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
5950 + "), finished=" + mFinished + ", paused="
5951 + newWindow.mToken.paused);
5952
5953 // Displaying a window implicitly causes dispatching to
5954 // be unpaused. (This is to protect against bugs if someone
5955 // pauses dispatching but forgets to resume.)
5956 newWindow.mToken.paused = false;
5957
5958 mGotFirstWindow = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005959
5960 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
5961 if (DEBUG_INPUT) Log.v(TAG,
5962 "New SYSTEM_ERROR window; resetting state");
5963 mLastWin = null;
5964 mLastBinder = null;
5965 mMotionTarget = null;
5966 mFinished = true;
5967 } else if (mLastWin != null) {
5968 // If the new window is above the window we are
5969 // waiting on, then stop waiting and let key dispatching
5970 // start on the new guy.
5971 if (DEBUG_INPUT) Log.v(
5972 TAG, "Last win layer=" + mLastWin.mLayer
5973 + ", new win layer=" + newWindow.mLayer);
5974 if (newWindow.mLayer >= mLastWin.mLayer) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005975 // The new window is above the old; finish pending input to the last
5976 // window and start directing it to the new one.
5977 mLastWin.mToken.paused = false;
5978 doFinishedKeyLocked(true); // does a notifyAll()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 }
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005980 // Either the new window is lower, so there is no need to wake key waiters,
5981 // or we just finished key input to the previous window, which implicitly
5982 // notified the key waiters. In both cases, we don't need to issue the
5983 // notification here.
5984 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005985 }
5986
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005987 // Now that we've put a new window state in place, make the event waiter
5988 // take notice and retarget its attentions.
5989 notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005990 }
5991 }
5992
5993 void pauseDispatchingLocked(WindowToken token) {
5994 synchronized (this)
5995 {
5996 if (DEBUG_INPUT) Log.v(TAG, "Pausing WindowToken " + token);
5997 token.paused = true;
5998
5999 /*
6000 if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) {
6001 mPaused = true;
6002 } else {
6003 if (mLastWin == null) {
Dave Bortcfe65242009-04-09 14:51:04 -07006004 Log.i(TAG, "Key dispatching not paused: no last window.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006005 } else if (mFinished) {
Dave Bortcfe65242009-04-09 14:51:04 -07006006 Log.i(TAG, "Key dispatching not paused: finished last key.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006007 } else {
Dave Bortcfe65242009-04-09 14:51:04 -07006008 Log.i(TAG, "Key dispatching not paused: window in higher layer.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006009 }
6010 }
6011 */
6012 }
6013 }
6014
6015 void resumeDispatchingLocked(WindowToken token) {
6016 synchronized (this) {
6017 if (token.paused) {
6018 if (DEBUG_INPUT) Log.v(
6019 TAG, "Resuming WindowToken " + token
6020 + ", last=" + mLastBinder
6021 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6022 + "), finished=" + mFinished + ", paused="
6023 + token.paused);
6024 token.paused = false;
6025 if (mLastWin != null && mLastWin.mToken == token && mFinished) {
6026 doFinishedKeyLocked(true);
6027 } else {
6028 notifyAll();
6029 }
6030 }
6031 }
6032 }
6033
6034 void setEventDispatchingLocked(boolean enabled) {
6035 synchronized (this) {
6036 mEventDispatching = enabled;
6037 notifyAll();
6038 }
6039 }
Romain Guy06882f82009-06-10 13:36:04 -07006040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006041 void appSwitchComing() {
6042 synchronized (this) {
6043 // Don't wait for more than .5 seconds for app to finish
6044 // processing the pending events.
6045 long now = SystemClock.uptimeMillis() + 500;
6046 if (DEBUG_INPUT) Log.v(TAG, "appSwitchComing: " + now);
6047 if (mTimeToSwitch == 0 || now < mTimeToSwitch) {
6048 mTimeToSwitch = now;
6049 }
6050 notifyAll();
6051 }
6052 }
Romain Guy06882f82009-06-10 13:36:04 -07006053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006054 private final void doFinishedKeyLocked(boolean doRecycle) {
6055 if (mLastWin != null) {
6056 releasePendingPointerLocked(mLastWin.mSession);
6057 releasePendingTrackballLocked(mLastWin.mSession);
6058 }
Romain Guy06882f82009-06-10 13:36:04 -07006059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006060 if (mLastWin == null || !mLastWin.mToken.paused
6061 || !mLastWin.isVisibleLw()) {
6062 // If the current window has been paused, we aren't -really-
6063 // finished... so let the waiters still wait.
6064 mLastWin = null;
6065 mLastBinder = null;
6066 }
6067 mFinished = true;
6068 notifyAll();
6069 }
6070 }
6071
6072 private class KeyQ extends KeyInputQueue
6073 implements KeyInputQueue.FilterCallback {
6074 PowerManager.WakeLock mHoldingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07006075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006076 KeyQ() {
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07006077 super(mContext, WindowManagerService.this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006078 PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
6079 mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
6080 "KEEP_SCREEN_ON_FLAG");
6081 mHoldingScreen.setReferenceCounted(false);
6082 }
6083
6084 @Override
6085 boolean preprocessEvent(InputDevice device, RawInputEvent event) {
6086 if (mPolicy.preprocessInputEventTq(event)) {
6087 return true;
6088 }
Romain Guy06882f82009-06-10 13:36:04 -07006089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 switch (event.type) {
6091 case RawInputEvent.EV_KEY: {
6092 // XXX begin hack
6093 if (DEBUG) {
6094 if (event.keycode == KeyEvent.KEYCODE_G) {
6095 if (event.value != 0) {
6096 // G down
6097 mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
6098 }
6099 return false;
6100 }
6101 if (event.keycode == KeyEvent.KEYCODE_D) {
6102 if (event.value != 0) {
6103 //dump();
6104 }
6105 return false;
6106 }
6107 }
6108 // XXX end hack
Romain Guy06882f82009-06-10 13:36:04 -07006109
Charles Mendis322591c2009-10-29 11:06:59 -07006110 boolean screenIsOff = !mPowerManager.isScreenOn();
6111 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006112 int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
Romain Guy06882f82009-06-10 13:36:04 -07006113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006114 if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) {
6115 mPowerManager.goToSleep(event.when);
6116 }
6117
6118 if (screenIsOff) {
6119 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6120 }
6121 if (screenIsDim) {
6122 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6123 }
6124 if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
6125 mPowerManager.userActivity(event.when, false,
Michael Chane96440f2009-05-06 10:27:36 -07006126 LocalPowerManager.BUTTON_EVENT, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006127 }
Romain Guy06882f82009-06-10 13:36:04 -07006128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006129 if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
6130 if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) {
6131 filterQueue(this);
6132 mKeyWaiter.appSwitchComing();
6133 }
6134 return true;
6135 } else {
6136 return false;
6137 }
6138 }
Romain Guy06882f82009-06-10 13:36:04 -07006139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006140 case RawInputEvent.EV_REL: {
Charles Mendis322591c2009-10-29 11:06:59 -07006141 boolean screenIsOff = !mPowerManager.isScreenOn();
6142 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006143 if (screenIsOff) {
6144 if (!mPolicy.isWakeRelMovementTq(event.deviceId,
6145 device.classes, event)) {
6146 //Log.i(TAG, "dropping because screenIsOff and !isWakeKey");
6147 return false;
6148 }
6149 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6150 }
6151 if (screenIsDim) {
6152 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6153 }
6154 return true;
6155 }
Romain Guy06882f82009-06-10 13:36:04 -07006156
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006157 case RawInputEvent.EV_ABS: {
Charles Mendis322591c2009-10-29 11:06:59 -07006158 boolean screenIsOff = !mPowerManager.isScreenOn();
6159 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006160 if (screenIsOff) {
6161 if (!mPolicy.isWakeAbsMovementTq(event.deviceId,
6162 device.classes, event)) {
6163 //Log.i(TAG, "dropping because screenIsOff and !isWakeKey");
6164 return false;
6165 }
6166 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6167 }
6168 if (screenIsDim) {
6169 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6170 }
6171 return true;
6172 }
Romain Guy06882f82009-06-10 13:36:04 -07006173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006174 default:
6175 return true;
6176 }
6177 }
6178
6179 public int filterEvent(QueuedEvent ev) {
6180 switch (ev.classType) {
6181 case RawInputEvent.CLASS_KEYBOARD:
6182 KeyEvent ke = (KeyEvent)ev.event;
6183 if (mPolicy.isMovementKeyTi(ke.getKeyCode())) {
6184 Log.w(TAG, "Dropping movement key during app switch: "
6185 + ke.getKeyCode() + ", action=" + ke.getAction());
6186 return FILTER_REMOVE;
6187 }
6188 return FILTER_ABORT;
6189 default:
6190 return FILTER_KEEP;
6191 }
6192 }
Romain Guy06882f82009-06-10 13:36:04 -07006193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006194 /**
6195 * Must be called with the main window manager lock held.
6196 */
6197 void setHoldScreenLocked(boolean holding) {
6198 boolean state = mHoldingScreen.isHeld();
6199 if (holding != state) {
6200 if (holding) {
6201 mHoldingScreen.acquire();
6202 } else {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07006203 mPolicy.screenOnStoppedLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006204 mHoldingScreen.release();
6205 }
6206 }
6207 }
Michael Chan53071d62009-05-13 17:29:48 -07006208 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006209
6210 public boolean detectSafeMode() {
6211 mSafeMode = mPolicy.detectSafeMode();
6212 return mSafeMode;
6213 }
Romain Guy06882f82009-06-10 13:36:04 -07006214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 public void systemReady() {
6216 mPolicy.systemReady();
6217 }
Romain Guy06882f82009-06-10 13:36:04 -07006218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006219 private final class InputDispatcherThread extends Thread {
6220 // Time to wait when there is nothing to do: 9999 seconds.
6221 static final int LONG_WAIT=9999*1000;
6222
6223 public InputDispatcherThread() {
6224 super("InputDispatcher");
6225 }
Romain Guy06882f82009-06-10 13:36:04 -07006226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006227 @Override
6228 public void run() {
6229 while (true) {
6230 try {
6231 process();
6232 } catch (Exception e) {
6233 Log.e(TAG, "Exception in input dispatcher", e);
6234 }
6235 }
6236 }
Romain Guy06882f82009-06-10 13:36:04 -07006237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006238 private void process() {
6239 android.os.Process.setThreadPriority(
6240 android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -07006241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006242 // The last key event we saw
6243 KeyEvent lastKey = null;
6244
6245 // Last keydown time for auto-repeating keys
6246 long lastKeyTime = SystemClock.uptimeMillis();
6247 long nextKeyTime = lastKeyTime+LONG_WAIT;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006248 long downTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006249
Romain Guy06882f82009-06-10 13:36:04 -07006250 // How many successive repeats we generated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006251 int keyRepeatCount = 0;
6252
6253 // Need to report that configuration has changed?
6254 boolean configChanged = false;
Romain Guy06882f82009-06-10 13:36:04 -07006255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006256 while (true) {
6257 long curTime = SystemClock.uptimeMillis();
6258
6259 if (DEBUG_INPUT) Log.v(
6260 TAG, "Waiting for next key: now=" + curTime
6261 + ", repeat @ " + nextKeyTime);
6262
6263 // Retrieve next event, waiting only as long as the next
6264 // repeat timeout. If the configuration has changed, then
6265 // don't wait at all -- we'll report the change as soon as
6266 // we have processed all events.
6267 QueuedEvent ev = mQueue.getEvent(
6268 (int)((!configChanged && curTime < nextKeyTime)
6269 ? (nextKeyTime-curTime) : 0));
6270
6271 if (DEBUG_INPUT && ev != null) Log.v(
6272 TAG, "Event: type=" + ev.classType + " data=" + ev.event);
6273
Michael Chan53071d62009-05-13 17:29:48 -07006274 if (MEASURE_LATENCY) {
6275 lt.sample("2 got event ", System.nanoTime() - ev.whenNano);
6276 }
6277
Mike Lockwood3d0ea722009-10-21 22:58:29 -04006278 if (lastKey != null && !mPolicy.allowKeyRepeat()) {
6279 // cancel key repeat at the request of the policy.
6280 lastKey = null;
6281 downTime = 0;
6282 lastKeyTime = curTime;
6283 nextKeyTime = curTime + LONG_WAIT;
6284 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006285 try {
6286 if (ev != null) {
Michael Chan53071d62009-05-13 17:29:48 -07006287 curTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006288 int eventType;
6289 if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
6290 eventType = eventType((MotionEvent)ev.event);
6291 } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
6292 ev.classType == RawInputEvent.CLASS_TRACKBALL) {
6293 eventType = LocalPowerManager.BUTTON_EVENT;
6294 } else {
6295 eventType = LocalPowerManager.OTHER_EVENT;
6296 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07006297 try {
Michael Chan53071d62009-05-13 17:29:48 -07006298 if ((curTime - mLastBatteryStatsCallTime)
Michael Chane96440f2009-05-06 10:27:36 -07006299 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
Michael Chan53071d62009-05-13 17:29:48 -07006300 mLastBatteryStatsCallTime = curTime;
Michael Chane96440f2009-05-06 10:27:36 -07006301 mBatteryStats.noteInputEvent();
6302 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07006303 } catch (RemoteException e) {
6304 // Ignore
6305 }
Michael Chane10de972009-05-18 11:24:50 -07006306
6307 if (eventType != TOUCH_EVENT
6308 && eventType != LONG_TOUCH_EVENT
6309 && eventType != CHEEK_EVENT) {
6310 mPowerManager.userActivity(curTime, false,
6311 eventType, false);
6312 } else if (mLastTouchEventType != eventType
6313 || (curTime - mLastUserActivityCallTime)
6314 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
6315 mLastUserActivityCallTime = curTime;
6316 mLastTouchEventType = eventType;
6317 mPowerManager.userActivity(curTime, false,
6318 eventType, false);
6319 }
6320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006321 switch (ev.classType) {
6322 case RawInputEvent.CLASS_KEYBOARD:
6323 KeyEvent ke = (KeyEvent)ev.event;
6324 if (ke.isDown()) {
6325 lastKey = ke;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006326 downTime = curTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 keyRepeatCount = 0;
6328 lastKeyTime = curTime;
6329 nextKeyTime = lastKeyTime
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006330 + ViewConfiguration.getLongPressTimeout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 if (DEBUG_INPUT) Log.v(
6332 TAG, "Received key down: first repeat @ "
6333 + nextKeyTime);
6334 } else {
6335 lastKey = null;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006336 downTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006337 // Arbitrary long timeout.
6338 lastKeyTime = curTime;
6339 nextKeyTime = curTime + LONG_WAIT;
6340 if (DEBUG_INPUT) Log.v(
6341 TAG, "Received key up: ignore repeat @ "
6342 + nextKeyTime);
6343 }
6344 dispatchKey((KeyEvent)ev.event, 0, 0);
6345 mQueue.recycleEvent(ev);
6346 break;
6347 case RawInputEvent.CLASS_TOUCHSCREEN:
6348 //Log.i(TAG, "Read next event " + ev);
6349 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
6350 break;
6351 case RawInputEvent.CLASS_TRACKBALL:
6352 dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
6353 break;
6354 case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
6355 configChanged = true;
6356 break;
6357 default:
6358 mQueue.recycleEvent(ev);
6359 break;
6360 }
Romain Guy06882f82009-06-10 13:36:04 -07006361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006362 } else if (configChanged) {
6363 configChanged = false;
6364 sendNewConfiguration();
Romain Guy06882f82009-06-10 13:36:04 -07006365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006366 } else if (lastKey != null) {
6367 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07006368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006369 // Timeout occurred while key was down. If it is at or
6370 // past the key repeat time, dispatch the repeat.
6371 if (DEBUG_INPUT) Log.v(
6372 TAG, "Key timeout: repeat=" + nextKeyTime
6373 + ", now=" + curTime);
6374 if (curTime < nextKeyTime) {
6375 continue;
6376 }
Romain Guy06882f82009-06-10 13:36:04 -07006377
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006378 lastKeyTime = nextKeyTime;
6379 nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY;
6380 keyRepeatCount++;
6381 if (DEBUG_INPUT) Log.v(
6382 TAG, "Key repeat: count=" + keyRepeatCount
6383 + ", next @ " + nextKeyTime);
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006384 KeyEvent newEvent;
6385 if (downTime != 0 && (downTime
6386 + ViewConfiguration.getLongPressTimeout())
6387 <= curTime) {
6388 newEvent = KeyEvent.changeTimeRepeat(lastKey,
6389 curTime, keyRepeatCount,
6390 lastKey.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6391 downTime = 0;
6392 } else {
6393 newEvent = KeyEvent.changeTimeRepeat(lastKey,
6394 curTime, keyRepeatCount);
6395 }
6396 dispatchKey(newEvent, 0, 0);
Romain Guy06882f82009-06-10 13:36:04 -07006397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006398 } else {
6399 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07006400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401 lastKeyTime = curTime;
6402 nextKeyTime = curTime + LONG_WAIT;
6403 }
Romain Guy06882f82009-06-10 13:36:04 -07006404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 } catch (Exception e) {
6406 Log.e(TAG,
6407 "Input thread received uncaught exception: " + e, e);
6408 }
6409 }
6410 }
6411 }
6412
6413 // -------------------------------------------------------------
6414 // Client Session State
6415 // -------------------------------------------------------------
6416
6417 private final class Session extends IWindowSession.Stub
6418 implements IBinder.DeathRecipient {
6419 final IInputMethodClient mClient;
6420 final IInputContext mInputContext;
6421 final int mUid;
6422 final int mPid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006423 final String mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006424 SurfaceSession mSurfaceSession;
6425 int mNumWindow = 0;
6426 boolean mClientDead = false;
Romain Guy06882f82009-06-10 13:36:04 -07006427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006428 /**
6429 * Current pointer move event being dispatched to client window... must
6430 * hold key lock to access.
6431 */
6432 QueuedEvent mPendingPointerMove;
6433 WindowState mPendingPointerWindow;
Romain Guy06882f82009-06-10 13:36:04 -07006434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006435 /**
6436 * Current trackball move event being dispatched to client window... must
6437 * hold key lock to access.
6438 */
6439 QueuedEvent mPendingTrackballMove;
6440 WindowState mPendingTrackballWindow;
6441
6442 public Session(IInputMethodClient client, IInputContext inputContext) {
6443 mClient = client;
6444 mInputContext = inputContext;
6445 mUid = Binder.getCallingUid();
6446 mPid = Binder.getCallingPid();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006447 StringBuilder sb = new StringBuilder();
6448 sb.append("Session{");
6449 sb.append(Integer.toHexString(System.identityHashCode(this)));
6450 sb.append(" uid ");
6451 sb.append(mUid);
6452 sb.append("}");
6453 mStringName = sb.toString();
Romain Guy06882f82009-06-10 13:36:04 -07006454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 synchronized (mWindowMap) {
6456 if (mInputMethodManager == null && mHaveInputMethods) {
6457 IBinder b = ServiceManager.getService(
6458 Context.INPUT_METHOD_SERVICE);
6459 mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
6460 }
6461 }
6462 long ident = Binder.clearCallingIdentity();
6463 try {
6464 // Note: it is safe to call in to the input method manager
6465 // here because we are not holding our lock.
6466 if (mInputMethodManager != null) {
6467 mInputMethodManager.addClient(client, inputContext,
6468 mUid, mPid);
6469 } else {
6470 client.setUsingInputMethod(false);
6471 }
6472 client.asBinder().linkToDeath(this, 0);
6473 } catch (RemoteException e) {
6474 // The caller has died, so we can just forget about this.
6475 try {
6476 if (mInputMethodManager != null) {
6477 mInputMethodManager.removeClient(client);
6478 }
6479 } catch (RemoteException ee) {
6480 }
6481 } finally {
6482 Binder.restoreCallingIdentity(ident);
6483 }
6484 }
Romain Guy06882f82009-06-10 13:36:04 -07006485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 @Override
6487 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
6488 throws RemoteException {
6489 try {
6490 return super.onTransact(code, data, reply, flags);
6491 } catch (RuntimeException e) {
6492 // Log all 'real' exceptions thrown to the caller
6493 if (!(e instanceof SecurityException)) {
6494 Log.e(TAG, "Window Session Crash", e);
6495 }
6496 throw e;
6497 }
6498 }
6499
6500 public void binderDied() {
6501 // Note: it is safe to call in to the input method manager
6502 // here because we are not holding our lock.
6503 try {
6504 if (mInputMethodManager != null) {
6505 mInputMethodManager.removeClient(mClient);
6506 }
6507 } catch (RemoteException e) {
6508 }
6509 synchronized(mWindowMap) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07006510 mClient.asBinder().unlinkToDeath(this, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006511 mClientDead = true;
6512 killSessionLocked();
6513 }
6514 }
6515
6516 public int add(IWindow window, WindowManager.LayoutParams attrs,
6517 int viewVisibility, Rect outContentInsets) {
6518 return addWindow(this, window, attrs, viewVisibility, outContentInsets);
6519 }
Romain Guy06882f82009-06-10 13:36:04 -07006520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006521 public void remove(IWindow window) {
6522 removeWindow(this, window);
6523 }
Romain Guy06882f82009-06-10 13:36:04 -07006524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006525 public int relayout(IWindow window, WindowManager.LayoutParams attrs,
6526 int requestedWidth, int requestedHeight, int viewFlags,
6527 boolean insetsPending, Rect outFrame, Rect outContentInsets,
6528 Rect outVisibleInsets, Surface outSurface) {
6529 return relayoutWindow(this, window, attrs,
6530 requestedWidth, requestedHeight, viewFlags, insetsPending,
6531 outFrame, outContentInsets, outVisibleInsets, outSurface);
6532 }
Romain Guy06882f82009-06-10 13:36:04 -07006533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006534 public void setTransparentRegion(IWindow window, Region region) {
6535 setTransparentRegionWindow(this, window, region);
6536 }
Romain Guy06882f82009-06-10 13:36:04 -07006537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006538 public void setInsets(IWindow window, int touchableInsets,
6539 Rect contentInsets, Rect visibleInsets) {
6540 setInsetsWindow(this, window, touchableInsets, contentInsets,
6541 visibleInsets);
6542 }
Romain Guy06882f82009-06-10 13:36:04 -07006543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006544 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
6545 getWindowDisplayFrame(this, window, outDisplayFrame);
6546 }
Romain Guy06882f82009-06-10 13:36:04 -07006547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006548 public void finishDrawing(IWindow window) {
6549 if (localLOGV) Log.v(
6550 TAG, "IWindow finishDrawing called for " + window);
6551 finishDrawingWindow(this, window);
6552 }
6553
6554 public void finishKey(IWindow window) {
6555 if (localLOGV) Log.v(
6556 TAG, "IWindow finishKey called for " + window);
6557 mKeyWaiter.finishedKey(this, window, false,
6558 KeyWaiter.RETURN_NOTHING);
6559 }
6560
6561 public MotionEvent getPendingPointerMove(IWindow window) {
6562 if (localLOGV) Log.v(
6563 TAG, "IWindow getPendingMotionEvent called for " + window);
6564 return mKeyWaiter.finishedKey(this, window, false,
6565 KeyWaiter.RETURN_PENDING_POINTER);
6566 }
Romain Guy06882f82009-06-10 13:36:04 -07006567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006568 public MotionEvent getPendingTrackballMove(IWindow window) {
6569 if (localLOGV) Log.v(
6570 TAG, "IWindow getPendingMotionEvent called for " + window);
6571 return mKeyWaiter.finishedKey(this, window, false,
6572 KeyWaiter.RETURN_PENDING_TRACKBALL);
6573 }
6574
6575 public void setInTouchMode(boolean mode) {
6576 synchronized(mWindowMap) {
6577 mInTouchMode = mode;
6578 }
6579 }
6580
6581 public boolean getInTouchMode() {
6582 synchronized(mWindowMap) {
6583 return mInTouchMode;
6584 }
6585 }
6586
6587 public boolean performHapticFeedback(IWindow window, int effectId,
6588 boolean always) {
6589 synchronized(mWindowMap) {
6590 long ident = Binder.clearCallingIdentity();
6591 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07006592 return mPolicy.performHapticFeedbackLw(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006593 windowForClientLocked(this, window), effectId, always);
6594 } finally {
6595 Binder.restoreCallingIdentity(ident);
6596 }
6597 }
6598 }
Romain Guy06882f82009-06-10 13:36:04 -07006599
Marco Nelissenbf6956b2009-11-09 15:21:13 -08006600 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006601 synchronized(mWindowMap) {
6602 long ident = Binder.clearCallingIdentity();
6603 try {
6604 setWindowWallpaperPositionLocked(windowForClientLocked(this, window),
Marco Nelissenbf6956b2009-11-09 15:21:13 -08006605 x, y, xStep, yStep);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006606 } finally {
6607 Binder.restoreCallingIdentity(ident);
6608 }
6609 }
6610 }
6611
Dianne Hackborn19382ac2009-09-11 21:13:37 -07006612 public void wallpaperOffsetsComplete(IBinder window) {
6613 WindowManagerService.this.wallpaperOffsetsComplete(window);
6614 }
6615
Dianne Hackborn75804932009-10-20 20:15:20 -07006616 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
6617 int z, Bundle extras, boolean sync) {
6618 synchronized(mWindowMap) {
6619 long ident = Binder.clearCallingIdentity();
6620 try {
6621 return sendWindowWallpaperCommandLocked(
6622 windowForClientLocked(this, window),
6623 action, x, y, z, extras, sync);
6624 } finally {
6625 Binder.restoreCallingIdentity(ident);
6626 }
6627 }
6628 }
6629
6630 public void wallpaperCommandComplete(IBinder window, Bundle result) {
6631 WindowManagerService.this.wallpaperCommandComplete(window, result);
6632 }
6633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006634 void windowAddedLocked() {
6635 if (mSurfaceSession == null) {
6636 if (localLOGV) Log.v(
6637 TAG, "First window added to " + this + ", creating SurfaceSession");
6638 mSurfaceSession = new SurfaceSession();
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07006639 if (SHOW_TRANSACTIONS) Log.i(
6640 TAG, " NEW SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006641 mSessions.add(this);
6642 }
6643 mNumWindow++;
6644 }
6645
6646 void windowRemovedLocked() {
6647 mNumWindow--;
6648 killSessionLocked();
6649 }
Romain Guy06882f82009-06-10 13:36:04 -07006650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006651 void killSessionLocked() {
6652 if (mNumWindow <= 0 && mClientDead) {
6653 mSessions.remove(this);
6654 if (mSurfaceSession != null) {
6655 if (localLOGV) Log.v(
6656 TAG, "Last window removed from " + this
6657 + ", destroying " + mSurfaceSession);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07006658 if (SHOW_TRANSACTIONS) Log.i(
6659 TAG, " KILL SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006660 try {
6661 mSurfaceSession.kill();
6662 } catch (Exception e) {
6663 Log.w(TAG, "Exception thrown when killing surface session "
6664 + mSurfaceSession + " in session " + this
6665 + ": " + e.toString());
6666 }
6667 mSurfaceSession = null;
6668 }
6669 }
6670 }
Romain Guy06882f82009-06-10 13:36:04 -07006671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006672 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006673 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
6674 pw.print(" mClientDead="); pw.print(mClientDead);
6675 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
6676 if (mPendingPointerWindow != null || mPendingPointerMove != null) {
6677 pw.print(prefix);
6678 pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
6679 pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
6680 }
6681 if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
6682 pw.print(prefix);
6683 pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
6684 pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
6685 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006686 }
6687
6688 @Override
6689 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006690 return mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006691 }
6692 }
6693
6694 // -------------------------------------------------------------
6695 // Client Window State
6696 // -------------------------------------------------------------
6697
6698 private final class WindowState implements WindowManagerPolicy.WindowState {
6699 final Session mSession;
6700 final IWindow mClient;
6701 WindowToken mToken;
The Android Open Source Project10592532009-03-18 17:39:46 -07006702 WindowToken mRootToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006703 AppWindowToken mAppToken;
6704 AppWindowToken mTargetAppToken;
6705 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
6706 final DeathRecipient mDeathRecipient;
6707 final WindowState mAttachedWindow;
6708 final ArrayList mChildWindows = new ArrayList();
6709 final int mBaseLayer;
6710 final int mSubLayer;
6711 final boolean mLayoutAttached;
6712 final boolean mIsImWindow;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006713 final boolean mIsWallpaper;
6714 final boolean mIsFloatingLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006715 int mViewVisibility;
6716 boolean mPolicyVisibility = true;
6717 boolean mPolicyVisibilityAfterAnim = true;
6718 boolean mAppFreezing;
6719 Surface mSurface;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07006720 boolean mReportDestroySurface;
6721 boolean mSurfacePendingDestroy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006722 boolean mAttachedHidden; // is our parent window hidden?
6723 boolean mLastHidden; // was this window last hidden?
Dianne Hackborn759a39e2009-08-09 17:20:27 -07006724 boolean mWallpaperVisible; // for wallpaper, what was last vis report?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006725 int mRequestedWidth;
6726 int mRequestedHeight;
6727 int mLastRequestedWidth;
6728 int mLastRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006729 int mLayer;
6730 int mAnimLayer;
6731 int mLastLayer;
6732 boolean mHaveFrame;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07006733 boolean mObscured;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07006734 boolean mTurnOnScreen;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006735
6736 WindowState mNextOutsideTouch;
Romain Guy06882f82009-06-10 13:36:04 -07006737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006738 // Actual frame shown on-screen (may be modified by animation)
6739 final Rect mShownFrame = new Rect();
6740 final Rect mLastShownFrame = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07006741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006742 /**
6743 * Insets that determine the actually visible area
6744 */
6745 final Rect mVisibleInsets = new Rect();
6746 final Rect mLastVisibleInsets = new Rect();
6747 boolean mVisibleInsetsChanged;
6748
6749 /**
6750 * Insets that are covered by system windows
6751 */
6752 final Rect mContentInsets = new Rect();
6753 final Rect mLastContentInsets = new Rect();
6754 boolean mContentInsetsChanged;
6755
6756 /**
6757 * Set to true if we are waiting for this window to receive its
6758 * given internal insets before laying out other windows based on it.
6759 */
6760 boolean mGivenInsetsPending;
Romain Guy06882f82009-06-10 13:36:04 -07006761
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006762 /**
6763 * These are the content insets that were given during layout for
6764 * this window, to be applied to windows behind it.
6765 */
6766 final Rect mGivenContentInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07006767
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006768 /**
6769 * These are the visible insets that were given during layout for
6770 * this window, to be applied to windows behind it.
6771 */
6772 final Rect mGivenVisibleInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07006773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 /**
6775 * Flag indicating whether the touchable region should be adjusted by
6776 * the visible insets; if false the area outside the visible insets is
6777 * NOT touchable, so we must use those to adjust the frame during hit
6778 * tests.
6779 */
6780 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
Romain Guy06882f82009-06-10 13:36:04 -07006781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006782 // Current transformation being applied.
6783 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
6784 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
6785 float mHScale=1, mVScale=1;
6786 float mLastHScale=1, mLastVScale=1;
6787 final Matrix mTmpMatrix = new Matrix();
6788
6789 // "Real" frame that the application sees.
6790 final Rect mFrame = new Rect();
6791 final Rect mLastFrame = new Rect();
6792
6793 final Rect mContainingFrame = new Rect();
6794 final Rect mDisplayFrame = new Rect();
6795 final Rect mContentFrame = new Rect();
6796 final Rect mVisibleFrame = new Rect();
6797
6798 float mShownAlpha = 1;
6799 float mAlpha = 1;
6800 float mLastAlpha = 1;
6801
6802 // Set to true if, when the window gets displayed, it should perform
6803 // an enter animation.
6804 boolean mEnterAnimationPending;
6805
6806 // Currently running animation.
6807 boolean mAnimating;
6808 boolean mLocalAnimating;
6809 Animation mAnimation;
6810 boolean mAnimationIsEntrance;
6811 boolean mHasTransformation;
6812 boolean mHasLocalTransformation;
6813 final Transformation mTransformation = new Transformation();
6814
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07006815 // If a window showing a wallpaper: the requested offset for the
6816 // wallpaper; if a wallpaper window: the currently applied offset.
6817 float mWallpaperX = -1;
6818 float mWallpaperY = -1;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08006819
6820 // If a window showing a wallpaper: what fraction of the offset
6821 // range corresponds to a full virtual screen.
6822 float mWallpaperXStep = -1;
6823 float mWallpaperYStep = -1;
6824
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07006825 // Wallpaper windows: pixels offset based on above variables.
6826 int mXOffset;
6827 int mYOffset;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006829 // This is set after IWindowSession.relayout() has been called at
6830 // least once for the window. It allows us to detect the situation
6831 // where we don't yet have a surface, but should have one soon, so
6832 // we can give the window focus before waiting for the relayout.
6833 boolean mRelayoutCalled;
Romain Guy06882f82009-06-10 13:36:04 -07006834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006835 // This is set after the Surface has been created but before the
6836 // window has been drawn. During this time the surface is hidden.
6837 boolean mDrawPending;
6838
6839 // This is set after the window has finished drawing for the first
6840 // time but before its surface is shown. The surface will be
6841 // displayed when the next layout is run.
6842 boolean mCommitDrawPending;
6843
6844 // This is set during the time after the window's drawing has been
6845 // committed, and before its surface is actually shown. It is used
6846 // to delay showing the surface until all windows in a token are ready
6847 // to be shown.
6848 boolean mReadyToShow;
Romain Guy06882f82009-06-10 13:36:04 -07006849
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006850 // Set when the window has been shown in the screen the first time.
6851 boolean mHasDrawn;
6852
6853 // Currently running an exit animation?
6854 boolean mExiting;
6855
6856 // Currently on the mDestroySurface list?
6857 boolean mDestroying;
Romain Guy06882f82009-06-10 13:36:04 -07006858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006859 // Completely remove from window manager after exit animation?
6860 boolean mRemoveOnExit;
6861
6862 // Set when the orientation is changing and this window has not yet
6863 // been updated for the new orientation.
6864 boolean mOrientationChanging;
Romain Guy06882f82009-06-10 13:36:04 -07006865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006866 // Is this window now (or just being) removed?
6867 boolean mRemoved;
Romain Guy06882f82009-06-10 13:36:04 -07006868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006869 WindowState(Session s, IWindow c, WindowToken token,
6870 WindowState attachedWindow, WindowManager.LayoutParams a,
6871 int viewVisibility) {
6872 mSession = s;
6873 mClient = c;
6874 mToken = token;
6875 mAttrs.copyFrom(a);
6876 mViewVisibility = viewVisibility;
6877 DeathRecipient deathRecipient = new DeathRecipient();
6878 mAlpha = a.alpha;
6879 if (localLOGV) Log.v(
6880 TAG, "Window " + this + " client=" + c.asBinder()
6881 + " token=" + token + " (" + mAttrs.token + ")");
6882 try {
6883 c.asBinder().linkToDeath(deathRecipient, 0);
6884 } catch (RemoteException e) {
6885 mDeathRecipient = null;
6886 mAttachedWindow = null;
6887 mLayoutAttached = false;
6888 mIsImWindow = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006889 mIsWallpaper = false;
6890 mIsFloatingLayer = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006891 mBaseLayer = 0;
6892 mSubLayer = 0;
6893 return;
6894 }
6895 mDeathRecipient = deathRecipient;
Romain Guy06882f82009-06-10 13:36:04 -07006896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006897 if ((mAttrs.type >= FIRST_SUB_WINDOW &&
6898 mAttrs.type <= LAST_SUB_WINDOW)) {
6899 // The multiplier here is to reserve space for multiple
6900 // windows in the same type layer.
6901 mBaseLayer = mPolicy.windowTypeToLayerLw(
6902 attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
6903 + TYPE_LAYER_OFFSET;
6904 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
6905 mAttachedWindow = attachedWindow;
6906 mAttachedWindow.mChildWindows.add(this);
6907 mLayoutAttached = mAttrs.type !=
6908 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
6909 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
6910 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006911 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
6912 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006913 } else {
6914 // The multiplier here is to reserve space for multiple
6915 // windows in the same type layer.
6916 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
6917 * TYPE_LAYER_MULTIPLIER
6918 + TYPE_LAYER_OFFSET;
6919 mSubLayer = 0;
6920 mAttachedWindow = null;
6921 mLayoutAttached = false;
6922 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
6923 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006924 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
6925 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006926 }
6927
6928 WindowState appWin = this;
6929 while (appWin.mAttachedWindow != null) {
6930 appWin = mAttachedWindow;
6931 }
6932 WindowToken appToken = appWin.mToken;
6933 while (appToken.appWindowToken == null) {
6934 WindowToken parent = mTokenMap.get(appToken.token);
6935 if (parent == null || appToken == parent) {
6936 break;
6937 }
6938 appToken = parent;
6939 }
The Android Open Source Project10592532009-03-18 17:39:46 -07006940 mRootToken = appToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006941 mAppToken = appToken.appWindowToken;
6942
6943 mSurface = null;
6944 mRequestedWidth = 0;
6945 mRequestedHeight = 0;
6946 mLastRequestedWidth = 0;
6947 mLastRequestedHeight = 0;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006948 mXOffset = 0;
6949 mYOffset = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006950 mLayer = 0;
6951 mAnimLayer = 0;
6952 mLastLayer = 0;
6953 }
6954
6955 void attach() {
6956 if (localLOGV) Log.v(
6957 TAG, "Attaching " + this + " token=" + mToken
6958 + ", list=" + mToken.windows);
6959 mSession.windowAddedLocked();
6960 }
6961
6962 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
6963 mHaveFrame = true;
6964
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006965 final Rect container = mContainingFrame;
6966 container.set(pf);
6967
6968 final Rect display = mDisplayFrame;
6969 display.set(df);
6970
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07006971 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006972 container.intersect(mCompatibleScreenFrame);
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07006973 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
6974 display.intersect(mCompatibleScreenFrame);
6975 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07006976 }
6977
6978 final int pw = container.right - container.left;
6979 final int ph = container.bottom - container.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006980
6981 int w,h;
6982 if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
6983 w = mAttrs.width < 0 ? pw : mAttrs.width;
6984 h = mAttrs.height< 0 ? ph : mAttrs.height;
6985 } else {
6986 w = mAttrs.width == mAttrs.FILL_PARENT ? pw : mRequestedWidth;
6987 h = mAttrs.height== mAttrs.FILL_PARENT ? ph : mRequestedHeight;
6988 }
Romain Guy06882f82009-06-10 13:36:04 -07006989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006990 final Rect content = mContentFrame;
6991 content.set(cf);
Romain Guy06882f82009-06-10 13:36:04 -07006992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006993 final Rect visible = mVisibleFrame;
6994 visible.set(vf);
Romain Guy06882f82009-06-10 13:36:04 -07006995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006996 final Rect frame = mFrame;
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07006997 final int fw = frame.width();
6998 final int fh = frame.height();
Romain Guy06882f82009-06-10 13:36:04 -07006999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007000 //System.out.println("In: w=" + w + " h=" + h + " container=" +
7001 // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
7002
7003 Gravity.apply(mAttrs.gravity, w, h, container,
7004 (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
7005 (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
7006
7007 //System.out.println("Out: " + mFrame);
7008
7009 // Now make sure the window fits in the overall display.
7010 Gravity.applyDisplay(mAttrs.gravity, df, frame);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007012 // Make sure the content and visible frames are inside of the
7013 // final window frame.
7014 if (content.left < frame.left) content.left = frame.left;
7015 if (content.top < frame.top) content.top = frame.top;
7016 if (content.right > frame.right) content.right = frame.right;
7017 if (content.bottom > frame.bottom) content.bottom = frame.bottom;
7018 if (visible.left < frame.left) visible.left = frame.left;
7019 if (visible.top < frame.top) visible.top = frame.top;
7020 if (visible.right > frame.right) visible.right = frame.right;
7021 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007023 final Rect contentInsets = mContentInsets;
7024 contentInsets.left = content.left-frame.left;
7025 contentInsets.top = content.top-frame.top;
7026 contentInsets.right = frame.right-content.right;
7027 contentInsets.bottom = frame.bottom-content.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007029 final Rect visibleInsets = mVisibleInsets;
7030 visibleInsets.left = visible.left-frame.left;
7031 visibleInsets.top = visible.top-frame.top;
7032 visibleInsets.right = frame.right-visible.right;
7033 visibleInsets.bottom = frame.bottom-visible.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007034
Dianne Hackborn284ac932009-08-28 10:34:25 -07007035 if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
7036 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07007037 mDisplay.getHeight(), false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07007038 }
7039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007040 if (localLOGV) {
7041 //if ("com.google.android.youtube".equals(mAttrs.packageName)
7042 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
7043 Log.v(TAG, "Resolving (mRequestedWidth="
7044 + mRequestedWidth + ", mRequestedheight="
7045 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
7046 + "): frame=" + mFrame.toShortString()
7047 + " ci=" + contentInsets.toShortString()
7048 + " vi=" + visibleInsets.toShortString());
7049 //}
7050 }
7051 }
Romain Guy06882f82009-06-10 13:36:04 -07007052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007053 public Rect getFrameLw() {
7054 return mFrame;
7055 }
7056
7057 public Rect getShownFrameLw() {
7058 return mShownFrame;
7059 }
7060
7061 public Rect getDisplayFrameLw() {
7062 return mDisplayFrame;
7063 }
7064
7065 public Rect getContentFrameLw() {
7066 return mContentFrame;
7067 }
7068
7069 public Rect getVisibleFrameLw() {
7070 return mVisibleFrame;
7071 }
7072
7073 public boolean getGivenInsetsPendingLw() {
7074 return mGivenInsetsPending;
7075 }
7076
7077 public Rect getGivenContentInsetsLw() {
7078 return mGivenContentInsets;
7079 }
Romain Guy06882f82009-06-10 13:36:04 -07007080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007081 public Rect getGivenVisibleInsetsLw() {
7082 return mGivenVisibleInsets;
7083 }
Romain Guy06882f82009-06-10 13:36:04 -07007084
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007085 public WindowManager.LayoutParams getAttrs() {
7086 return mAttrs;
7087 }
7088
7089 public int getSurfaceLayer() {
7090 return mLayer;
7091 }
Romain Guy06882f82009-06-10 13:36:04 -07007092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007093 public IApplicationToken getAppToken() {
7094 return mAppToken != null ? mAppToken.appToken : null;
7095 }
7096
7097 public boolean hasAppShownWindows() {
7098 return mAppToken != null ? mAppToken.firstWindowDrawn : false;
7099 }
7100
7101 public boolean hasAppStartingIcon() {
7102 return mAppToken != null ? (mAppToken.startingData != null) : false;
7103 }
7104
7105 public WindowManagerPolicy.WindowState getAppStartingWindow() {
7106 return mAppToken != null ? mAppToken.startingWindow : null;
7107 }
7108
7109 public void setAnimation(Animation anim) {
7110 if (localLOGV) Log.v(
7111 TAG, "Setting animation in " + this + ": " + anim);
7112 mAnimating = false;
7113 mLocalAnimating = false;
7114 mAnimation = anim;
7115 mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
7116 mAnimation.scaleCurrentDuration(mWindowAnimationScale);
7117 }
7118
7119 public void clearAnimation() {
7120 if (mAnimation != null) {
7121 mAnimating = true;
7122 mLocalAnimating = false;
7123 mAnimation = null;
7124 }
7125 }
Romain Guy06882f82009-06-10 13:36:04 -07007126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007127 Surface createSurfaceLocked() {
7128 if (mSurface == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007129 mReportDestroySurface = false;
7130 mSurfacePendingDestroy = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007131 mDrawPending = true;
7132 mCommitDrawPending = false;
7133 mReadyToShow = false;
7134 if (mAppToken != null) {
7135 mAppToken.allDrawn = false;
7136 }
7137
7138 int flags = 0;
Mathias Agopian317a6282009-08-13 17:29:02 -07007139 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 flags |= Surface.PUSH_BUFFERS;
7141 }
7142
7143 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
7144 flags |= Surface.SECURE;
7145 }
7146 if (DEBUG_VISIBILITY) Log.v(
7147 TAG, "Creating surface in session "
7148 + mSession.mSurfaceSession + " window " + this
7149 + " w=" + mFrame.width()
7150 + " h=" + mFrame.height() + " format="
7151 + mAttrs.format + " flags=" + flags);
7152
7153 int w = mFrame.width();
7154 int h = mFrame.height();
7155 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
7156 // for a scaled surface, we always want the requested
7157 // size.
7158 w = mRequestedWidth;
7159 h = mRequestedHeight;
7160 }
7161
Romain Guy9825ec62009-10-01 00:58:09 -07007162 // Something is wrong and SurfaceFlinger will not like this,
7163 // try to revert to sane values
7164 if (w <= 0) w = 1;
7165 if (h <= 0) h = 1;
7166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007167 try {
7168 mSurface = new Surface(
Romain Guy06882f82009-06-10 13:36:04 -07007169 mSession.mSurfaceSession, mSession.mPid,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007170 0, w, h, mAttrs.format, flags);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007171 if (SHOW_TRANSACTIONS) Log.i(TAG, " CREATE SURFACE "
7172 + mSurface + " IN SESSION "
7173 + mSession.mSurfaceSession
7174 + ": pid=" + mSession.mPid + " format="
7175 + mAttrs.format + " flags=0x"
7176 + Integer.toHexString(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007177 } catch (Surface.OutOfResourcesException e) {
7178 Log.w(TAG, "OutOfResourcesException creating surface");
7179 reclaimSomeSurfaceMemoryLocked(this, "create");
7180 return null;
7181 } catch (Exception e) {
7182 Log.e(TAG, "Exception creating surface", e);
7183 return null;
7184 }
Romain Guy06882f82009-06-10 13:36:04 -07007185
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007186 if (localLOGV) Log.v(
7187 TAG, "Got surface: " + mSurface
7188 + ", set left=" + mFrame.left + " top=" + mFrame.top
7189 + ", animLayer=" + mAnimLayer);
7190 if (SHOW_TRANSACTIONS) {
7191 Log.i(TAG, ">>> OPEN TRANSACTION");
7192 Log.i(TAG, " SURFACE " + mSurface + ": CREATE ("
7193 + mAttrs.getTitle() + ") pos=(" +
7194 mFrame.left + "," + mFrame.top + ") (" +
7195 mFrame.width() + "x" + mFrame.height() + "), layer=" +
7196 mAnimLayer + " HIDE");
7197 }
7198 Surface.openTransaction();
7199 try {
7200 try {
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07007201 mSurface.setPosition(mFrame.left + mXOffset,
7202 mFrame.top + mYOffset);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007203 mSurface.setLayer(mAnimLayer);
7204 mSurface.hide();
7205 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007206 if (SHOW_TRANSACTIONS) Log.i(TAG, " SURFACE "
7207 + mSurface + ": DITHER");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007208 mSurface.setFlags(Surface.SURFACE_DITHER,
7209 Surface.SURFACE_DITHER);
7210 }
7211 } catch (RuntimeException e) {
7212 Log.w(TAG, "Error creating surface in " + w, e);
7213 reclaimSomeSurfaceMemoryLocked(this, "create-init");
7214 }
7215 mLastHidden = true;
7216 } finally {
7217 if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION");
7218 Surface.closeTransaction();
7219 }
7220 if (localLOGV) Log.v(
7221 TAG, "Created surface " + this);
7222 }
7223 return mSurface;
7224 }
Romain Guy06882f82009-06-10 13:36:04 -07007225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007226 void destroySurfaceLocked() {
7227 // Window is no longer on-screen, so can no longer receive
7228 // key events... if we were waiting for it to finish
7229 // handling a key event, the wait is over!
7230 mKeyWaiter.finishedKey(mSession, mClient, true,
7231 KeyWaiter.RETURN_NOTHING);
7232 mKeyWaiter.releasePendingPointerLocked(mSession);
7233 mKeyWaiter.releasePendingTrackballLocked(mSession);
7234
7235 if (mAppToken != null && this == mAppToken.startingWindow) {
7236 mAppToken.startingDisplayed = false;
7237 }
Romain Guy06882f82009-06-10 13:36:04 -07007238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007239 if (mSurface != null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007240 mDrawPending = false;
7241 mCommitDrawPending = false;
7242 mReadyToShow = false;
7243
7244 int i = mChildWindows.size();
7245 while (i > 0) {
7246 i--;
7247 WindowState c = (WindowState)mChildWindows.get(i);
7248 c.mAttachedHidden = true;
7249 }
7250
7251 if (mReportDestroySurface) {
7252 mReportDestroySurface = false;
7253 mSurfacePendingDestroy = true;
7254 try {
7255 mClient.dispatchGetNewSurface();
7256 // We'll really destroy on the next time around.
7257 return;
7258 } catch (RemoteException e) {
7259 }
7260 }
7261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007262 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007263 if (DEBUG_VISIBILITY) {
7264 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07007265 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007266 Log.w(TAG, "Window " + this + " destroying surface "
7267 + mSurface + ", session " + mSession, e);
7268 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007269 if (SHOW_TRANSACTIONS) {
7270 RuntimeException ex = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07007271 if (!HIDE_STACK_CRAWLS) ex.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007272 Log.i(TAG, " SURFACE " + mSurface + ": DESTROY ("
7273 + mAttrs.getTitle() + ")", ex);
7274 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007275 mSurface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007276 } catch (RuntimeException e) {
7277 Log.w(TAG, "Exception thrown when destroying Window " + this
7278 + " surface " + mSurface + " session " + mSession
7279 + ": " + e.toString());
7280 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007282 mSurface = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007283 }
7284 }
7285
7286 boolean finishDrawingLocked() {
7287 if (mDrawPending) {
7288 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Log.v(
7289 TAG, "finishDrawingLocked: " + mSurface);
7290 mCommitDrawPending = true;
7291 mDrawPending = false;
7292 return true;
7293 }
7294 return false;
7295 }
7296
7297 // This must be called while inside a transaction.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007298 boolean commitFinishDrawingLocked(long currentTime) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007299 //Log.i(TAG, "commitFinishDrawingLocked: " + mSurface);
7300 if (!mCommitDrawPending) {
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007301 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007302 }
7303 mCommitDrawPending = false;
7304 mReadyToShow = true;
7305 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
7306 final AppWindowToken atoken = mAppToken;
7307 if (atoken == null || atoken.allDrawn || starting) {
7308 performShowLocked();
7309 }
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007310 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007311 }
7312
7313 // This must be called while inside a transaction.
7314 boolean performShowLocked() {
7315 if (DEBUG_VISIBILITY) {
7316 RuntimeException e = new RuntimeException();
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07007317 if (!HIDE_STACK_CRAWLS) e.fillInStackTrace();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007318 Log.v(TAG, "performShow on " + this
7319 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
7320 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
7321 }
7322 if (mReadyToShow && isReadyForDisplay()) {
7323 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Log.i(
7324 TAG, " SURFACE " + mSurface + ": SHOW (performShowLocked)");
7325 if (DEBUG_VISIBILITY) Log.v(TAG, "Showing " + this
7326 + " during animation: policyVis=" + mPolicyVisibility
7327 + " attHidden=" + mAttachedHidden
7328 + " tok.hiddenRequested="
7329 + (mAppToken != null ? mAppToken.hiddenRequested : false)
Dianne Hackborn248b1882009-09-16 16:46:44 -07007330 + " tok.hidden="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007331 + (mAppToken != null ? mAppToken.hidden : false)
7332 + " animating=" + mAnimating
7333 + " tok animating="
7334 + (mAppToken != null ? mAppToken.animating : false));
7335 if (!showSurfaceRobustlyLocked(this)) {
7336 return false;
7337 }
7338 mLastAlpha = -1;
7339 mHasDrawn = true;
7340 mLastHidden = false;
7341 mReadyToShow = false;
7342 enableScreenIfNeededLocked();
7343
7344 applyEnterAnimationLocked(this);
Romain Guy06882f82009-06-10 13:36:04 -07007345
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007346 int i = mChildWindows.size();
7347 while (i > 0) {
7348 i--;
7349 WindowState c = (WindowState)mChildWindows.get(i);
7350 if (c.mSurface != null && c.mAttachedHidden) {
7351 c.mAttachedHidden = false;
7352 c.performShowLocked();
7353 }
7354 }
Romain Guy06882f82009-06-10 13:36:04 -07007355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356 if (mAttrs.type != TYPE_APPLICATION_STARTING
7357 && mAppToken != null) {
7358 mAppToken.firstWindowDrawn = true;
Dianne Hackborn248b1882009-09-16 16:46:44 -07007359
7360 if (mAppToken.startingData != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007361 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Log.v(TAG,
7362 "Finish starting " + mToken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007363 + ": first real window is shown, no animation");
Dianne Hackborn248b1882009-09-16 16:46:44 -07007364 // If this initial window is animating, stop it -- we
7365 // will do an animation to reveal it from behind the
7366 // starting window, so there is no need for it to also
7367 // be doing its own stuff.
7368 if (mAnimation != null) {
7369 mAnimation = null;
7370 // Make sure we clean up the animation.
7371 mAnimating = true;
7372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007373 mFinishedStarting.add(mAppToken);
7374 mH.sendEmptyMessage(H.FINISHED_STARTING);
7375 }
7376 mAppToken.updateReportedVisibilityLocked();
7377 }
7378 }
7379 return true;
7380 }
Romain Guy06882f82009-06-10 13:36:04 -07007381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007382 // This must be called while inside a transaction. Returns true if
7383 // there is more animation to run.
7384 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
7385 if (!mDisplayFrozen) {
7386 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07007387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
7389 mHasTransformation = true;
7390 mHasLocalTransformation = true;
7391 if (!mLocalAnimating) {
7392 if (DEBUG_ANIM) Log.v(
7393 TAG, "Starting animation in " + this +
7394 " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
7395 " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
7396 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
7397 mAnimation.setStartTime(currentTime);
7398 mLocalAnimating = true;
7399 mAnimating = true;
7400 }
7401 mTransformation.clear();
7402 final boolean more = mAnimation.getTransformation(
7403 currentTime, mTransformation);
7404 if (DEBUG_ANIM) Log.v(
7405 TAG, "Stepped animation in " + this +
7406 ": more=" + more + ", xform=" + mTransformation);
7407 if (more) {
7408 // we're not done!
7409 return true;
7410 }
7411 if (DEBUG_ANIM) Log.v(
7412 TAG, "Finished animation in " + this +
7413 " @ " + currentTime);
7414 mAnimation = null;
7415 //WindowManagerService.this.dump();
7416 }
7417 mHasLocalTransformation = false;
7418 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007419 && mAppToken.animation != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007420 // When our app token is animating, we kind-of pretend like
7421 // we are as well. Note the mLocalAnimating mAnimationIsEntrance
7422 // part of this check means that we will only do this if
7423 // our window is not currently exiting, or it is not
7424 // locally animating itself. The idea being that one that
7425 // is exiting and doing a local animation should be removed
7426 // once that animation is done.
7427 mAnimating = true;
7428 mHasTransformation = true;
7429 mTransformation.clear();
7430 return false;
7431 } else if (mHasTransformation) {
7432 // Little trick to get through the path below to act like
7433 // we have finished an animation.
7434 mAnimating = true;
7435 } else if (isAnimating()) {
7436 mAnimating = true;
7437 }
7438 } else if (mAnimation != null) {
7439 // If the display is frozen, and there is a pending animation,
7440 // clear it and make sure we run the cleanup code.
7441 mAnimating = true;
7442 mLocalAnimating = true;
7443 mAnimation = null;
7444 }
Romain Guy06882f82009-06-10 13:36:04 -07007445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007446 if (!mAnimating && !mLocalAnimating) {
7447 return false;
7448 }
7449
7450 if (DEBUG_ANIM) Log.v(
7451 TAG, "Animation done in " + this + ": exiting=" + mExiting
7452 + ", reportedVisible="
7453 + (mAppToken != null ? mAppToken.reportedVisible : false));
Romain Guy06882f82009-06-10 13:36:04 -07007454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007455 mAnimating = false;
7456 mLocalAnimating = false;
7457 mAnimation = null;
7458 mAnimLayer = mLayer;
7459 if (mIsImWindow) {
7460 mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007461 } else if (mIsWallpaper) {
7462 mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007463 }
7464 if (DEBUG_LAYERS) Log.v(TAG, "Stepping win " + this
7465 + " anim layer: " + mAnimLayer);
7466 mHasTransformation = false;
7467 mHasLocalTransformation = false;
7468 mPolicyVisibility = mPolicyVisibilityAfterAnim;
7469 mTransformation.clear();
7470 if (mHasDrawn
7471 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
7472 && mAppToken != null
7473 && mAppToken.firstWindowDrawn
7474 && mAppToken.startingData != null) {
7475 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Finish starting "
7476 + mToken + ": first real window done animating");
7477 mFinishedStarting.add(mAppToken);
7478 mH.sendEmptyMessage(H.FINISHED_STARTING);
7479 }
Romain Guy06882f82009-06-10 13:36:04 -07007480
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 finishExit();
7482
7483 if (mAppToken != null) {
7484 mAppToken.updateReportedVisibilityLocked();
7485 }
7486
7487 return false;
7488 }
7489
7490 void finishExit() {
7491 if (DEBUG_ANIM) Log.v(
7492 TAG, "finishExit in " + this
7493 + ": exiting=" + mExiting
7494 + " remove=" + mRemoveOnExit
7495 + " windowAnimating=" + isWindowAnimating());
Romain Guy06882f82009-06-10 13:36:04 -07007496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007497 final int N = mChildWindows.size();
7498 for (int i=0; i<N; i++) {
7499 ((WindowState)mChildWindows.get(i)).finishExit();
7500 }
Romain Guy06882f82009-06-10 13:36:04 -07007501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007502 if (!mExiting) {
7503 return;
7504 }
Romain Guy06882f82009-06-10 13:36:04 -07007505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007506 if (isWindowAnimating()) {
7507 return;
7508 }
7509
7510 if (localLOGV) Log.v(
7511 TAG, "Exit animation finished in " + this
7512 + ": remove=" + mRemoveOnExit);
7513 if (mSurface != null) {
7514 mDestroySurface.add(this);
7515 mDestroying = true;
7516 if (SHOW_TRANSACTIONS) Log.i(
7517 TAG, " SURFACE " + mSurface + ": HIDE (finishExit)");
7518 try {
7519 mSurface.hide();
7520 } catch (RuntimeException e) {
7521 Log.w(TAG, "Error hiding surface in " + this, e);
7522 }
7523 mLastHidden = true;
7524 mKeyWaiter.releasePendingPointerLocked(mSession);
7525 }
7526 mExiting = false;
7527 if (mRemoveOnExit) {
7528 mPendingRemove.add(this);
7529 mRemoveOnExit = false;
7530 }
7531 }
Romain Guy06882f82009-06-10 13:36:04 -07007532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007533 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
7534 if (dsdx < .99999f || dsdx > 1.00001f) return false;
7535 if (dtdy < .99999f || dtdy > 1.00001f) return false;
7536 if (dtdx < -.000001f || dtdx > .000001f) return false;
7537 if (dsdy < -.000001f || dsdy > .000001f) return false;
7538 return true;
7539 }
Romain Guy06882f82009-06-10 13:36:04 -07007540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007541 void computeShownFrameLocked() {
7542 final boolean selfTransformation = mHasLocalTransformation;
7543 Transformation attachedTransformation =
7544 (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
7545 ? mAttachedWindow.mTransformation : null;
7546 Transformation appTransformation =
7547 (mAppToken != null && mAppToken.hasTransformation)
7548 ? mAppToken.transformation : null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007549
7550 // Wallpapers are animated based on the "real" window they
7551 // are currently targeting.
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007552 if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07007553 && mWallpaperTarget != null) {
Dianne Hackborn5baba162009-09-23 17:01:12 -07007554 if (mWallpaperTarget.mHasLocalTransformation &&
7555 mWallpaperTarget.mAnimation != null &&
7556 !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007557 attachedTransformation = mWallpaperTarget.mTransformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07007558 if (DEBUG_WALLPAPER && attachedTransformation != null) {
7559 Log.v(TAG, "WP target attached xform: " + attachedTransformation);
7560 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007561 }
7562 if (mWallpaperTarget.mAppToken != null &&
Dianne Hackborn5baba162009-09-23 17:01:12 -07007563 mWallpaperTarget.mAppToken.hasTransformation &&
7564 mWallpaperTarget.mAppToken.animation != null &&
7565 !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007566 appTransformation = mWallpaperTarget.mAppToken.transformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07007567 if (DEBUG_WALLPAPER && appTransformation != null) {
7568 Log.v(TAG, "WP target app xform: " + appTransformation);
7569 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007570 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007571 }
7572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007573 if (selfTransformation || attachedTransformation != null
7574 || appTransformation != null) {
Romain Guy06882f82009-06-10 13:36:04 -07007575 // cache often used attributes locally
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576 final Rect frame = mFrame;
7577 final float tmpFloats[] = mTmpFloats;
7578 final Matrix tmpMatrix = mTmpMatrix;
7579
7580 // Compute the desired transformation.
Dianne Hackborn65c23872009-09-18 17:47:02 -07007581 tmpMatrix.setTranslate(0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007582 if (selfTransformation) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007583 tmpMatrix.postConcat(mTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007584 }
Dianne Hackborn65c23872009-09-18 17:47:02 -07007585 tmpMatrix.postTranslate(frame.left, frame.top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586 if (attachedTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007587 tmpMatrix.postConcat(attachedTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007588 }
7589 if (appTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007590 tmpMatrix.postConcat(appTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 }
7592
7593 // "convert" it into SurfaceFlinger's format
7594 // (a 2x2 matrix + an offset)
7595 // Here we must not transform the position of the surface
7596 // since it is already included in the transformation.
7597 //Log.i(TAG, "Transform: " + matrix);
Romain Guy06882f82009-06-10 13:36:04 -07007598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 tmpMatrix.getValues(tmpFloats);
7600 mDsDx = tmpFloats[Matrix.MSCALE_X];
7601 mDtDx = tmpFloats[Matrix.MSKEW_X];
7602 mDsDy = tmpFloats[Matrix.MSKEW_Y];
7603 mDtDy = tmpFloats[Matrix.MSCALE_Y];
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007604 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
7605 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 int w = frame.width();
7607 int h = frame.height();
7608 mShownFrame.set(x, y, x+w, y+h);
7609
7610 // Now set the alpha... but because our current hardware
7611 // can't do alpha transformation on a non-opaque surface,
7612 // turn it off if we are running an animation that is also
7613 // transforming since it is more important to have that
7614 // animation be smooth.
7615 mShownAlpha = mAlpha;
7616 if (!mLimitedAlphaCompositing
7617 || (!PixelFormat.formatHasAlpha(mAttrs.format)
7618 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
7619 && x == frame.left && y == frame.top))) {
7620 //Log.i(TAG, "Applying alpha transform");
7621 if (selfTransformation) {
7622 mShownAlpha *= mTransformation.getAlpha();
7623 }
7624 if (attachedTransformation != null) {
7625 mShownAlpha *= attachedTransformation.getAlpha();
7626 }
7627 if (appTransformation != null) {
7628 mShownAlpha *= appTransformation.getAlpha();
7629 }
7630 } else {
7631 //Log.i(TAG, "Not applying alpha transform");
7632 }
Romain Guy06882f82009-06-10 13:36:04 -07007633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007634 if (localLOGV) Log.v(
7635 TAG, "Continuing animation in " + this +
7636 ": " + mShownFrame +
7637 ", alpha=" + mTransformation.getAlpha());
7638 return;
7639 }
Romain Guy06882f82009-06-10 13:36:04 -07007640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007641 mShownFrame.set(mFrame);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007642 if (mXOffset != 0 || mYOffset != 0) {
7643 mShownFrame.offset(mXOffset, mYOffset);
7644 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007645 mShownAlpha = mAlpha;
7646 mDsDx = 1;
7647 mDtDx = 0;
7648 mDsDy = 0;
7649 mDtDy = 1;
7650 }
Romain Guy06882f82009-06-10 13:36:04 -07007651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 /**
7653 * Is this window visible? It is not visible if there is no
7654 * surface, or we are in the process of running an exit animation
7655 * that will remove the surface, or its app token has been hidden.
7656 */
7657 public boolean isVisibleLw() {
7658 final AppWindowToken atoken = mAppToken;
7659 return mSurface != null && mPolicyVisibility && !mAttachedHidden
7660 && (atoken == null || !atoken.hiddenRequested)
7661 && !mExiting && !mDestroying;
7662 }
7663
7664 /**
Dianne Hackborn3d163f072009-10-07 21:26:57 -07007665 * Like {@link #isVisibleLw}, but also counts a window that is currently
7666 * "hidden" behind the keyguard as visible. This allows us to apply
7667 * things like window flags that impact the keyguard.
7668 * XXX I am starting to think we need to have ANOTHER visibility flag
7669 * for this "hidden behind keyguard" state rather than overloading
7670 * mPolicyVisibility. Ungh.
7671 */
7672 public boolean isVisibleOrBehindKeyguardLw() {
7673 final AppWindowToken atoken = mAppToken;
7674 return mSurface != null && !mAttachedHidden
7675 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
7676 && !mExiting && !mDestroying;
7677 }
7678
7679 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007680 * Is this window visible, ignoring its app token? It is not visible
7681 * if there is no surface, or we are in the process of running an exit animation
7682 * that will remove the surface.
7683 */
7684 public boolean isWinVisibleLw() {
7685 final AppWindowToken atoken = mAppToken;
7686 return mSurface != null && mPolicyVisibility && !mAttachedHidden
7687 && (atoken == null || !atoken.hiddenRequested || atoken.animating)
7688 && !mExiting && !mDestroying;
7689 }
7690
7691 /**
7692 * The same as isVisible(), but follows the current hidden state of
7693 * the associated app token, not the pending requested hidden state.
7694 */
7695 boolean isVisibleNow() {
7696 return mSurface != null && mPolicyVisibility && !mAttachedHidden
The Android Open Source Project10592532009-03-18 17:39:46 -07007697 && !mRootToken.hidden && !mExiting && !mDestroying;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007698 }
7699
7700 /**
7701 * Same as isVisible(), but we also count it as visible between the
7702 * call to IWindowSession.add() and the first relayout().
7703 */
7704 boolean isVisibleOrAdding() {
7705 final AppWindowToken atoken = mAppToken;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007706 return ((mSurface != null && !mReportDestroySurface)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007707 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
7708 && mPolicyVisibility && !mAttachedHidden
7709 && (atoken == null || !atoken.hiddenRequested)
7710 && !mExiting && !mDestroying;
7711 }
7712
7713 /**
7714 * Is this window currently on-screen? It is on-screen either if it
7715 * is visible or it is currently running an animation before no longer
7716 * being visible.
7717 */
7718 boolean isOnScreen() {
7719 final AppWindowToken atoken = mAppToken;
7720 if (atoken != null) {
7721 return mSurface != null && mPolicyVisibility && !mDestroying
7722 && ((!mAttachedHidden && !atoken.hiddenRequested)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07007723 || mAnimation != null || atoken.animation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007724 } else {
7725 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn0cd48872009-08-13 18:51:59 -07007726 && (!mAttachedHidden || mAnimation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007727 }
7728 }
Romain Guy06882f82009-06-10 13:36:04 -07007729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007730 /**
7731 * Like isOnScreen(), but we don't return true if the window is part
7732 * of a transition that has not yet been started.
7733 */
7734 boolean isReadyForDisplay() {
Dianne Hackborna8f60182009-09-01 19:01:50 -07007735 if (mRootToken.waitingToShow &&
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07007736 mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07007737 return false;
7738 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007739 final AppWindowToken atoken = mAppToken;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07007740 final boolean animating = atoken != null
7741 ? (atoken.animation != null) : false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007742 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007743 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
7744 && !mRootToken.hidden)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07007745 || mAnimation != null || animating);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007746 }
7747
7748 /** Is the window or its container currently animating? */
7749 boolean isAnimating() {
7750 final WindowState attached = mAttachedWindow;
7751 final AppWindowToken atoken = mAppToken;
7752 return mAnimation != null
7753 || (attached != null && attached.mAnimation != null)
Romain Guy06882f82009-06-10 13:36:04 -07007754 || (atoken != null &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007755 (atoken.animation != null
7756 || atoken.inPendingTransaction));
7757 }
7758
7759 /** Is this window currently animating? */
7760 boolean isWindowAnimating() {
7761 return mAnimation != null;
7762 }
7763
7764 /**
7765 * Like isOnScreen, but returns false if the surface hasn't yet
7766 * been drawn.
7767 */
7768 public boolean isDisplayedLw() {
7769 final AppWindowToken atoken = mAppToken;
7770 return mSurface != null && mPolicyVisibility && !mDestroying
7771 && !mDrawPending && !mCommitDrawPending
7772 && ((!mAttachedHidden &&
7773 (atoken == null || !atoken.hiddenRequested))
7774 || mAnimating);
7775 }
7776
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07007777 /**
7778 * Returns true if the window has a surface that it has drawn a
7779 * complete UI in to.
7780 */
7781 public boolean isDrawnLw() {
7782 final AppWindowToken atoken = mAppToken;
7783 return mSurface != null && !mDestroying
7784 && !mDrawPending && !mCommitDrawPending;
7785 }
7786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007787 public boolean fillsScreenLw(int screenWidth, int screenHeight,
7788 boolean shownFrame, boolean onlyOpaque) {
7789 if (mSurface == null) {
7790 return false;
7791 }
7792 if (mAppToken != null && !mAppToken.appFullscreen) {
7793 return false;
7794 }
7795 if (onlyOpaque && mAttrs.format != PixelFormat.OPAQUE) {
7796 return false;
7797 }
7798 final Rect frame = shownFrame ? mShownFrame : mFrame;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007799
7800 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
7801 return frame.left <= mCompatibleScreenFrame.left &&
7802 frame.top <= mCompatibleScreenFrame.top &&
7803 frame.right >= mCompatibleScreenFrame.right &&
7804 frame.bottom >= mCompatibleScreenFrame.bottom;
7805 } else {
7806 return frame.left <= 0 && frame.top <= 0
7807 && frame.right >= screenWidth
7808 && frame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007809 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 }
Romain Guy06882f82009-06-10 13:36:04 -07007811
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007812 /**
Dianne Hackborn25994b42009-09-04 14:21:19 -07007813 * Return true if the window is opaque and fully drawn. This indicates
7814 * it may obscure windows behind it.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007815 */
7816 boolean isOpaqueDrawn() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07007817 return (mAttrs.format == PixelFormat.OPAQUE
7818 || mAttrs.type == TYPE_WALLPAPER)
7819 && mSurface != null && mAnimation == null
7820 && (mAppToken == null || mAppToken.animation == null)
7821 && !mDrawPending && !mCommitDrawPending;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007822 }
7823
7824 boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
7825 return
7826 // only if the application is requesting compatible window
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07007827 (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
7828 // only if it's visible
7829 mHasDrawn && mViewVisibility == View.VISIBLE &&
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007830 // and only if the application fills the compatible screen
7831 mFrame.left <= mCompatibleScreenFrame.left &&
7832 mFrame.top <= mCompatibleScreenFrame.top &&
7833 mFrame.right >= mCompatibleScreenFrame.right &&
7834 mFrame.bottom >= mCompatibleScreenFrame.bottom &&
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07007835 // and starting window do not need background filler
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007836 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007837 }
7838
7839 boolean isFullscreen(int screenWidth, int screenHeight) {
7840 return mFrame.left <= 0 && mFrame.top <= 0 &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007841 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007842 }
7843
7844 void removeLocked() {
7845 if (mAttachedWindow != null) {
7846 mAttachedWindow.mChildWindows.remove(this);
7847 }
7848 destroySurfaceLocked();
7849 mSession.windowRemovedLocked();
7850 try {
7851 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
7852 } catch (RuntimeException e) {
7853 // Ignore if it has already been removed (usually because
7854 // we are doing this as part of processing a death note.)
7855 }
7856 }
7857
7858 private class DeathRecipient implements IBinder.DeathRecipient {
7859 public void binderDied() {
7860 try {
7861 synchronized(mWindowMap) {
7862 WindowState win = windowForClientLocked(mSession, mClient);
7863 Log.i(TAG, "WIN DEATH: " + win);
7864 if (win != null) {
7865 removeWindowLocked(mSession, win);
7866 }
7867 }
7868 } catch (IllegalArgumentException ex) {
7869 // This will happen if the window has already been
7870 // removed.
7871 }
7872 }
7873 }
7874
7875 /** Returns true if this window desires key events. */
7876 public final boolean canReceiveKeys() {
7877 return isVisibleOrAdding()
7878 && (mViewVisibility == View.VISIBLE)
7879 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
7880 }
7881
7882 public boolean hasDrawnLw() {
7883 return mHasDrawn;
7884 }
7885
7886 public boolean showLw(boolean doAnimation) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007887 return showLw(doAnimation, true);
7888 }
7889
7890 boolean showLw(boolean doAnimation, boolean requestAnim) {
7891 if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
7892 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007893 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007894 mPolicyVisibility = true;
7895 mPolicyVisibilityAfterAnim = true;
7896 if (doAnimation) {
7897 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
7898 }
7899 if (requestAnim) {
7900 requestAnimationLocked(0);
7901 }
7902 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007903 }
7904
7905 public boolean hideLw(boolean doAnimation) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007906 return hideLw(doAnimation, true);
7907 }
7908
7909 boolean hideLw(boolean doAnimation, boolean requestAnim) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007910 boolean current = doAnimation ? mPolicyVisibilityAfterAnim
7911 : mPolicyVisibility;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007912 if (!current) {
7913 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007914 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007915 if (doAnimation) {
7916 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
7917 if (mAnimation == null) {
7918 doAnimation = false;
7919 }
7920 }
7921 if (doAnimation) {
7922 mPolicyVisibilityAfterAnim = false;
7923 } else {
7924 mPolicyVisibilityAfterAnim = false;
7925 mPolicyVisibility = false;
7926 }
7927 if (requestAnim) {
7928 requestAnimationLocked(0);
7929 }
7930 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007931 }
7932
7933 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007934 StringBuilder sb = new StringBuilder(64);
Romain Guy06882f82009-06-10 13:36:04 -07007935
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007936 pw.print(prefix); pw.print("mSession="); pw.print(mSession);
7937 pw.print(" mClient="); pw.println(mClient.asBinder());
7938 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
7939 if (mAttachedWindow != null || mLayoutAttached) {
7940 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
7941 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
7942 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007943 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
7944 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
7945 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007946 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
7947 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007948 }
7949 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
7950 pw.print(" mSubLayer="); pw.print(mSubLayer);
7951 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
7952 pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
7953 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
7954 pw.print("="); pw.print(mAnimLayer);
7955 pw.print(" mLastLayer="); pw.println(mLastLayer);
7956 if (mSurface != null) {
7957 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
7958 }
7959 pw.print(prefix); pw.print("mToken="); pw.println(mToken);
7960 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
7961 if (mAppToken != null) {
7962 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
7963 }
7964 if (mTargetAppToken != null) {
7965 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
7966 }
7967 pw.print(prefix); pw.print("mViewVisibility=0x");
7968 pw.print(Integer.toHexString(mViewVisibility));
7969 pw.print(" mLastHidden="); pw.print(mLastHidden);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007970 pw.print(" mHaveFrame="); pw.print(mHaveFrame);
7971 pw.print(" mObscured="); pw.println(mObscured);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007972 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
7973 pw.print(prefix); pw.print("mPolicyVisibility=");
7974 pw.print(mPolicyVisibility);
7975 pw.print(" mPolicyVisibilityAfterAnim=");
7976 pw.print(mPolicyVisibilityAfterAnim);
7977 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
7978 }
7979 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007980 pw.print(" h="); pw.println(mRequestedHeight);
7981 if (mXOffset != 0 || mYOffset != 0) {
7982 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
7983 pw.print(" y="); pw.println(mYOffset);
7984 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007985 pw.print(prefix); pw.print("mGivenContentInsets=");
7986 mGivenContentInsets.printShortString(pw);
7987 pw.print(" mGivenVisibleInsets=");
7988 mGivenVisibleInsets.printShortString(pw);
7989 pw.println();
7990 if (mTouchableInsets != 0 || mGivenInsetsPending) {
7991 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
7992 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
7993 }
7994 pw.print(prefix); pw.print("mShownFrame=");
7995 mShownFrame.printShortString(pw);
7996 pw.print(" last="); mLastShownFrame.printShortString(pw);
7997 pw.println();
7998 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
7999 pw.print(" last="); mLastFrame.printShortString(pw);
8000 pw.println();
8001 pw.print(prefix); pw.print("mContainingFrame=");
8002 mContainingFrame.printShortString(pw);
8003 pw.print(" mDisplayFrame=");
8004 mDisplayFrame.printShortString(pw);
8005 pw.println();
8006 pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
8007 pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
8008 pw.println();
8009 pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
8010 pw.print(" last="); mLastContentInsets.printShortString(pw);
8011 pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
8012 pw.print(" last="); mLastVisibleInsets.printShortString(pw);
8013 pw.println();
8014 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
8015 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
8016 pw.print(" mAlpha="); pw.print(mAlpha);
8017 pw.print(" mLastAlpha="); pw.println(mLastAlpha);
8018 }
8019 if (mAnimating || mLocalAnimating || mAnimationIsEntrance
8020 || mAnimation != null) {
8021 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
8022 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
8023 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
8024 pw.print(" mAnimation="); pw.println(mAnimation);
8025 }
8026 if (mHasTransformation || mHasLocalTransformation) {
8027 pw.print(prefix); pw.print("XForm: has=");
8028 pw.print(mHasTransformation);
8029 pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
8030 pw.print(" "); mTransformation.printShortString(pw);
8031 pw.println();
8032 }
8033 pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
8034 pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
8035 pw.print(" mReadyToShow="); pw.print(mReadyToShow);
8036 pw.print(" mHasDrawn="); pw.println(mHasDrawn);
8037 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
8038 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
8039 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
8040 pw.print(" mDestroying="); pw.print(mDestroying);
8041 pw.print(" mRemoved="); pw.println(mRemoved);
8042 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07008043 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008044 pw.print(prefix); pw.print("mOrientationChanging=");
8045 pw.print(mOrientationChanging);
Dianne Hackborn93e462b2009-09-15 22:50:40 -07008046 pw.print(" mAppFreezing="); pw.print(mAppFreezing);
8047 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008048 }
Mitsuru Oshima589cebe2009-07-22 20:38:58 -07008049 if (mHScale != 1 || mVScale != 1) {
8050 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
8051 pw.print(" mVScale="); pw.println(mVScale);
8052 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07008053 if (mWallpaperX != -1 || mWallpaperY != -1) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008054 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
8055 pw.print(" mWallpaperY="); pw.println(mWallpaperY);
8056 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08008057 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
8058 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
8059 pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
8060 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008061 }
8062
8063 @Override
8064 public String toString() {
8065 return "Window{"
8066 + Integer.toHexString(System.identityHashCode(this))
8067 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
8068 }
8069 }
Romain Guy06882f82009-06-10 13:36:04 -07008070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008071 // -------------------------------------------------------------
8072 // Window Token State
8073 // -------------------------------------------------------------
8074
8075 class WindowToken {
8076 // The actual token.
8077 final IBinder token;
8078
8079 // The type of window this token is for, as per WindowManager.LayoutParams.
8080 final int windowType;
Romain Guy06882f82009-06-10 13:36:04 -07008081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008082 // Set if this token was explicitly added by a client, so should
8083 // not be removed when all windows are removed.
8084 final boolean explicit;
Romain Guy06882f82009-06-10 13:36:04 -07008085
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008086 // For printing.
8087 String stringName;
Romain Guy06882f82009-06-10 13:36:04 -07008088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008089 // If this is an AppWindowToken, this is non-null.
8090 AppWindowToken appWindowToken;
Romain Guy06882f82009-06-10 13:36:04 -07008091
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008092 // All of the windows associated with this token.
8093 final ArrayList<WindowState> windows = new ArrayList<WindowState>();
8094
8095 // Is key dispatching paused for this token?
8096 boolean paused = false;
8097
8098 // Should this token's windows be hidden?
8099 boolean hidden;
8100
8101 // Temporary for finding which tokens no longer have visible windows.
8102 boolean hasVisible;
8103
Dianne Hackborna8f60182009-09-01 19:01:50 -07008104 // Set to true when this token is in a pending transaction where it
8105 // will be shown.
8106 boolean waitingToShow;
8107
8108 // Set to true when this token is in a pending transaction where it
8109 // will be hidden.
8110 boolean waitingToHide;
8111
8112 // Set to true when this token is in a pending transaction where its
8113 // windows will be put to the bottom of the list.
8114 boolean sendingToBottom;
8115
8116 // Set to true when this token is in a pending transaction where its
8117 // windows will be put to the top of the list.
8118 boolean sendingToTop;
8119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008120 WindowToken(IBinder _token, int type, boolean _explicit) {
8121 token = _token;
8122 windowType = type;
8123 explicit = _explicit;
8124 }
8125
8126 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008127 pw.print(prefix); pw.print("token="); pw.println(token);
8128 pw.print(prefix); pw.print("windows="); pw.println(windows);
8129 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
8130 pw.print(" hidden="); pw.print(hidden);
8131 pw.print(" hasVisible="); pw.println(hasVisible);
Dianne Hackborna8f60182009-09-01 19:01:50 -07008132 if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
8133 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
8134 pw.print(" waitingToHide="); pw.print(waitingToHide);
8135 pw.print(" sendingToBottom="); pw.print(sendingToBottom);
8136 pw.print(" sendingToTop="); pw.println(sendingToTop);
8137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008138 }
8139
8140 @Override
8141 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008142 if (stringName == null) {
8143 StringBuilder sb = new StringBuilder();
8144 sb.append("WindowToken{");
8145 sb.append(Integer.toHexString(System.identityHashCode(this)));
8146 sb.append(" token="); sb.append(token); sb.append('}');
8147 stringName = sb.toString();
8148 }
8149 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008150 }
8151 };
8152
8153 class AppWindowToken extends WindowToken {
8154 // Non-null only for application tokens.
8155 final IApplicationToken appToken;
8156
8157 // All of the windows and child windows that are included in this
8158 // application token. Note this list is NOT sorted!
8159 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
8160
8161 int groupId = -1;
8162 boolean appFullscreen;
8163 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Romain Guy06882f82009-06-10 13:36:04 -07008164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008165 // These are used for determining when all windows associated with
8166 // an activity have been drawn, so they can be made visible together
8167 // at the same time.
8168 int lastTransactionSequence = mTransactionSequence-1;
8169 int numInterestingWindows;
8170 int numDrawnWindows;
8171 boolean inPendingTransaction;
8172 boolean allDrawn;
Romain Guy06882f82009-06-10 13:36:04 -07008173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008174 // Is this token going to be hidden in a little while? If so, it
8175 // won't be taken into account for setting the screen orientation.
8176 boolean willBeHidden;
Romain Guy06882f82009-06-10 13:36:04 -07008177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008178 // Is this window's surface needed? This is almost like hidden, except
8179 // it will sometimes be true a little earlier: when the token has
8180 // been shown, but is still waiting for its app transition to execute
8181 // before making its windows shown.
8182 boolean hiddenRequested;
Romain Guy06882f82009-06-10 13:36:04 -07008183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008184 // Have we told the window clients to hide themselves?
8185 boolean clientHidden;
Romain Guy06882f82009-06-10 13:36:04 -07008186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008187 // Last visibility state we reported to the app token.
8188 boolean reportedVisible;
8189
8190 // Set to true when the token has been removed from the window mgr.
8191 boolean removed;
8192
8193 // Have we been asked to have this token keep the screen frozen?
8194 boolean freezingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07008195
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008196 boolean animating;
8197 Animation animation;
8198 boolean hasTransformation;
8199 final Transformation transformation = new Transformation();
Romain Guy06882f82009-06-10 13:36:04 -07008200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008201 // Offset to the window of all layers in the token, for use by
8202 // AppWindowToken animations.
8203 int animLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -07008204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008205 // Information about an application starting window if displayed.
8206 StartingData startingData;
8207 WindowState startingWindow;
8208 View startingView;
8209 boolean startingDisplayed;
8210 boolean startingMoved;
8211 boolean firstWindowDrawn;
8212
8213 AppWindowToken(IApplicationToken _token) {
8214 super(_token.asBinder(),
8215 WindowManager.LayoutParams.TYPE_APPLICATION, true);
8216 appWindowToken = this;
8217 appToken = _token;
8218 }
Romain Guy06882f82009-06-10 13:36:04 -07008219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008220 public void setAnimation(Animation anim) {
8221 if (localLOGV) Log.v(
8222 TAG, "Setting animation in " + this + ": " + anim);
8223 animation = anim;
8224 animating = false;
8225 anim.restrictDuration(MAX_ANIMATION_DURATION);
8226 anim.scaleCurrentDuration(mTransitionAnimationScale);
8227 int zorder = anim.getZAdjustment();
8228 int adj = 0;
8229 if (zorder == Animation.ZORDER_TOP) {
8230 adj = TYPE_LAYER_OFFSET;
8231 } else if (zorder == Animation.ZORDER_BOTTOM) {
8232 adj = -TYPE_LAYER_OFFSET;
8233 }
Romain Guy06882f82009-06-10 13:36:04 -07008234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008235 if (animLayerAdjustment != adj) {
8236 animLayerAdjustment = adj;
8237 updateLayers();
8238 }
8239 }
Romain Guy06882f82009-06-10 13:36:04 -07008240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008241 public void setDummyAnimation() {
8242 if (animation == null) {
8243 if (localLOGV) Log.v(
8244 TAG, "Setting dummy animation in " + this);
8245 animation = sDummyAnimation;
8246 }
8247 }
8248
8249 public void clearAnimation() {
8250 if (animation != null) {
8251 animation = null;
8252 animating = true;
8253 }
8254 }
Romain Guy06882f82009-06-10 13:36:04 -07008255
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008256 void updateLayers() {
8257 final int N = allAppWindows.size();
8258 final int adj = animLayerAdjustment;
8259 for (int i=0; i<N; i++) {
8260 WindowState w = allAppWindows.get(i);
8261 w.mAnimLayer = w.mLayer + adj;
8262 if (DEBUG_LAYERS) Log.v(TAG, "Updating layer " + w + ": "
8263 + w.mAnimLayer);
8264 if (w == mInputMethodTarget) {
8265 setInputMethodAnimLayerAdjustment(adj);
8266 }
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008267 if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008268 setWallpaperAnimLayerAdjustmentLocked(adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008269 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008270 }
8271 }
Romain Guy06882f82009-06-10 13:36:04 -07008272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008273 void sendAppVisibilityToClients() {
8274 final int N = allAppWindows.size();
8275 for (int i=0; i<N; i++) {
8276 WindowState win = allAppWindows.get(i);
8277 if (win == startingWindow && clientHidden) {
8278 // Don't hide the starting window.
8279 continue;
8280 }
8281 try {
8282 if (DEBUG_VISIBILITY) Log.v(TAG,
8283 "Setting visibility of " + win + ": " + (!clientHidden));
8284 win.mClient.dispatchAppVisibility(!clientHidden);
8285 } catch (RemoteException e) {
8286 }
8287 }
8288 }
Romain Guy06882f82009-06-10 13:36:04 -07008289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008290 void showAllWindowsLocked() {
8291 final int NW = allAppWindows.size();
8292 for (int i=0; i<NW; i++) {
8293 WindowState w = allAppWindows.get(i);
8294 if (DEBUG_VISIBILITY) Log.v(TAG,
8295 "performing show on: " + w);
8296 w.performShowLocked();
8297 }
8298 }
Romain Guy06882f82009-06-10 13:36:04 -07008299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008300 // This must be called while inside a transaction.
8301 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
8302 if (!mDisplayFrozen) {
8303 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07008304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008305 if (animation == sDummyAnimation) {
8306 // This guy is going to animate, but not yet. For now count
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008307 // it as not animating for purposes of scheduling transactions;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008308 // when it is really time to animate, this will be set to
8309 // a real animation and the next call will execute normally.
8310 return false;
8311 }
Romain Guy06882f82009-06-10 13:36:04 -07008312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008313 if ((allDrawn || animating || startingDisplayed) && animation != null) {
8314 if (!animating) {
8315 if (DEBUG_ANIM) Log.v(
8316 TAG, "Starting animation in " + this +
8317 " @ " + currentTime + ": dw=" + dw + " dh=" + dh
8318 + " scale=" + mTransitionAnimationScale
8319 + " allDrawn=" + allDrawn + " animating=" + animating);
8320 animation.initialize(dw, dh, dw, dh);
8321 animation.setStartTime(currentTime);
8322 animating = true;
8323 }
8324 transformation.clear();
8325 final boolean more = animation.getTransformation(
8326 currentTime, transformation);
8327 if (DEBUG_ANIM) Log.v(
8328 TAG, "Stepped animation in " + this +
8329 ": more=" + more + ", xform=" + transformation);
8330 if (more) {
8331 // we're done!
8332 hasTransformation = true;
8333 return true;
8334 }
8335 if (DEBUG_ANIM) Log.v(
8336 TAG, "Finished animation in " + this +
8337 " @ " + currentTime);
8338 animation = null;
8339 }
8340 } else if (animation != null) {
8341 // If the display is frozen, and there is a pending animation,
8342 // clear it and make sure we run the cleanup code.
8343 animating = true;
8344 animation = null;
8345 }
8346
8347 hasTransformation = false;
Romain Guy06882f82009-06-10 13:36:04 -07008348
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008349 if (!animating) {
8350 return false;
8351 }
8352
8353 clearAnimation();
8354 animating = false;
8355 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
8356 moveInputMethodWindowsIfNeededLocked(true);
8357 }
Romain Guy06882f82009-06-10 13:36:04 -07008358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008359 if (DEBUG_ANIM) Log.v(
8360 TAG, "Animation done in " + this
8361 + ": reportedVisible=" + reportedVisible);
8362
8363 transformation.clear();
8364 if (animLayerAdjustment != 0) {
8365 animLayerAdjustment = 0;
8366 updateLayers();
8367 }
Romain Guy06882f82009-06-10 13:36:04 -07008368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008369 final int N = windows.size();
8370 for (int i=0; i<N; i++) {
8371 ((WindowState)windows.get(i)).finishExit();
8372 }
8373 updateReportedVisibilityLocked();
Romain Guy06882f82009-06-10 13:36:04 -07008374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008375 return false;
8376 }
8377
8378 void updateReportedVisibilityLocked() {
8379 if (appToken == null) {
8380 return;
8381 }
Romain Guy06882f82009-06-10 13:36:04 -07008382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008383 int numInteresting = 0;
8384 int numVisible = 0;
8385 boolean nowGone = true;
Romain Guy06882f82009-06-10 13:36:04 -07008386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008387 if (DEBUG_VISIBILITY) Log.v(TAG, "Update reported visibility: " + this);
8388 final int N = allAppWindows.size();
8389 for (int i=0; i<N; i++) {
8390 WindowState win = allAppWindows.get(i);
8391 if (win == startingWindow || win.mAppFreezing) {
8392 continue;
8393 }
8394 if (DEBUG_VISIBILITY) {
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008395 Log.v(TAG, "Win " + win + ": isDrawn="
8396 + win.isDrawnLw()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008397 + ", isAnimating=" + win.isAnimating());
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008398 if (!win.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008399 Log.v(TAG, "Not displayed: s=" + win.mSurface
8400 + " pv=" + win.mPolicyVisibility
8401 + " dp=" + win.mDrawPending
8402 + " cdp=" + win.mCommitDrawPending
8403 + " ah=" + win.mAttachedHidden
8404 + " th="
8405 + (win.mAppToken != null
8406 ? win.mAppToken.hiddenRequested : false)
8407 + " a=" + win.mAnimating);
8408 }
8409 }
8410 numInteresting++;
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008411 if (win.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008412 if (!win.isAnimating()) {
8413 numVisible++;
8414 }
8415 nowGone = false;
8416 } else if (win.isAnimating()) {
8417 nowGone = false;
8418 }
8419 }
Romain Guy06882f82009-06-10 13:36:04 -07008420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008421 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
8422 if (DEBUG_VISIBILITY) Log.v(TAG, "VIS " + this + ": interesting="
8423 + numInteresting + " visible=" + numVisible);
8424 if (nowVisible != reportedVisible) {
8425 if (DEBUG_VISIBILITY) Log.v(
8426 TAG, "Visibility changed in " + this
8427 + ": vis=" + nowVisible);
8428 reportedVisible = nowVisible;
8429 Message m = mH.obtainMessage(
8430 H.REPORT_APPLICATION_TOKEN_WINDOWS,
8431 nowVisible ? 1 : 0,
8432 nowGone ? 1 : 0,
8433 this);
8434 mH.sendMessage(m);
8435 }
8436 }
Romain Guy06882f82009-06-10 13:36:04 -07008437
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07008438 WindowState findMainWindow() {
8439 int j = windows.size();
8440 while (j > 0) {
8441 j--;
8442 WindowState win = windows.get(j);
8443 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
8444 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
8445 return win;
8446 }
8447 }
8448 return null;
8449 }
8450
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008451 void dump(PrintWriter pw, String prefix) {
8452 super.dump(pw, prefix);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008453 if (appToken != null) {
8454 pw.print(prefix); pw.println("app=true");
8455 }
8456 if (allAppWindows.size() > 0) {
8457 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
8458 }
8459 pw.print(prefix); pw.print("groupId="); pw.print(groupId);
Dianne Hackborna8f60182009-09-01 19:01:50 -07008460 pw.print(" appFullscreen="); pw.print(appFullscreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008461 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
8462 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
8463 pw.print(" clientHidden="); pw.print(clientHidden);
8464 pw.print(" willBeHidden="); pw.print(willBeHidden);
8465 pw.print(" reportedVisible="); pw.println(reportedVisible);
8466 if (paused || freezingScreen) {
8467 pw.print(prefix); pw.print("paused="); pw.print(paused);
8468 pw.print(" freezingScreen="); pw.println(freezingScreen);
8469 }
8470 if (numInterestingWindows != 0 || numDrawnWindows != 0
8471 || inPendingTransaction || allDrawn) {
8472 pw.print(prefix); pw.print("numInterestingWindows=");
8473 pw.print(numInterestingWindows);
8474 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
8475 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
8476 pw.print(" allDrawn="); pw.println(allDrawn);
8477 }
8478 if (animating || animation != null) {
8479 pw.print(prefix); pw.print("animating="); pw.print(animating);
8480 pw.print(" animation="); pw.println(animation);
8481 }
8482 if (animLayerAdjustment != 0) {
8483 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
8484 }
8485 if (hasTransformation) {
8486 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
8487 pw.print(" transformation="); transformation.printShortString(pw);
8488 pw.println();
8489 }
8490 if (startingData != null || removed || firstWindowDrawn) {
8491 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
8492 pw.print(" removed="); pw.print(removed);
8493 pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
8494 }
8495 if (startingWindow != null || startingView != null
8496 || startingDisplayed || startingMoved) {
8497 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
8498 pw.print(" startingView="); pw.print(startingView);
8499 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
8500 pw.print(" startingMoved"); pw.println(startingMoved);
8501 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502 }
8503
8504 @Override
8505 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008506 if (stringName == null) {
8507 StringBuilder sb = new StringBuilder();
8508 sb.append("AppWindowToken{");
8509 sb.append(Integer.toHexString(System.identityHashCode(this)));
8510 sb.append(" token="); sb.append(token); sb.append('}');
8511 stringName = sb.toString();
8512 }
8513 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008514 }
8515 }
Romain Guy06882f82009-06-10 13:36:04 -07008516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008517 // -------------------------------------------------------------
8518 // DummyAnimation
8519 // -------------------------------------------------------------
8520
8521 // This is an animation that does nothing: it just immediately finishes
8522 // itself every time it is called. It is used as a stub animation in cases
8523 // where we want to synchronize multiple things that may be animating.
8524 static final class DummyAnimation extends Animation {
8525 public boolean getTransformation(long currentTime, Transformation outTransformation) {
8526 return false;
8527 }
8528 }
8529 static final Animation sDummyAnimation = new DummyAnimation();
Romain Guy06882f82009-06-10 13:36:04 -07008530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531 // -------------------------------------------------------------
8532 // Async Handler
8533 // -------------------------------------------------------------
8534
8535 static final class StartingData {
8536 final String pkg;
8537 final int theme;
8538 final CharSequence nonLocalizedLabel;
8539 final int labelRes;
8540 final int icon;
Romain Guy06882f82009-06-10 13:36:04 -07008541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008542 StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
8543 int _labelRes, int _icon) {
8544 pkg = _pkg;
8545 theme = _theme;
8546 nonLocalizedLabel = _nonLocalizedLabel;
8547 labelRes = _labelRes;
8548 icon = _icon;
8549 }
8550 }
8551
8552 private final class H extends Handler {
8553 public static final int REPORT_FOCUS_CHANGE = 2;
8554 public static final int REPORT_LOSING_FOCUS = 3;
8555 public static final int ANIMATE = 4;
8556 public static final int ADD_STARTING = 5;
8557 public static final int REMOVE_STARTING = 6;
8558 public static final int FINISHED_STARTING = 7;
8559 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008560 public static final int WINDOW_FREEZE_TIMEOUT = 11;
8561 public static final int HOLD_SCREEN_CHANGED = 12;
8562 public static final int APP_TRANSITION_TIMEOUT = 13;
8563 public static final int PERSIST_ANIMATION_SCALE = 14;
8564 public static final int FORCE_GC = 15;
8565 public static final int ENABLE_SCREEN = 16;
8566 public static final int APP_FREEZE_TIMEOUT = 17;
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07008567 public static final int COMPUTE_AND_SEND_NEW_CONFIGURATION = 18;
Romain Guy06882f82009-06-10 13:36:04 -07008568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008569 private Session mLastReportedHold;
Romain Guy06882f82009-06-10 13:36:04 -07008570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008571 public H() {
8572 }
Romain Guy06882f82009-06-10 13:36:04 -07008573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008574 @Override
8575 public void handleMessage(Message msg) {
8576 switch (msg.what) {
8577 case REPORT_FOCUS_CHANGE: {
8578 WindowState lastFocus;
8579 WindowState newFocus;
Romain Guy06882f82009-06-10 13:36:04 -07008580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008581 synchronized(mWindowMap) {
8582 lastFocus = mLastFocus;
8583 newFocus = mCurrentFocus;
8584 if (lastFocus == newFocus) {
8585 // Focus is not changing, so nothing to do.
8586 return;
8587 }
8588 mLastFocus = newFocus;
8589 //Log.i(TAG, "Focus moving from " + lastFocus
8590 // + " to " + newFocus);
8591 if (newFocus != null && lastFocus != null
8592 && !newFocus.isDisplayedLw()) {
8593 //Log.i(TAG, "Delaying loss of focus...");
8594 mLosingFocus.add(lastFocus);
8595 lastFocus = null;
8596 }
8597 }
8598
8599 if (lastFocus != newFocus) {
8600 //System.out.println("Changing focus from " + lastFocus
8601 // + " to " + newFocus);
8602 if (newFocus != null) {
8603 try {
8604 //Log.i(TAG, "Gaining focus: " + newFocus);
8605 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
8606 } catch (RemoteException e) {
8607 // Ignore if process has died.
8608 }
8609 }
8610
8611 if (lastFocus != null) {
8612 try {
8613 //Log.i(TAG, "Losing focus: " + lastFocus);
8614 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
8615 } catch (RemoteException e) {
8616 // Ignore if process has died.
8617 }
8618 }
8619 }
8620 } break;
8621
8622 case REPORT_LOSING_FOCUS: {
8623 ArrayList<WindowState> losers;
Romain Guy06882f82009-06-10 13:36:04 -07008624
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008625 synchronized(mWindowMap) {
8626 losers = mLosingFocus;
8627 mLosingFocus = new ArrayList<WindowState>();
8628 }
8629
8630 final int N = losers.size();
8631 for (int i=0; i<N; i++) {
8632 try {
8633 //Log.i(TAG, "Losing delayed focus: " + losers.get(i));
8634 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
8635 } catch (RemoteException e) {
8636 // Ignore if process has died.
8637 }
8638 }
8639 } break;
8640
8641 case ANIMATE: {
8642 synchronized(mWindowMap) {
8643 mAnimationPending = false;
8644 performLayoutAndPlaceSurfacesLocked();
8645 }
8646 } break;
8647
8648 case ADD_STARTING: {
8649 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8650 final StartingData sd = wtoken.startingData;
8651
8652 if (sd == null) {
8653 // Animation has been canceled... do nothing.
8654 return;
8655 }
Romain Guy06882f82009-06-10 13:36:04 -07008656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008657 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Add starting "
8658 + wtoken + ": pkg=" + sd.pkg);
Romain Guy06882f82009-06-10 13:36:04 -07008659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660 View view = null;
8661 try {
8662 view = mPolicy.addStartingWindow(
8663 wtoken.token, sd.pkg,
8664 sd.theme, sd.nonLocalizedLabel, sd.labelRes,
8665 sd.icon);
8666 } catch (Exception e) {
8667 Log.w(TAG, "Exception when adding starting window", e);
8668 }
8669
8670 if (view != null) {
8671 boolean abort = false;
8672
8673 synchronized(mWindowMap) {
8674 if (wtoken.removed || wtoken.startingData == null) {
8675 // If the window was successfully added, then
8676 // we need to remove it.
8677 if (wtoken.startingWindow != null) {
8678 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
8679 "Aborted starting " + wtoken
8680 + ": removed=" + wtoken.removed
8681 + " startingData=" + wtoken.startingData);
8682 wtoken.startingWindow = null;
8683 wtoken.startingData = null;
8684 abort = true;
8685 }
8686 } else {
8687 wtoken.startingView = view;
8688 }
8689 if (DEBUG_STARTING_WINDOW && !abort) Log.v(TAG,
8690 "Added starting " + wtoken
8691 + ": startingWindow="
8692 + wtoken.startingWindow + " startingView="
8693 + wtoken.startingView);
8694 }
8695
8696 if (abort) {
8697 try {
8698 mPolicy.removeStartingWindow(wtoken.token, view);
8699 } catch (Exception e) {
8700 Log.w(TAG, "Exception when removing starting window", e);
8701 }
8702 }
8703 }
8704 } break;
8705
8706 case REMOVE_STARTING: {
8707 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8708 IBinder token = null;
8709 View view = null;
8710 synchronized (mWindowMap) {
8711 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Remove starting "
8712 + wtoken + ": startingWindow="
8713 + wtoken.startingWindow + " startingView="
8714 + wtoken.startingView);
8715 if (wtoken.startingWindow != null) {
8716 view = wtoken.startingView;
8717 token = wtoken.token;
8718 wtoken.startingData = null;
8719 wtoken.startingView = null;
8720 wtoken.startingWindow = null;
8721 }
8722 }
8723 if (view != null) {
8724 try {
8725 mPolicy.removeStartingWindow(token, view);
8726 } catch (Exception e) {
8727 Log.w(TAG, "Exception when removing starting window", e);
8728 }
8729 }
8730 } break;
8731
8732 case FINISHED_STARTING: {
8733 IBinder token = null;
8734 View view = null;
8735 while (true) {
8736 synchronized (mWindowMap) {
8737 final int N = mFinishedStarting.size();
8738 if (N <= 0) {
8739 break;
8740 }
8741 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
8742
8743 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
8744 "Finished starting " + wtoken
8745 + ": startingWindow=" + wtoken.startingWindow
8746 + " startingView=" + wtoken.startingView);
8747
8748 if (wtoken.startingWindow == null) {
8749 continue;
8750 }
8751
8752 view = wtoken.startingView;
8753 token = wtoken.token;
8754 wtoken.startingData = null;
8755 wtoken.startingView = null;
8756 wtoken.startingWindow = null;
8757 }
8758
8759 try {
8760 mPolicy.removeStartingWindow(token, view);
8761 } catch (Exception e) {
8762 Log.w(TAG, "Exception when removing starting window", e);
8763 }
8764 }
8765 } break;
8766
8767 case REPORT_APPLICATION_TOKEN_WINDOWS: {
8768 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8769
8770 boolean nowVisible = msg.arg1 != 0;
8771 boolean nowGone = msg.arg2 != 0;
8772
8773 try {
8774 if (DEBUG_VISIBILITY) Log.v(
8775 TAG, "Reporting visible in " + wtoken
8776 + " visible=" + nowVisible
8777 + " gone=" + nowGone);
8778 if (nowVisible) {
8779 wtoken.appToken.windowsVisible();
8780 } else {
8781 wtoken.appToken.windowsGone();
8782 }
8783 } catch (RemoteException ex) {
8784 }
8785 } break;
Romain Guy06882f82009-06-10 13:36:04 -07008786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008787 case WINDOW_FREEZE_TIMEOUT: {
8788 synchronized (mWindowMap) {
8789 Log.w(TAG, "Window freeze timeout expired.");
8790 int i = mWindows.size();
8791 while (i > 0) {
8792 i--;
8793 WindowState w = (WindowState)mWindows.get(i);
8794 if (w.mOrientationChanging) {
8795 w.mOrientationChanging = false;
8796 Log.w(TAG, "Force clearing orientation change: " + w);
8797 }
8798 }
8799 performLayoutAndPlaceSurfacesLocked();
8800 }
8801 break;
8802 }
Romain Guy06882f82009-06-10 13:36:04 -07008803
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008804 case HOLD_SCREEN_CHANGED: {
8805 Session oldHold;
8806 Session newHold;
8807 synchronized (mWindowMap) {
8808 oldHold = mLastReportedHold;
8809 newHold = (Session)msg.obj;
8810 mLastReportedHold = newHold;
8811 }
Romain Guy06882f82009-06-10 13:36:04 -07008812
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 if (oldHold != newHold) {
8814 try {
8815 if (oldHold != null) {
8816 mBatteryStats.noteStopWakelock(oldHold.mUid,
8817 "window",
8818 BatteryStats.WAKE_TYPE_WINDOW);
8819 }
8820 if (newHold != null) {
8821 mBatteryStats.noteStartWakelock(newHold.mUid,
8822 "window",
8823 BatteryStats.WAKE_TYPE_WINDOW);
8824 }
8825 } catch (RemoteException e) {
8826 }
8827 }
8828 break;
8829 }
Romain Guy06882f82009-06-10 13:36:04 -07008830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008831 case APP_TRANSITION_TIMEOUT: {
8832 synchronized (mWindowMap) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07008833 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008834 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
8835 "*** APP TRANSITION TIMEOUT");
8836 mAppTransitionReady = true;
8837 mAppTransitionTimeout = true;
8838 performLayoutAndPlaceSurfacesLocked();
8839 }
8840 }
8841 break;
8842 }
Romain Guy06882f82009-06-10 13:36:04 -07008843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008844 case PERSIST_ANIMATION_SCALE: {
8845 Settings.System.putFloat(mContext.getContentResolver(),
8846 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
8847 Settings.System.putFloat(mContext.getContentResolver(),
8848 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
8849 break;
8850 }
Romain Guy06882f82009-06-10 13:36:04 -07008851
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008852 case FORCE_GC: {
8853 synchronized(mWindowMap) {
8854 if (mAnimationPending) {
8855 // If we are animating, don't do the gc now but
8856 // delay a bit so we don't interrupt the animation.
8857 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
8858 2000);
8859 return;
8860 }
8861 // If we are currently rotating the display, it will
8862 // schedule a new message when done.
8863 if (mDisplayFrozen) {
8864 return;
8865 }
8866 mFreezeGcPending = 0;
8867 }
8868 Runtime.getRuntime().gc();
8869 break;
8870 }
Romain Guy06882f82009-06-10 13:36:04 -07008871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008872 case ENABLE_SCREEN: {
8873 performEnableScreen();
8874 break;
8875 }
Romain Guy06882f82009-06-10 13:36:04 -07008876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008877 case APP_FREEZE_TIMEOUT: {
8878 synchronized (mWindowMap) {
8879 Log.w(TAG, "App freeze timeout expired.");
8880 int i = mAppTokens.size();
8881 while (i > 0) {
8882 i--;
8883 AppWindowToken tok = mAppTokens.get(i);
8884 if (tok.freezingScreen) {
8885 Log.w(TAG, "Force clearing freeze: " + tok);
8886 unsetAppFreezingScreenLocked(tok, true, true);
8887 }
8888 }
8889 }
8890 break;
8891 }
Romain Guy06882f82009-06-10 13:36:04 -07008892
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07008893 case COMPUTE_AND_SEND_NEW_CONFIGURATION: {
Dianne Hackborncfaef692009-06-15 14:24:44 -07008894 if (updateOrientationFromAppTokensUnchecked(null, null) != null) {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07008895 sendNewConfiguration();
8896 }
8897 break;
8898 }
Romain Guy06882f82009-06-10 13:36:04 -07008899
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008900 }
8901 }
8902 }
8903
8904 // -------------------------------------------------------------
8905 // IWindowManager API
8906 // -------------------------------------------------------------
8907
8908 public IWindowSession openSession(IInputMethodClient client,
8909 IInputContext inputContext) {
8910 if (client == null) throw new IllegalArgumentException("null client");
8911 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
8912 return new Session(client, inputContext);
8913 }
8914
8915 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
8916 synchronized (mWindowMap) {
8917 // The focus for the client is the window immediately below
8918 // where we would place the input method window.
8919 int idx = findDesiredInputMethodWindowIndexLocked(false);
8920 WindowState imFocus;
8921 if (idx > 0) {
8922 imFocus = (WindowState)mWindows.get(idx-1);
8923 if (imFocus != null) {
8924 if (imFocus.mSession.mClient != null &&
8925 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
8926 return true;
8927 }
8928 }
8929 }
8930 }
8931 return false;
8932 }
Romain Guy06882f82009-06-10 13:36:04 -07008933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008934 // -------------------------------------------------------------
8935 // Internals
8936 // -------------------------------------------------------------
8937
8938 final WindowState windowForClientLocked(Session session, IWindow client) {
8939 return windowForClientLocked(session, client.asBinder());
8940 }
Romain Guy06882f82009-06-10 13:36:04 -07008941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008942 final WindowState windowForClientLocked(Session session, IBinder client) {
8943 WindowState win = mWindowMap.get(client);
8944 if (localLOGV) Log.v(
8945 TAG, "Looking up client " + client + ": " + win);
8946 if (win == null) {
8947 RuntimeException ex = new RuntimeException();
8948 Log.w(TAG, "Requested window " + client + " does not exist", ex);
8949 return null;
8950 }
8951 if (session != null && win.mSession != session) {
8952 RuntimeException ex = new RuntimeException();
8953 Log.w(TAG, "Requested window " + client + " is in session " +
8954 win.mSession + ", not " + session, ex);
8955 return null;
8956 }
8957
8958 return win;
8959 }
8960
Dianne Hackborna8f60182009-09-01 19:01:50 -07008961 final void rebuildAppWindowListLocked() {
8962 int NW = mWindows.size();
8963 int i;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008964 int lastWallpaper = -1;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07008965 int numRemoved = 0;
Dianne Hackborna8f60182009-09-01 19:01:50 -07008966
8967 // First remove all existing app windows.
8968 i=0;
8969 while (i < NW) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008970 WindowState w = (WindowState)mWindows.get(i);
8971 if (w.mAppToken != null) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07008972 WindowState win = (WindowState)mWindows.remove(i);
8973 if (DEBUG_WINDOW_MOVEMENT) Log.v(TAG,
8974 "Rebuild removing window: " + win);
Dianne Hackborna8f60182009-09-01 19:01:50 -07008975 NW--;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07008976 numRemoved++;
Dianne Hackborna8f60182009-09-01 19:01:50 -07008977 continue;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008978 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
8979 && lastWallpaper == i-1) {
8980 lastWallpaper = i;
Dianne Hackborna8f60182009-09-01 19:01:50 -07008981 }
8982 i++;
8983 }
8984
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008985 // The wallpaper window(s) typically live at the bottom of the stack,
8986 // so skip them before adding app tokens.
8987 lastWallpaper++;
8988 i = lastWallpaper;
8989
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07008990 // First add all of the exiting app tokens... these are no longer
8991 // in the main app list, but still have windows shown. We put them
8992 // in the back because now that the animation is over we no longer
8993 // will care about them.
8994 int NT = mExitingAppTokens.size();
Dianne Hackborna8f60182009-09-01 19:01:50 -07008995 for (int j=0; j<NT; j++) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07008996 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
8997 }
8998
8999 // And add in the still active app tokens in Z order.
9000 NT = mAppTokens.size();
9001 for (int j=0; j<NT; j++) {
9002 i = reAddAppWindowsLocked(i, mAppTokens.get(j));
Dianne Hackborna8f60182009-09-01 19:01:50 -07009003 }
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009004
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009005 i -= lastWallpaper;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009006 if (i != numRemoved) {
9007 Log.w(TAG, "Rebuild removed " + numRemoved
9008 + " windows but added " + i);
9009 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07009010 }
9011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009012 private final void assignLayersLocked() {
9013 int N = mWindows.size();
9014 int curBaseLayer = 0;
9015 int curLayer = 0;
9016 int i;
Romain Guy06882f82009-06-10 13:36:04 -07009017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009018 for (i=0; i<N; i++) {
9019 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009020 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
9021 || (i > 0 && w.mIsWallpaper)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009022 curLayer += WINDOW_LAYER_MULTIPLIER;
9023 w.mLayer = curLayer;
9024 } else {
9025 curBaseLayer = curLayer = w.mBaseLayer;
9026 w.mLayer = curLayer;
9027 }
9028 if (w.mTargetAppToken != null) {
9029 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
9030 } else if (w.mAppToken != null) {
9031 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
9032 } else {
9033 w.mAnimLayer = w.mLayer;
9034 }
9035 if (w.mIsImWindow) {
9036 w.mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07009037 } else if (w.mIsWallpaper) {
9038 w.mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009039 }
9040 if (DEBUG_LAYERS) Log.v(TAG, "Assign layer " + w + ": "
9041 + w.mAnimLayer);
9042 //System.out.println(
9043 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
9044 }
9045 }
9046
9047 private boolean mInLayout = false;
9048 private final void performLayoutAndPlaceSurfacesLocked() {
9049 if (mInLayout) {
Dave Bortcfe65242009-04-09 14:51:04 -07009050 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009051 throw new RuntimeException("Recursive call!");
9052 }
9053 Log.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
9054 return;
9055 }
9056
9057 boolean recoveringMemory = false;
9058 if (mForceRemoves != null) {
9059 recoveringMemory = true;
9060 // Wait a little it for things to settle down, and off we go.
9061 for (int i=0; i<mForceRemoves.size(); i++) {
9062 WindowState ws = mForceRemoves.get(i);
9063 Log.i(TAG, "Force removing: " + ws);
9064 removeWindowInnerLocked(ws.mSession, ws);
9065 }
9066 mForceRemoves = null;
9067 Log.w(TAG, "Due to memory failure, waiting a bit for next layout");
9068 Object tmp = new Object();
9069 synchronized (tmp) {
9070 try {
9071 tmp.wait(250);
9072 } catch (InterruptedException e) {
9073 }
9074 }
9075 }
Romain Guy06882f82009-06-10 13:36:04 -07009076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009077 mInLayout = true;
9078 try {
9079 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
Romain Guy06882f82009-06-10 13:36:04 -07009080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009081 int i = mPendingRemove.size()-1;
9082 if (i >= 0) {
9083 while (i >= 0) {
9084 WindowState w = mPendingRemove.get(i);
9085 removeWindowInnerLocked(w.mSession, w);
9086 i--;
9087 }
9088 mPendingRemove.clear();
9089
9090 mInLayout = false;
9091 assignLayersLocked();
9092 mLayoutNeeded = true;
9093 performLayoutAndPlaceSurfacesLocked();
9094
9095 } else {
9096 mInLayout = false;
9097 if (mLayoutNeeded) {
9098 requestAnimationLocked(0);
9099 }
9100 }
9101 } catch (RuntimeException e) {
9102 mInLayout = false;
9103 Log.e(TAG, "Unhandled exception while layout out windows", e);
9104 }
9105 }
9106
9107 private final void performLayoutLockedInner() {
9108 final int dw = mDisplay.getWidth();
9109 final int dh = mDisplay.getHeight();
9110
9111 final int N = mWindows.size();
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07009112 int repeats = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009113 int i;
9114
9115 // FIRST LOOP: Perform a layout, if needed.
Romain Guy06882f82009-06-10 13:36:04 -07009116
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07009117 while (mLayoutNeeded) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009118 mPolicy.beginLayoutLw(dw, dh);
9119
9120 // First perform layout of any root windows (not attached
9121 // to another window).
9122 int topAttached = -1;
9123 for (i = N-1; i >= 0; i--) {
9124 WindowState win = (WindowState) mWindows.get(i);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07009125
9126 // Don't do layout of a window if it is not visible, or
9127 // soon won't be visible, to avoid wasting time and funky
9128 // changes while a window is animating away.
9129 final AppWindowToken atoken = win.mAppToken;
9130 final boolean gone = win.mViewVisibility == View.GONE
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009131 || !win.mRelayoutCalled
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07009132 || win.mRootToken.hidden
9133 || (atoken != null && atoken.hiddenRequested)
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07009134 || win.mAttachedHidden
9135 || win.mExiting || win.mDestroying;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009136
9137 // If this view is GONE, then skip it -- keep the current
9138 // frame, and let the caller know so they can ignore it
9139 // if they want. (We do the normal layout for INVISIBLE
9140 // windows, since that means "perform layout as normal,
9141 // just don't display").
9142 if (!gone || !win.mHaveFrame) {
9143 if (!win.mLayoutAttached) {
9144 mPolicy.layoutWindowLw(win, win.mAttrs, null);
9145 } else {
9146 if (topAttached < 0) topAttached = i;
9147 }
9148 }
9149 }
Romain Guy06882f82009-06-10 13:36:04 -07009150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009151 // Now perform layout of attached windows, which usually
9152 // depend on the position of the window they are attached to.
9153 // XXX does not deal with windows that are attached to windows
9154 // that are themselves attached.
9155 for (i = topAttached; i >= 0; i--) {
9156 WindowState win = (WindowState) mWindows.get(i);
9157
9158 // If this view is GONE, then skip it -- keep the current
9159 // frame, and let the caller know so they can ignore it
9160 // if they want. (We do the normal layout for INVISIBLE
9161 // windows, since that means "perform layout as normal,
9162 // just don't display").
9163 if (win.mLayoutAttached) {
9164 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
9165 || !win.mHaveFrame) {
9166 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
9167 }
9168 }
9169 }
9170
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009171 int changes = mPolicy.finishLayoutLw();
9172 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
9173 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9174 assignLayersLocked();
9175 }
9176 }
9177 if (changes == 0) {
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07009178 mLayoutNeeded = false;
9179 } else if (repeats > 2) {
9180 Log.w(TAG, "Layout repeat aborted after too many iterations");
9181 mLayoutNeeded = false;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009182 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9183 Configuration newConfig = updateOrientationFromAppTokensLocked(
9184 null, null);
9185 if (newConfig != null) {
9186 mLayoutNeeded = true;
9187 mH.sendEmptyMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION);
9188 }
9189 }
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07009190 } else {
9191 repeats++;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009192 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9193 Configuration newConfig = updateOrientationFromAppTokensLocked(
9194 null, null);
9195 if (newConfig != null) {
9196 mH.sendEmptyMessage(H.COMPUTE_AND_SEND_NEW_CONFIGURATION);
9197 }
9198 }
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07009199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009200 }
9201 }
Romain Guy06882f82009-06-10 13:36:04 -07009202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203 private final void performLayoutAndPlaceSurfacesLockedInner(
9204 boolean recoveringMemory) {
9205 final long currentTime = SystemClock.uptimeMillis();
9206 final int dw = mDisplay.getWidth();
9207 final int dh = mDisplay.getHeight();
9208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009209 int i;
9210
9211 // FIRST LOOP: Perform a layout, if needed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009212 performLayoutLockedInner();
Romain Guy06882f82009-06-10 13:36:04 -07009213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009214 if (mFxSession == null) {
9215 mFxSession = new SurfaceSession();
9216 }
Romain Guy06882f82009-06-10 13:36:04 -07009217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009218 if (SHOW_TRANSACTIONS) Log.i(TAG, ">>> OPEN TRANSACTION");
9219
9220 // Initialize state of exiting tokens.
9221 for (i=mExitingTokens.size()-1; i>=0; i--) {
9222 mExitingTokens.get(i).hasVisible = false;
9223 }
9224
9225 // Initialize state of exiting applications.
9226 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
9227 mExitingAppTokens.get(i).hasVisible = false;
9228 }
9229
9230 // SECOND LOOP: Execute animations and update visibility of windows.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 boolean orientationChangeComplete = true;
9232 Session holdScreen = null;
9233 float screenBrightness = -1;
9234 boolean focusDisplayed = false;
9235 boolean animating = false;
9236
9237 Surface.openTransaction();
9238 try {
9239 boolean restart;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009240 boolean forceHiding = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009241
9242 do {
9243 final int transactionSequence = ++mTransactionSequence;
9244
9245 // Update animations of all applications, including those
9246 // associated with exiting/removed apps
9247 boolean tokensAnimating = false;
9248 final int NAT = mAppTokens.size();
9249 for (i=0; i<NAT; i++) {
9250 if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
9251 tokensAnimating = true;
9252 }
9253 }
9254 final int NEAT = mExitingAppTokens.size();
9255 for (i=0; i<NEAT; i++) {
9256 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
9257 tokensAnimating = true;
9258 }
9259 }
9260
9261 animating = tokensAnimating;
9262 restart = false;
9263
9264 boolean tokenMayBeDrawn = false;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009265 boolean wallpaperMayChange = false;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009266 boolean focusMayChange = false;
9267 boolean wallpaperForceHidingChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009268
9269 mPolicy.beginAnimationLw(dw, dh);
9270
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009271 final int N = mWindows.size();
9272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009273 for (i=N-1; i>=0; i--) {
9274 WindowState w = (WindowState)mWindows.get(i);
9275
9276 final WindowManager.LayoutParams attrs = w.mAttrs;
9277
9278 if (w.mSurface != null) {
9279 // Execute animation.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009280 if (w.commitFinishDrawingLocked(currentTime)) {
9281 if ((w.mAttrs.flags
9282 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009283 if (DEBUG_WALLPAPER) Log.v(TAG,
9284 "First draw done in potential wallpaper target " + w);
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009285 wallpaperMayChange = true;
9286 }
9287 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009288
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009289 boolean wasAnimating = w.mAnimating;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009290 if (w.stepAnimationLocked(currentTime, dw, dh)) {
9291 animating = true;
9292 //w.dump(" ");
9293 }
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009294 if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
9295 wallpaperMayChange = true;
9296 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009297
9298 if (mPolicy.doesForceHide(w, attrs)) {
9299 if (!wasAnimating && animating) {
9300 wallpaperForceHidingChanged = true;
9301 focusMayChange = true;
9302 } else if (w.isReadyForDisplay() && w.mAnimation == null) {
9303 forceHiding = true;
9304 }
9305 } else if (mPolicy.canBeForceHidden(w, attrs)) {
9306 boolean changed;
9307 if (forceHiding) {
9308 changed = w.hideLw(false, false);
9309 } else {
9310 changed = w.showLw(false, false);
9311 if (changed && wallpaperForceHidingChanged
9312 && w.isReadyForDisplay()) {
9313 // Assume we will need to animate. If
9314 // we don't (because the wallpaper will
9315 // stay with the lock screen), then we will
9316 // clean up later.
9317 Animation a = mPolicy.createForceHideEnterAnimation();
9318 if (a != null) {
9319 w.setAnimation(a);
9320 }
9321 }
9322 }
9323 if (changed && (attrs.flags
9324 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
9325 wallpaperMayChange = true;
9326 }
Christopher Tate405d0892009-10-27 20:23:28 -07009327 if (changed && !forceHiding
9328 && (mCurrentFocus == null)
9329 && (mFocusedApp != null)) {
9330 // It's possible that the last focus recalculation left no
9331 // current focused window even though the app has come to the
9332 // foreground already. In this case, we make sure to recalculate
9333 // focus when we show a window.
9334 focusMayChange = true;
9335 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009336 }
9337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009338 mPolicy.animatingWindowLw(w, attrs);
9339 }
9340
9341 final AppWindowToken atoken = w.mAppToken;
9342 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
9343 if (atoken.lastTransactionSequence != transactionSequence) {
9344 atoken.lastTransactionSequence = transactionSequence;
9345 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9346 atoken.startingDisplayed = false;
9347 }
9348 if ((w.isOnScreen() || w.mAttrs.type
9349 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
9350 && !w.mExiting && !w.mDestroying) {
9351 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009352 Log.v(TAG, "Eval win " + w + ": isDrawn="
9353 + w.isDrawnLw()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009354 + ", isAnimating=" + w.isAnimating());
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009355 if (!w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009356 Log.v(TAG, "Not displayed: s=" + w.mSurface
9357 + " pv=" + w.mPolicyVisibility
9358 + " dp=" + w.mDrawPending
9359 + " cdp=" + w.mCommitDrawPending
9360 + " ah=" + w.mAttachedHidden
9361 + " th=" + atoken.hiddenRequested
9362 + " a=" + w.mAnimating);
9363 }
9364 }
9365 if (w != atoken.startingWindow) {
9366 if (!atoken.freezingScreen || !w.mAppFreezing) {
9367 atoken.numInterestingWindows++;
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009368 if (w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009369 atoken.numDrawnWindows++;
9370 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Log.v(TAG,
9371 "tokenMayBeDrawn: " + atoken
9372 + " freezingScreen=" + atoken.freezingScreen
9373 + " mAppFreezing=" + w.mAppFreezing);
9374 tokenMayBeDrawn = true;
9375 }
9376 }
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009377 } else if (w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009378 atoken.startingDisplayed = true;
9379 }
9380 }
9381 } else if (w.mReadyToShow) {
9382 w.performShowLocked();
9383 }
9384 }
9385
9386 if (mPolicy.finishAnimationLw()) {
9387 restart = true;
9388 }
9389
9390 if (tokenMayBeDrawn) {
9391 // See if any windows have been drawn, so they (and others
9392 // associated with them) can now be shown.
9393 final int NT = mTokenList.size();
9394 for (i=0; i<NT; i++) {
9395 AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
9396 if (wtoken == null) {
9397 continue;
9398 }
9399 if (wtoken.freezingScreen) {
9400 int numInteresting = wtoken.numInterestingWindows;
9401 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9402 if (DEBUG_VISIBILITY) Log.v(TAG,
9403 "allDrawn: " + wtoken
9404 + " interesting=" + numInteresting
9405 + " drawn=" + wtoken.numDrawnWindows);
9406 wtoken.showAllWindowsLocked();
9407 unsetAppFreezingScreenLocked(wtoken, false, true);
9408 orientationChangeComplete = true;
9409 }
9410 } else if (!wtoken.allDrawn) {
9411 int numInteresting = wtoken.numInterestingWindows;
9412 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
9413 if (DEBUG_VISIBILITY) Log.v(TAG,
9414 "allDrawn: " + wtoken
9415 + " interesting=" + numInteresting
9416 + " drawn=" + wtoken.numDrawnWindows);
9417 wtoken.allDrawn = true;
9418 restart = true;
9419
9420 // We can now show all of the drawn windows!
9421 if (!mOpeningApps.contains(wtoken)) {
9422 wtoken.showAllWindowsLocked();
9423 }
9424 }
9425 }
9426 }
9427 }
9428
9429 // If we are ready to perform an app transition, check through
9430 // all of the app tokens to be shown and see if they are ready
9431 // to go.
9432 if (mAppTransitionReady) {
9433 int NN = mOpeningApps.size();
9434 boolean goodToGo = true;
9435 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9436 "Checking " + NN + " opening apps (frozen="
9437 + mDisplayFrozen + " timeout="
9438 + mAppTransitionTimeout + ")...");
9439 if (!mDisplayFrozen && !mAppTransitionTimeout) {
9440 // If the display isn't frozen, wait to do anything until
9441 // all of the apps are ready. Otherwise just go because
9442 // we'll unfreeze the display when everyone is ready.
9443 for (i=0; i<NN && goodToGo; i++) {
9444 AppWindowToken wtoken = mOpeningApps.get(i);
9445 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9446 "Check opening app" + wtoken + ": allDrawn="
9447 + wtoken.allDrawn + " startingDisplayed="
9448 + wtoken.startingDisplayed);
9449 if (!wtoken.allDrawn && !wtoken.startingDisplayed
9450 && !wtoken.startingMoved) {
9451 goodToGo = false;
9452 }
9453 }
9454 }
9455 if (goodToGo) {
9456 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "**** GOOD TO GO");
9457 int transit = mNextAppTransition;
9458 if (mSkipAppTransitionAnimation) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009459 transit = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009460 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009461 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009462 mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009463 mAppTransitionRunning = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009464 mAppTransitionTimeout = false;
9465 mStartingIconInTransition = false;
9466 mSkipAppTransitionAnimation = false;
9467
9468 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
9469
Dianne Hackborna8f60182009-09-01 19:01:50 -07009470 // If there are applications waiting to come to the
9471 // top of the stack, now is the time to move their windows.
9472 // (Note that we don't do apps going to the bottom
9473 // here -- we want to keep their windows in the old
9474 // Z-order until the animation completes.)
9475 if (mToTopApps.size() > 0) {
9476 NN = mAppTokens.size();
9477 for (i=0; i<NN; i++) {
9478 AppWindowToken wtoken = mAppTokens.get(i);
9479 if (wtoken.sendingToTop) {
9480 wtoken.sendingToTop = false;
9481 moveAppWindowsLocked(wtoken, NN, false);
9482 }
9483 }
9484 mToTopApps.clear();
9485 }
9486
Dianne Hackborn25994b42009-09-04 14:21:19 -07009487 WindowState oldWallpaper = mWallpaperTarget;
9488
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009489 adjustWallpaperWindowsLocked();
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009490 wallpaperMayChange = false;
9491
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009492 // The top-most window will supply the layout params,
9493 // and we will determine it below.
9494 LayoutParams animLp = null;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009495 AppWindowToken animToken = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009496 int bestAnimLayer = -1;
9497
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07009498 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009499 "New wallpaper target=" + mWallpaperTarget
9500 + ", lower target=" + mLowerWallpaperTarget
9501 + ", upper target=" + mUpperWallpaperTarget);
Dianne Hackborn25994b42009-09-04 14:21:19 -07009502 int foundWallpapers = 0;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009503 // Do a first pass through the tokens for two
9504 // things:
9505 // (1) Determine if both the closing and opening
9506 // app token sets are wallpaper targets, in which
9507 // case special animations are needed
9508 // (since the wallpaper needs to stay static
9509 // behind them).
9510 // (2) Find the layout params of the top-most
9511 // application window in the tokens, which is
9512 // what will control the animation theme.
9513 final int NC = mClosingApps.size();
9514 NN = NC + mOpeningApps.size();
9515 for (i=0; i<NN; i++) {
9516 AppWindowToken wtoken;
9517 int mode;
9518 if (i < NC) {
9519 wtoken = mClosingApps.get(i);
9520 mode = 1;
9521 } else {
9522 wtoken = mOpeningApps.get(i-NC);
9523 mode = 2;
9524 }
9525 if (mLowerWallpaperTarget != null) {
9526 if (mLowerWallpaperTarget.mAppToken == wtoken
9527 || mUpperWallpaperTarget.mAppToken == wtoken) {
9528 foundWallpapers |= mode;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07009529 }
9530 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009531 if (wtoken.appFullscreen) {
9532 WindowState ws = wtoken.findMainWindow();
9533 if (ws != null) {
9534 // If this is a compatibility mode
9535 // window, we will always use its anim.
9536 if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
9537 animLp = ws.mAttrs;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009538 animToken = ws.mAppToken;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009539 bestAnimLayer = Integer.MAX_VALUE;
9540 } else if (ws.mLayer > bestAnimLayer) {
9541 animLp = ws.mAttrs;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009542 animToken = ws.mAppToken;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009543 bestAnimLayer = ws.mLayer;
9544 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07009545 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07009546 }
9547 }
9548
Dianne Hackborn25994b42009-09-04 14:21:19 -07009549 if (foundWallpapers == 3) {
9550 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9551 "Wallpaper animation!");
9552 switch (transit) {
9553 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
9554 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
9555 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
9556 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN;
9557 break;
9558 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
9559 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
9560 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
9561 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE;
9562 break;
9563 }
9564 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9565 "New transit: " + transit);
9566 } else if (oldWallpaper != null) {
9567 // We are transitioning from an activity with
9568 // a wallpaper to one without.
9569 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
9570 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9571 "New transit away from wallpaper: " + transit);
9572 } else if (mWallpaperTarget != null) {
9573 // We are transitioning from an activity without
9574 // a wallpaper to now showing the wallpaper
9575 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN;
9576 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9577 "New transit into wallpaper: " + transit);
9578 }
9579
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009580 if ((transit&WindowManagerPolicy.TRANSIT_ENTER_MASK) != 0) {
9581 mLastEnterAnimToken = animToken;
9582 mLastEnterAnimParams = animLp;
9583 } else if (mLastEnterAnimParams != null) {
9584 animLp = mLastEnterAnimParams;
9585 mLastEnterAnimToken = null;
9586 mLastEnterAnimParams = null;
9587 }
9588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009589 NN = mOpeningApps.size();
9590 for (i=0; i<NN; i++) {
9591 AppWindowToken wtoken = mOpeningApps.get(i);
9592 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9593 "Now opening app" + wtoken);
9594 wtoken.reportedVisible = false;
9595 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -07009596 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009597 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -07009599 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009600 wtoken.showAllWindowsLocked();
9601 }
9602 NN = mClosingApps.size();
9603 for (i=0; i<NN; i++) {
9604 AppWindowToken wtoken = mClosingApps.get(i);
9605 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
9606 "Now closing app" + wtoken);
9607 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -07009608 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009609 setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009610 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -07009611 wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009612 // Force the allDrawn flag, because we want to start
9613 // this guy's animations regardless of whether it's
9614 // gotten drawn.
9615 wtoken.allDrawn = true;
9616 }
9617
Dianne Hackborn8b571a82009-09-25 16:09:43 -07009618 mNextAppTransitionPackage = null;
9619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009620 mOpeningApps.clear();
9621 mClosingApps.clear();
9622
9623 // This has changed the visibility of windows, so perform
9624 // a new layout to get them all up-to-date.
9625 mLayoutNeeded = true;
Dianne Hackborn20583ff2009-07-27 21:51:05 -07009626 if (!moveInputMethodWindowsIfNeededLocked(true)) {
9627 assignLayersLocked();
9628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009629 performLayoutLockedInner();
9630 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009631 focusMayChange = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009632
9633 restart = true;
9634 }
9635 }
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009636
Dianne Hackborna8f60182009-09-01 19:01:50 -07009637 if (!animating && mAppTransitionRunning) {
9638 // We have finished the animation of an app transition. To do
9639 // this, we have delayed a lot of operations like showing and
9640 // hiding apps, moving apps in Z-order, etc. The app token list
9641 // reflects the correct Z-order, but the window list may now
9642 // be out of sync with it. So here we will just rebuild the
9643 // entire app window list. Fun!
9644 mAppTransitionRunning = false;
9645 // Clear information about apps that were moving.
9646 mToBottomApps.clear();
9647
9648 rebuildAppWindowListLocked();
9649 restart = true;
9650 moveInputMethodWindowsIfNeededLocked(false);
9651 wallpaperMayChange = true;
9652 mLayoutNeeded = true;
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -08009653 // Since the window list has been rebuilt, focus might
9654 // have to be recomputed since the actual order of windows
9655 // might have changed again.
9656 focusMayChange = true;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009657 }
9658
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009659 int adjResult = 0;
9660
9661 if (wallpaperForceHidingChanged) {
9662 // At this point, there was a window with a wallpaper that
9663 // was force hiding other windows behind it, but now it
9664 // is going away. This may be simple -- just animate
9665 // away the wallpaper and its window -- or it may be
9666 // hard -- the wallpaper now needs to be shown behind
9667 // something that was hidden.
9668 WindowState oldWallpaper = mWallpaperTarget;
9669 adjResult = adjustWallpaperWindowsLocked();
9670 wallpaperMayChange = false;
9671 if (false) Log.v(TAG, "****** OLD: " + oldWallpaper
9672 + " NEW: " + mWallpaperTarget);
9673 if (mLowerWallpaperTarget == null) {
9674 // Whoops, we don't need a special wallpaper animation.
9675 // Clear them out.
9676 forceHiding = false;
9677 for (i=N-1; i>=0; i--) {
9678 WindowState w = (WindowState)mWindows.get(i);
9679 if (w.mSurface != null) {
9680 final WindowManager.LayoutParams attrs = w.mAttrs;
Suchi Amalapurapuc03d28b2009-10-28 14:32:05 -07009681 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) {
9682 if (DEBUG_FOCUS) Log.i(TAG, "win=" + w + " force hides other windows");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009683 forceHiding = true;
9684 } else if (mPolicy.canBeForceHidden(w, attrs)) {
9685 if (!w.mAnimating) {
9686 // We set the animation above so it
9687 // is not yet running.
9688 w.clearAnimation();
9689 }
9690 }
9691 }
9692 }
9693 }
9694 }
9695
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009696 if (wallpaperMayChange) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009697 if (DEBUG_WALLPAPER) Log.v(TAG,
9698 "Wallpaper may change! Adjusting");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009699 adjResult = adjustWallpaperWindowsLocked();
9700 }
9701
9702 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9703 if (DEBUG_WALLPAPER) Log.v(TAG,
9704 "Wallpaper layer changed: assigning layers + relayout");
9705 restart = true;
9706 mLayoutNeeded = true;
9707 assignLayersLocked();
9708 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
9709 if (DEBUG_WALLPAPER) Log.v(TAG,
9710 "Wallpaper visibility changed: relayout");
9711 restart = true;
9712 mLayoutNeeded = true;
9713 }
9714
9715 if (focusMayChange) {
9716 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009717 restart = true;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009718 adjResult = 0;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009719 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009720 }
9721
9722 if (mLayoutNeeded) {
9723 restart = true;
9724 performLayoutLockedInner();
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009725 }
9726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009727 } while (restart);
9728
9729 // THIRD LOOP: Update the surfaces of all windows.
9730
9731 final boolean someoneLosingFocus = mLosingFocus.size() != 0;
9732
9733 boolean obscured = false;
9734 boolean blurring = false;
9735 boolean dimming = false;
9736 boolean covered = false;
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07009737 boolean syswin = false;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07009738 boolean backgroundFillerShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009739
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009740 final int N = mWindows.size();
9741
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009742 for (i=N-1; i>=0; i--) {
9743 WindowState w = (WindowState)mWindows.get(i);
9744
9745 boolean displayed = false;
9746 final WindowManager.LayoutParams attrs = w.mAttrs;
9747 final int attrFlags = attrs.flags;
9748
9749 if (w.mSurface != null) {
9750 w.computeShownFrameLocked();
9751 if (localLOGV) Log.v(
9752 TAG, "Placing surface #" + i + " " + w.mSurface
9753 + ": new=" + w.mShownFrame + ", old="
9754 + w.mLastShownFrame);
9755
9756 boolean resize;
9757 int width, height;
9758 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
9759 resize = w.mLastRequestedWidth != w.mRequestedWidth ||
9760 w.mLastRequestedHeight != w.mRequestedHeight;
9761 // for a scaled surface, we just want to use
9762 // the requested size.
9763 width = w.mRequestedWidth;
9764 height = w.mRequestedHeight;
9765 w.mLastRequestedWidth = width;
9766 w.mLastRequestedHeight = height;
9767 w.mLastShownFrame.set(w.mShownFrame);
9768 try {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009769 if (SHOW_TRANSACTIONS) Log.i(
9770 TAG, " SURFACE " + w.mSurface
9771 + ": POS " + w.mShownFrame.left
9772 + ", " + w.mShownFrame.top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009773 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
9774 } catch (RuntimeException e) {
9775 Log.w(TAG, "Error positioning surface in " + w, e);
9776 if (!recoveringMemory) {
9777 reclaimSomeSurfaceMemoryLocked(w, "position");
9778 }
9779 }
9780 } else {
9781 resize = !w.mLastShownFrame.equals(w.mShownFrame);
9782 width = w.mShownFrame.width();
9783 height = w.mShownFrame.height();
9784 w.mLastShownFrame.set(w.mShownFrame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009785 }
9786
9787 if (resize) {
9788 if (width < 1) width = 1;
9789 if (height < 1) height = 1;
9790 if (w.mSurface != null) {
9791 try {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009792 if (SHOW_TRANSACTIONS) Log.i(
9793 TAG, " SURFACE " + w.mSurface + ": POS "
9794 + w.mShownFrame.left + ","
9795 + w.mShownFrame.top + " SIZE "
9796 + w.mShownFrame.width() + "x"
9797 + w.mShownFrame.height());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009798 w.mSurface.setSize(width, height);
9799 w.mSurface.setPosition(w.mShownFrame.left,
9800 w.mShownFrame.top);
9801 } catch (RuntimeException e) {
9802 // If something goes wrong with the surface (such
9803 // as running out of memory), don't take down the
9804 // entire system.
9805 Log.e(TAG, "Failure updating surface of " + w
9806 + "size=(" + width + "x" + height
9807 + "), pos=(" + w.mShownFrame.left
9808 + "," + w.mShownFrame.top + ")", e);
9809 if (!recoveringMemory) {
9810 reclaimSomeSurfaceMemoryLocked(w, "size");
9811 }
9812 }
9813 }
9814 }
9815 if (!w.mAppFreezing) {
9816 w.mContentInsetsChanged =
9817 !w.mLastContentInsets.equals(w.mContentInsets);
9818 w.mVisibleInsetsChanged =
9819 !w.mLastVisibleInsets.equals(w.mVisibleInsets);
Romain Guy06882f82009-06-10 13:36:04 -07009820 if (!w.mLastFrame.equals(w.mFrame)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 || w.mContentInsetsChanged
9822 || w.mVisibleInsetsChanged) {
9823 w.mLastFrame.set(w.mFrame);
9824 w.mLastContentInsets.set(w.mContentInsets);
9825 w.mLastVisibleInsets.set(w.mVisibleInsets);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009826 // If the screen is currently frozen, then keep
9827 // it frozen until this window draws at its new
9828 // orientation.
9829 if (mDisplayFrozen) {
9830 if (DEBUG_ORIENTATION) Log.v(TAG,
9831 "Resizing while display frozen: " + w);
9832 w.mOrientationChanging = true;
9833 if (mWindowsFreezingScreen) {
9834 mWindowsFreezingScreen = true;
9835 // XXX should probably keep timeout from
9836 // when we first froze the display.
9837 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
9838 mH.sendMessageDelayed(mH.obtainMessage(
9839 H.WINDOW_FREEZE_TIMEOUT), 2000);
9840 }
9841 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009842 // If the orientation is changing, then we need to
9843 // hold off on unfreezing the display until this
9844 // window has been redrawn; to do that, we need
9845 // to go through the process of getting informed
9846 // by the application when it has finished drawing.
9847 if (w.mOrientationChanging) {
9848 if (DEBUG_ORIENTATION) Log.v(TAG,
9849 "Orientation start waiting for draw in "
9850 + w + ", surface " + w.mSurface);
9851 w.mDrawPending = true;
9852 w.mCommitDrawPending = false;
9853 w.mReadyToShow = false;
9854 if (w.mAppToken != null) {
9855 w.mAppToken.allDrawn = false;
9856 }
9857 }
Romain Guy06882f82009-06-10 13:36:04 -07009858 if (DEBUG_ORIENTATION) Log.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009859 "Resizing window " + w + " to " + w.mFrame);
9860 mResizingWindows.add(w);
9861 } else if (w.mOrientationChanging) {
9862 if (!w.mDrawPending && !w.mCommitDrawPending) {
9863 if (DEBUG_ORIENTATION) Log.v(TAG,
9864 "Orientation not waiting for draw in "
9865 + w + ", surface " + w.mSurface);
9866 w.mOrientationChanging = false;
9867 }
9868 }
9869 }
9870
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009871 if (w.mAttachedHidden || !w.isReadyForDisplay()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009872 if (!w.mLastHidden) {
9873 //dump();
9874 w.mLastHidden = true;
9875 if (SHOW_TRANSACTIONS) Log.i(
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009876 TAG, " SURFACE " + w.mSurface + ": HIDE (performLayout)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009877 if (w.mSurface != null) {
9878 try {
9879 w.mSurface.hide();
9880 } catch (RuntimeException e) {
9881 Log.w(TAG, "Exception hiding surface in " + w);
9882 }
9883 }
9884 mKeyWaiter.releasePendingPointerLocked(w.mSession);
9885 }
9886 // If we are waiting for this window to handle an
9887 // orientation change, well, it is hidden, so
9888 // doesn't really matter. Note that this does
9889 // introduce a potential glitch if the window
9890 // becomes unhidden before it has drawn for the
9891 // new orientation.
9892 if (w.mOrientationChanging) {
9893 w.mOrientationChanging = false;
9894 if (DEBUG_ORIENTATION) Log.v(TAG,
9895 "Orientation change skips hidden " + w);
9896 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009897 } else if (w.mLastLayer != w.mAnimLayer
9898 || w.mLastAlpha != w.mShownAlpha
9899 || w.mLastDsDx != w.mDsDx
9900 || w.mLastDtDx != w.mDtDx
9901 || w.mLastDsDy != w.mDsDy
9902 || w.mLastDtDy != w.mDtDy
9903 || w.mLastHScale != w.mHScale
9904 || w.mLastVScale != w.mVScale
9905 || w.mLastHidden) {
9906 displayed = true;
9907 w.mLastAlpha = w.mShownAlpha;
9908 w.mLastLayer = w.mAnimLayer;
9909 w.mLastDsDx = w.mDsDx;
9910 w.mLastDtDx = w.mDtDx;
9911 w.mLastDsDy = w.mDsDy;
9912 w.mLastDtDy = w.mDtDy;
9913 w.mLastHScale = w.mHScale;
9914 w.mLastVScale = w.mVScale;
9915 if (SHOW_TRANSACTIONS) Log.i(
9916 TAG, " SURFACE " + w.mSurface + ": alpha="
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009917 + w.mShownAlpha + " layer=" + w.mAnimLayer
9918 + " matrix=[" + (w.mDsDx*w.mHScale)
9919 + "," + (w.mDtDx*w.mVScale)
9920 + "][" + (w.mDsDy*w.mHScale)
9921 + "," + (w.mDtDy*w.mVScale) + "]");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009922 if (w.mSurface != null) {
9923 try {
9924 w.mSurface.setAlpha(w.mShownAlpha);
9925 w.mSurface.setLayer(w.mAnimLayer);
9926 w.mSurface.setMatrix(
9927 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
9928 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
9929 } catch (RuntimeException e) {
9930 Log.w(TAG, "Error updating surface in " + w, e);
9931 if (!recoveringMemory) {
9932 reclaimSomeSurfaceMemoryLocked(w, "update");
9933 }
9934 }
9935 }
9936
9937 if (w.mLastHidden && !w.mDrawPending
9938 && !w.mCommitDrawPending
9939 && !w.mReadyToShow) {
9940 if (SHOW_TRANSACTIONS) Log.i(
9941 TAG, " SURFACE " + w.mSurface + ": SHOW (performLayout)");
9942 if (DEBUG_VISIBILITY) Log.v(TAG, "Showing " + w
9943 + " during relayout");
9944 if (showSurfaceRobustlyLocked(w)) {
9945 w.mHasDrawn = true;
9946 w.mLastHidden = false;
9947 } else {
9948 w.mOrientationChanging = false;
9949 }
9950 }
9951 if (w.mSurface != null) {
9952 w.mToken.hasVisible = true;
9953 }
9954 } else {
9955 displayed = true;
9956 }
9957
9958 if (displayed) {
9959 if (!covered) {
9960 if (attrs.width == LayoutParams.FILL_PARENT
9961 && attrs.height == LayoutParams.FILL_PARENT) {
9962 covered = true;
9963 }
9964 }
9965 if (w.mOrientationChanging) {
9966 if (w.mDrawPending || w.mCommitDrawPending) {
9967 orientationChangeComplete = false;
9968 if (DEBUG_ORIENTATION) Log.v(TAG,
9969 "Orientation continue waiting for draw in " + w);
9970 } else {
9971 w.mOrientationChanging = false;
9972 if (DEBUG_ORIENTATION) Log.v(TAG,
9973 "Orientation change complete in " + w);
9974 }
9975 }
9976 w.mToken.hasVisible = true;
9977 }
9978 } else if (w.mOrientationChanging) {
9979 if (DEBUG_ORIENTATION) Log.v(TAG,
9980 "Orientation change skips hidden " + w);
9981 w.mOrientationChanging = false;
9982 }
9983
9984 final boolean canBeSeen = w.isDisplayedLw();
9985
9986 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
9987 focusDisplayed = true;
9988 }
9989
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07009990 final boolean obscuredChanged = w.mObscured != obscured;
9991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009992 // Update effect.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009993 if (!(w.mObscured=obscured)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009994 if (w.mSurface != null) {
9995 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
9996 holdScreen = w.mSession;
9997 }
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07009998 if (!syswin && w.mAttrs.screenBrightness >= 0
9999 && screenBrightness < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010000 screenBrightness = w.mAttrs.screenBrightness;
10001 }
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070010002 if (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
10003 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
10004 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR) {
10005 syswin = true;
10006 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010007 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010008
Dianne Hackborn25994b42009-09-04 14:21:19 -070010009 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
10010 if (opaqueDrawn && w.isFullscreen(dw, dh)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010011 // This window completely covers everything behind it,
10012 // so we want to leave all of them as unblurred (for
10013 // performance reasons).
10014 obscured = true;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010015 } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
10016 if (SHOW_TRANSACTIONS) Log.d(TAG, "showing background filler");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010017 // This window is in compatibility mode, and needs background filler.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010018 obscured = true;
10019 if (mBackgroundFillerSurface == null) {
10020 try {
10021 mBackgroundFillerSurface = new Surface(mFxSession, 0,
10022 0, dw, dh,
10023 PixelFormat.OPAQUE,
10024 Surface.FX_SURFACE_NORMAL);
10025 } catch (Exception e) {
10026 Log.e(TAG, "Exception creating filler surface", e);
10027 }
10028 }
10029 try {
10030 mBackgroundFillerSurface.setPosition(0, 0);
10031 mBackgroundFillerSurface.setSize(dw, dh);
10032 // Using the same layer as Dim because they will never be shown at the
10033 // same time.
10034 mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
10035 mBackgroundFillerSurface.show();
10036 } catch (RuntimeException e) {
10037 Log.e(TAG, "Exception showing filler surface");
10038 }
10039 backgroundFillerShown = true;
10040 mBackgroundFillerShown = true;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010041 } else if (canBeSeen && !obscured &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010042 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
10043 if (localLOGV) Log.v(TAG, "Win " + w
10044 + ": blurring=" + blurring
10045 + " obscured=" + obscured
10046 + " displayed=" + displayed);
10047 if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
10048 if (!dimming) {
10049 //Log.i(TAG, "DIM BEHIND: " + w);
10050 dimming = true;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010051 if (mDimAnimator == null) {
10052 mDimAnimator = new DimAnimator(mFxSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010053 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010054 mDimAnimator.show(dw, dh);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010056 mDimAnimator.updateParameters(w, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010057 }
10058 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
10059 if (!blurring) {
10060 //Log.i(TAG, "BLUR BEHIND: " + w);
10061 blurring = true;
10062 mBlurShown = true;
10063 if (mBlurSurface == null) {
10064 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR "
10065 + mBlurSurface + ": CREATE");
10066 try {
Romain Guy06882f82009-06-10 13:36:04 -070010067 mBlurSurface = new Surface(mFxSession, 0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010068 -1, 16, 16,
10069 PixelFormat.OPAQUE,
10070 Surface.FX_SURFACE_BLUR);
10071 } catch (Exception e) {
10072 Log.e(TAG, "Exception creating Blur surface", e);
10073 }
10074 }
10075 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR "
10076 + mBlurSurface + ": SHOW pos=(0,0) (" +
10077 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
10078 if (mBlurSurface != null) {
10079 mBlurSurface.setPosition(0, 0);
10080 mBlurSurface.setSize(dw, dh);
10081 try {
10082 mBlurSurface.show();
10083 } catch (RuntimeException e) {
10084 Log.w(TAG, "Failure showing blur surface", e);
10085 }
10086 }
10087 }
10088 mBlurSurface.setLayer(w.mAnimLayer-2);
10089 }
10090 }
10091 }
Dianne Hackborne9e9bca2009-08-18 15:08:22 -070010092
10093 if (obscuredChanged && mWallpaperTarget == w) {
10094 // This is the wallpaper target and its obscured state
10095 // changed... make sure the current wallaper's visibility
10096 // has been updated accordingly.
10097 updateWallpaperVisibilityLocked();
10098 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010099 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010100
10101 if (backgroundFillerShown == false && mBackgroundFillerShown) {
10102 mBackgroundFillerShown = false;
10103 if (SHOW_TRANSACTIONS) Log.d(TAG, "hiding background filler");
10104 try {
10105 mBackgroundFillerSurface.hide();
10106 } catch (RuntimeException e) {
10107 Log.e(TAG, "Exception hiding filler surface", e);
10108 }
10109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010110
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010111 if (mDimAnimator != null && mDimAnimator.mDimShown) {
10112 animating |= mDimAnimator.updateSurface(dimming, currentTime, mDisplayFrozen);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010113 }
Romain Guy06882f82009-06-10 13:36:04 -070010114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010115 if (!blurring && mBlurShown) {
10116 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR " + mBlurSurface
10117 + ": HIDE");
10118 try {
10119 mBlurSurface.hide();
10120 } catch (IllegalArgumentException e) {
10121 Log.w(TAG, "Illegal argument exception hiding blur surface");
10122 }
10123 mBlurShown = false;
10124 }
10125
10126 if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION");
10127 } catch (RuntimeException e) {
10128 Log.e(TAG, "Unhandled exception in Window Manager", e);
10129 }
10130
10131 Surface.closeTransaction();
Romain Guy06882f82009-06-10 13:36:04 -070010132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010133 if (DEBUG_ORIENTATION && mDisplayFrozen) Log.v(TAG,
10134 "With display frozen, orientationChangeComplete="
10135 + orientationChangeComplete);
10136 if (orientationChangeComplete) {
10137 if (mWindowsFreezingScreen) {
10138 mWindowsFreezingScreen = false;
10139 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10140 }
10141 if (mAppsFreezingScreen == 0) {
10142 stopFreezingDisplayLocked();
10143 }
10144 }
Romain Guy06882f82009-06-10 13:36:04 -070010145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010146 i = mResizingWindows.size();
10147 if (i > 0) {
10148 do {
10149 i--;
10150 WindowState win = mResizingWindows.get(i);
10151 try {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010152 if (DEBUG_ORIENTATION) Log.v(TAG, "Reporting new frame to "
10153 + win + ": " + win.mFrame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010154 win.mClient.resized(win.mFrame.width(),
10155 win.mFrame.height(), win.mLastContentInsets,
10156 win.mLastVisibleInsets, win.mDrawPending);
10157 win.mContentInsetsChanged = false;
10158 win.mVisibleInsetsChanged = false;
10159 } catch (RemoteException e) {
10160 win.mOrientationChanging = false;
10161 }
10162 } while (i > 0);
10163 mResizingWindows.clear();
10164 }
Romain Guy06882f82009-06-10 13:36:04 -070010165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010166 // Destroy the surface of any windows that are no longer visible.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010167 boolean wallpaperDestroyed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010168 i = mDestroySurface.size();
10169 if (i > 0) {
10170 do {
10171 i--;
10172 WindowState win = mDestroySurface.get(i);
10173 win.mDestroying = false;
10174 if (mInputMethodWindow == win) {
10175 mInputMethodWindow = null;
10176 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010177 if (win == mWallpaperTarget) {
10178 wallpaperDestroyed = true;
10179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010180 win.destroySurfaceLocked();
10181 } while (i > 0);
10182 mDestroySurface.clear();
10183 }
10184
10185 // Time to remove any exiting tokens?
10186 for (i=mExitingTokens.size()-1; i>=0; i--) {
10187 WindowToken token = mExitingTokens.get(i);
10188 if (!token.hasVisible) {
10189 mExitingTokens.remove(i);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070010190 if (token.windowType == TYPE_WALLPAPER) {
10191 mWallpaperTokens.remove(token);
10192 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010193 }
10194 }
10195
10196 // Time to remove any exiting applications?
10197 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
10198 AppWindowToken token = mExitingAppTokens.get(i);
10199 if (!token.hasVisible && !mClosingApps.contains(token)) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -070010200 // Make sure there is no animation running on this token,
10201 // so any windows associated with it will be removed as
10202 // soon as their animations are complete
10203 token.animation = null;
10204 token.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010205 mAppTokens.remove(token);
10206 mExitingAppTokens.remove(i);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010207 if (mLastEnterAnimToken == token) {
10208 mLastEnterAnimToken = null;
10209 mLastEnterAnimParams = null;
10210 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010211 }
10212 }
10213
Dianne Hackborna8f60182009-09-01 19:01:50 -070010214 boolean needRelayout = false;
10215
10216 if (!animating && mAppTransitionRunning) {
10217 // We have finished the animation of an app transition. To do
10218 // this, we have delayed a lot of operations like showing and
10219 // hiding apps, moving apps in Z-order, etc. The app token list
10220 // reflects the correct Z-order, but the window list may now
10221 // be out of sync with it. So here we will just rebuild the
10222 // entire app window list. Fun!
10223 mAppTransitionRunning = false;
10224 needRelayout = true;
10225 rebuildAppWindowListLocked();
10226 // Clear information about apps that were moving.
10227 mToBottomApps.clear();
10228 }
10229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 if (focusDisplayed) {
10231 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
10232 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010233 if (wallpaperDestroyed) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010234 needRelayout = adjustWallpaperWindowsLocked() != 0;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010235 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070010236 if (needRelayout) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010237 requestAnimationLocked(0);
10238 } else if (animating) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010239 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
10240 }
10241 mQueue.setHoldScreenLocked(holdScreen != null);
10242 if (screenBrightness < 0 || screenBrightness > 1.0f) {
10243 mPowerManager.setScreenBrightnessOverride(-1);
10244 } else {
10245 mPowerManager.setScreenBrightnessOverride((int)
10246 (screenBrightness * Power.BRIGHTNESS_ON));
10247 }
10248 if (holdScreen != mHoldingScreenOn) {
10249 mHoldingScreenOn = holdScreen;
10250 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
10251 mH.sendMessage(m);
10252 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -070010253
10254 if (mTurnOnScreen) {
10255 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
10256 LocalPowerManager.BUTTON_EVENT, true);
10257 mTurnOnScreen = false;
10258 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010259 }
10260
10261 void requestAnimationLocked(long delay) {
10262 if (!mAnimationPending) {
10263 mAnimationPending = true;
10264 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
10265 }
10266 }
Romain Guy06882f82009-06-10 13:36:04 -070010267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010268 /**
10269 * Have the surface flinger show a surface, robustly dealing with
10270 * error conditions. In particular, if there is not enough memory
10271 * to show the surface, then we will try to get rid of other surfaces
10272 * in order to succeed.
Romain Guy06882f82009-06-10 13:36:04 -070010273 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010274 * @return Returns true if the surface was successfully shown.
10275 */
10276 boolean showSurfaceRobustlyLocked(WindowState win) {
10277 try {
10278 if (win.mSurface != null) {
10279 win.mSurface.show();
Dianne Hackborn93e462b2009-09-15 22:50:40 -070010280 if (win.mTurnOnScreen) {
10281 win.mTurnOnScreen = false;
10282 mTurnOnScreen = true;
10283 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 }
10285 return true;
10286 } catch (RuntimeException e) {
10287 Log.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
10288 }
Romain Guy06882f82009-06-10 13:36:04 -070010289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010290 reclaimSomeSurfaceMemoryLocked(win, "show");
Romain Guy06882f82009-06-10 13:36:04 -070010291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010292 return false;
10293 }
Romain Guy06882f82009-06-10 13:36:04 -070010294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010295 void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
10296 final Surface surface = win.mSurface;
Romain Guy06882f82009-06-10 13:36:04 -070010297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010298 EventLog.writeEvent(LOG_WM_NO_SURFACE_MEMORY, win.toString(),
10299 win.mSession.mPid, operation);
Romain Guy06882f82009-06-10 13:36:04 -070010300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 if (mForceRemoves == null) {
10302 mForceRemoves = new ArrayList<WindowState>();
10303 }
Romain Guy06882f82009-06-10 13:36:04 -070010304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010305 long callingIdentity = Binder.clearCallingIdentity();
10306 try {
10307 // There was some problem... first, do a sanity check of the
10308 // window list to make sure we haven't left any dangling surfaces
10309 // around.
10310 int N = mWindows.size();
10311 boolean leakedSurface = false;
10312 Log.i(TAG, "Out of memory for surface! Looking for leaks...");
10313 for (int i=0; i<N; i++) {
10314 WindowState ws = (WindowState)mWindows.get(i);
10315 if (ws.mSurface != null) {
10316 if (!mSessions.contains(ws.mSession)) {
10317 Log.w(TAG, "LEAKED SURFACE (session doesn't exist): "
10318 + ws + " surface=" + ws.mSurface
10319 + " token=" + win.mToken
10320 + " pid=" + ws.mSession.mPid
10321 + " uid=" + ws.mSession.mUid);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010322 ws.mSurface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010323 ws.mSurface = null;
10324 mForceRemoves.add(ws);
10325 i--;
10326 N--;
10327 leakedSurface = true;
10328 } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
10329 Log.w(TAG, "LEAKED SURFACE (app token hidden): "
10330 + ws + " surface=" + ws.mSurface
10331 + " token=" + win.mAppToken);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010332 ws.mSurface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010333 ws.mSurface = null;
10334 leakedSurface = true;
10335 }
10336 }
10337 }
Romain Guy06882f82009-06-10 13:36:04 -070010338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010339 boolean killedApps = false;
10340 if (!leakedSurface) {
10341 Log.w(TAG, "No leaked surfaces; killing applicatons!");
10342 SparseIntArray pidCandidates = new SparseIntArray();
10343 for (int i=0; i<N; i++) {
10344 WindowState ws = (WindowState)mWindows.get(i);
10345 if (ws.mSurface != null) {
10346 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
10347 }
10348 }
10349 if (pidCandidates.size() > 0) {
10350 int[] pids = new int[pidCandidates.size()];
10351 for (int i=0; i<pids.length; i++) {
10352 pids[i] = pidCandidates.keyAt(i);
10353 }
10354 try {
10355 if (mActivityManager.killPidsForMemory(pids)) {
10356 killedApps = true;
10357 }
10358 } catch (RemoteException e) {
10359 }
10360 }
10361 }
Romain Guy06882f82009-06-10 13:36:04 -070010362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010363 if (leakedSurface || killedApps) {
10364 // We managed to reclaim some memory, so get rid of the trouble
10365 // surface and ask the app to request another one.
10366 Log.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
10367 if (surface != null) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010368 surface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010369 win.mSurface = null;
10370 }
Romain Guy06882f82009-06-10 13:36:04 -070010371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010372 try {
10373 win.mClient.dispatchGetNewSurface();
10374 } catch (RemoteException e) {
10375 }
10376 }
10377 } finally {
10378 Binder.restoreCallingIdentity(callingIdentity);
10379 }
10380 }
Romain Guy06882f82009-06-10 13:36:04 -070010381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010382 private boolean updateFocusedWindowLocked(int mode) {
10383 WindowState newFocus = computeFocusedWindowLocked();
10384 if (mCurrentFocus != newFocus) {
10385 // This check makes sure that we don't already have the focus
10386 // change message pending.
10387 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
10388 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
10389 if (localLOGV) Log.v(
10390 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
10391 final WindowState oldFocus = mCurrentFocus;
10392 mCurrentFocus = newFocus;
10393 mLosingFocus.remove(newFocus);
Romain Guy06882f82009-06-10 13:36:04 -070010394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010395 final WindowState imWindow = mInputMethodWindow;
10396 if (newFocus != imWindow && oldFocus != imWindow) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010397 if (moveInputMethodWindowsIfNeededLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010398 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010399 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
10400 mLayoutNeeded = true;
10401 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010402 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10403 performLayoutLockedInner();
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010404 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
10405 // Client will do the layout, but we need to assign layers
10406 // for handleNewWindowLocked() below.
10407 assignLayersLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010408 }
10409 }
Romain Guy06882f82009-06-10 13:36:04 -070010410
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010411 if (newFocus != null && mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
10412 mKeyWaiter.handleNewWindowLocked(newFocus);
10413 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414 return true;
10415 }
10416 return false;
10417 }
10418
10419 private WindowState computeFocusedWindowLocked() {
10420 WindowState result = null;
10421 WindowState win;
10422
10423 int i = mWindows.size() - 1;
10424 int nextAppIndex = mAppTokens.size()-1;
10425 WindowToken nextApp = nextAppIndex >= 0
10426 ? mAppTokens.get(nextAppIndex) : null;
10427
10428 while (i >= 0) {
10429 win = (WindowState)mWindows.get(i);
10430
10431 if (localLOGV || DEBUG_FOCUS) Log.v(
10432 TAG, "Looking for focus: " + i
10433 + " = " + win
10434 + ", flags=" + win.mAttrs.flags
10435 + ", canReceive=" + win.canReceiveKeys());
10436
10437 AppWindowToken thisApp = win.mAppToken;
Romain Guy06882f82009-06-10 13:36:04 -070010438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010439 // If this window's application has been removed, just skip it.
10440 if (thisApp != null && thisApp.removed) {
10441 i--;
10442 continue;
10443 }
Romain Guy06882f82009-06-10 13:36:04 -070010444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010445 // If there is a focused app, don't allow focus to go to any
10446 // windows below it. If this is an application window, step
10447 // through the app tokens until we find its app.
10448 if (thisApp != null && nextApp != null && thisApp != nextApp
10449 && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
10450 int origAppIndex = nextAppIndex;
10451 while (nextAppIndex > 0) {
10452 if (nextApp == mFocusedApp) {
10453 // Whoops, we are below the focused app... no focus
10454 // for you!
10455 if (localLOGV || DEBUG_FOCUS) Log.v(
10456 TAG, "Reached focused app: " + mFocusedApp);
10457 return null;
10458 }
10459 nextAppIndex--;
10460 nextApp = mAppTokens.get(nextAppIndex);
10461 if (nextApp == thisApp) {
10462 break;
10463 }
10464 }
10465 if (thisApp != nextApp) {
10466 // Uh oh, the app token doesn't exist! This shouldn't
10467 // happen, but if it does we can get totally hosed...
10468 // so restart at the original app.
10469 nextAppIndex = origAppIndex;
10470 nextApp = mAppTokens.get(nextAppIndex);
10471 }
10472 }
10473
10474 // Dispatch to this window if it is wants key events.
10475 if (win.canReceiveKeys()) {
10476 if (DEBUG_FOCUS) Log.v(
10477 TAG, "Found focus @ " + i + " = " + win);
10478 result = win;
10479 break;
10480 }
10481
10482 i--;
10483 }
10484
10485 return result;
10486 }
10487
10488 private void startFreezingDisplayLocked() {
10489 if (mDisplayFrozen) {
Chris Tate2ad63a92009-03-25 17:36:48 -070010490 // Freezing the display also suspends key event delivery, to
10491 // keep events from going astray while the display is reconfigured.
10492 // If someone has changed orientation again while the screen is
10493 // still frozen, the events will continue to be blocked while the
10494 // successive orientation change is processed. To prevent spurious
10495 // ANRs, we reset the event dispatch timeout in this case.
10496 synchronized (mKeyWaiter) {
10497 mKeyWaiter.mWasFrozen = true;
10498 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010499 return;
10500 }
Romain Guy06882f82009-06-10 13:36:04 -070010501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010502 mScreenFrozenLock.acquire();
Romain Guy06882f82009-06-10 13:36:04 -070010503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010504 long now = SystemClock.uptimeMillis();
10505 //Log.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
10506 if (mFreezeGcPending != 0) {
10507 if (now > (mFreezeGcPending+1000)) {
10508 //Log.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
10509 mH.removeMessages(H.FORCE_GC);
10510 Runtime.getRuntime().gc();
10511 mFreezeGcPending = now;
10512 }
10513 } else {
10514 mFreezeGcPending = now;
10515 }
Romain Guy06882f82009-06-10 13:36:04 -070010516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010517 mDisplayFrozen = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -070010518 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
10519 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010520 mNextAppTransitionPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010521 mAppTransitionReady = true;
10522 }
Romain Guy06882f82009-06-10 13:36:04 -070010523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010524 if (PROFILE_ORIENTATION) {
10525 File file = new File("/data/system/frozen");
10526 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
10527 }
10528 Surface.freezeDisplay(0);
10529 }
Romain Guy06882f82009-06-10 13:36:04 -070010530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531 private void stopFreezingDisplayLocked() {
10532 if (!mDisplayFrozen) {
10533 return;
10534 }
Romain Guy06882f82009-06-10 13:36:04 -070010535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010536 mDisplayFrozen = false;
10537 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
10538 if (PROFILE_ORIENTATION) {
10539 Debug.stopMethodTracing();
10540 }
10541 Surface.unfreezeDisplay(0);
Romain Guy06882f82009-06-10 13:36:04 -070010542
Chris Tate2ad63a92009-03-25 17:36:48 -070010543 // Reset the key delivery timeout on unfreeze, too. We force a wakeup here
10544 // too because regular key delivery processing should resume immediately.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010545 synchronized (mKeyWaiter) {
10546 mKeyWaiter.mWasFrozen = true;
10547 mKeyWaiter.notifyAll();
10548 }
10549
10550 // A little kludge: a lot could have happened while the
10551 // display was frozen, so now that we are coming back we
10552 // do a gc so that any remote references the system
10553 // processes holds on others can be released if they are
10554 // no longer needed.
10555 mH.removeMessages(H.FORCE_GC);
10556 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
10557 2000);
Romain Guy06882f82009-06-10 13:36:04 -070010558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010559 mScreenFrozenLock.release();
10560 }
Romain Guy06882f82009-06-10 13:36:04 -070010561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010562 @Override
10563 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10564 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
10565 != PackageManager.PERMISSION_GRANTED) {
10566 pw.println("Permission Denial: can't dump WindowManager from from pid="
10567 + Binder.getCallingPid()
10568 + ", uid=" + Binder.getCallingUid());
10569 return;
10570 }
Romain Guy06882f82009-06-10 13:36:04 -070010571
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010572 synchronized(mWindowMap) {
10573 pw.println("Current Window Manager state:");
10574 for (int i=mWindows.size()-1; i>=0; i--) {
10575 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010576 pw.print(" Window #"); pw.print(i); pw.print(' ');
10577 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010578 w.dump(pw, " ");
10579 }
10580 if (mInputMethodDialogs.size() > 0) {
10581 pw.println(" ");
10582 pw.println(" Input method dialogs:");
10583 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
10584 WindowState w = mInputMethodDialogs.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010585 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010586 }
10587 }
10588 if (mPendingRemove.size() > 0) {
10589 pw.println(" ");
10590 pw.println(" Remove pending for:");
10591 for (int i=mPendingRemove.size()-1; i>=0; i--) {
10592 WindowState w = mPendingRemove.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010593 pw.print(" Remove #"); pw.print(i); pw.print(' ');
10594 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010595 w.dump(pw, " ");
10596 }
10597 }
10598 if (mForceRemoves != null && mForceRemoves.size() > 0) {
10599 pw.println(" ");
10600 pw.println(" Windows force removing:");
10601 for (int i=mForceRemoves.size()-1; i>=0; i--) {
10602 WindowState w = mForceRemoves.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010603 pw.print(" Removing #"); pw.print(i); pw.print(' ');
10604 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010605 w.dump(pw, " ");
10606 }
10607 }
10608 if (mDestroySurface.size() > 0) {
10609 pw.println(" ");
10610 pw.println(" Windows waiting to destroy their surface:");
10611 for (int i=mDestroySurface.size()-1; i>=0; i--) {
10612 WindowState w = mDestroySurface.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010613 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
10614 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 w.dump(pw, " ");
10616 }
10617 }
10618 if (mLosingFocus.size() > 0) {
10619 pw.println(" ");
10620 pw.println(" Windows losing focus:");
10621 for (int i=mLosingFocus.size()-1; i>=0; i--) {
10622 WindowState w = mLosingFocus.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010623 pw.print(" Losing #"); pw.print(i); pw.print(' ');
10624 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010625 w.dump(pw, " ");
10626 }
10627 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010628 if (mResizingWindows.size() > 0) {
10629 pw.println(" ");
10630 pw.println(" Windows waiting to resize:");
10631 for (int i=mResizingWindows.size()-1; i>=0; i--) {
10632 WindowState w = mResizingWindows.get(i);
10633 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
10634 pw.print(w); pw.println(":");
10635 w.dump(pw, " ");
10636 }
10637 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010638 if (mSessions.size() > 0) {
10639 pw.println(" ");
10640 pw.println(" All active sessions:");
10641 Iterator<Session> it = mSessions.iterator();
10642 while (it.hasNext()) {
10643 Session s = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010644 pw.print(" Session "); pw.print(s); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010645 s.dump(pw, " ");
10646 }
10647 }
10648 if (mTokenMap.size() > 0) {
10649 pw.println(" ");
10650 pw.println(" All tokens:");
10651 Iterator<WindowToken> it = mTokenMap.values().iterator();
10652 while (it.hasNext()) {
10653 WindowToken token = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010654 pw.print(" Token "); pw.print(token.token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010655 token.dump(pw, " ");
10656 }
10657 }
10658 if (mTokenList.size() > 0) {
10659 pw.println(" ");
10660 pw.println(" Window token list:");
10661 for (int i=0; i<mTokenList.size(); i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010662 pw.print(" #"); pw.print(i); pw.print(": ");
10663 pw.println(mTokenList.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010664 }
10665 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070010666 if (mWallpaperTokens.size() > 0) {
10667 pw.println(" ");
10668 pw.println(" Wallpaper tokens:");
10669 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
10670 WindowToken token = mWallpaperTokens.get(i);
10671 pw.print(" Wallpaper #"); pw.print(i);
10672 pw.print(' '); pw.print(token); pw.println(':');
10673 token.dump(pw, " ");
10674 }
10675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010676 if (mAppTokens.size() > 0) {
10677 pw.println(" ");
10678 pw.println(" Application tokens in Z order:");
10679 for (int i=mAppTokens.size()-1; i>=0; i--) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010680 pw.print(" App #"); pw.print(i); pw.print(": ");
10681 pw.println(mAppTokens.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010682 }
10683 }
10684 if (mFinishedStarting.size() > 0) {
10685 pw.println(" ");
10686 pw.println(" Finishing start of application tokens:");
10687 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
10688 WindowToken token = mFinishedStarting.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010689 pw.print(" Finished Starting #"); pw.print(i);
10690 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010691 token.dump(pw, " ");
10692 }
10693 }
10694 if (mExitingTokens.size() > 0) {
10695 pw.println(" ");
10696 pw.println(" Exiting tokens:");
10697 for (int i=mExitingTokens.size()-1; i>=0; i--) {
10698 WindowToken token = mExitingTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010699 pw.print(" Exiting #"); pw.print(i);
10700 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010701 token.dump(pw, " ");
10702 }
10703 }
10704 if (mExitingAppTokens.size() > 0) {
10705 pw.println(" ");
10706 pw.println(" Exiting application tokens:");
10707 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
10708 WindowToken token = mExitingAppTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010709 pw.print(" Exiting App #"); pw.print(i);
10710 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010711 token.dump(pw, " ");
10712 }
10713 }
10714 pw.println(" ");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010715 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
10716 pw.print(" mLastFocus="); pw.println(mLastFocus);
10717 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
10718 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
10719 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
Dianne Hackbornf21adf62009-08-13 10:20:21 -070010720 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
Dianne Hackborn284ac932009-08-28 10:34:25 -070010721 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
10722 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
10723 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
10724 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010725 pw.print(" mInTouchMode="); pw.println(mInTouchMode);
10726 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
10727 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
10728 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
10729 pw.print(" mBlurShown="); pw.println(mBlurShown);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010730 if (mDimAnimator != null) {
10731 mDimAnimator.printTo(pw);
10732 } else {
10733 pw.print( " no DimAnimator ");
10734 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010735 pw.print(" mInputMethodAnimLayerAdjustment=");
Dianne Hackborn759a39e2009-08-09 17:20:27 -070010736 pw.print(mInputMethodAnimLayerAdjustment);
10737 pw.print(" mWallpaperAnimLayerAdjustment=");
10738 pw.println(mWallpaperAnimLayerAdjustment);
Dianne Hackborn284ac932009-08-28 10:34:25 -070010739 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
10740 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010741 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
10742 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
10743 pw.print(" mAppsFreezingScreen="); pw.println(mAppsFreezingScreen);
10744 pw.print(" mRotation="); pw.print(mRotation);
10745 pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
10746 pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
10747 pw.print(" mAnimationPending="); pw.print(mAnimationPending);
10748 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
10749 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
10750 pw.print(" mNextAppTransition=0x");
10751 pw.print(Integer.toHexString(mNextAppTransition));
10752 pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
Dianne Hackborna8f60182009-09-01 19:01:50 -070010753 pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010754 pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010755 if (mNextAppTransitionPackage != null) {
10756 pw.print(" mNextAppTransitionPackage=");
10757 pw.print(mNextAppTransitionPackage);
10758 pw.print(", mNextAppTransitionEnter=0x");
10759 pw.print(Integer.toHexString(mNextAppTransitionEnter));
10760 pw.print(", mNextAppTransitionExit=0x");
10761 pw.print(Integer.toHexString(mNextAppTransitionExit));
10762 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010763 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
10764 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010765 if (mLastEnterAnimToken != null || mLastEnterAnimToken != null) {
10766 pw.print(" mLastEnterAnimToken="); pw.print(mLastEnterAnimToken);
10767 pw.print(", mLastEnterAnimParams="); pw.println(mLastEnterAnimParams);
10768 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010769 if (mOpeningApps.size() > 0) {
10770 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
10771 }
10772 if (mClosingApps.size() > 0) {
10773 pw.print(" mClosingApps="); pw.println(mClosingApps);
10774 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070010775 if (mToTopApps.size() > 0) {
10776 pw.print(" mToTopApps="); pw.println(mToTopApps);
10777 }
10778 if (mToBottomApps.size() > 0) {
10779 pw.print(" mToBottomApps="); pw.println(mToBottomApps);
10780 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010781 pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth());
10782 pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010783 pw.println(" KeyWaiter state:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070010784 pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin);
10785 pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
10786 pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished);
10787 pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
10788 pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
10789 pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010790 }
10791 }
10792
10793 public void monitor() {
10794 synchronized (mWindowMap) { }
10795 synchronized (mKeyguardDisabled) { }
10796 synchronized (mKeyWaiter) { }
10797 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010798
Dianne Hackbornddca3ee2009-07-23 19:01:31 -070010799 public void virtualKeyFeedback(KeyEvent event) {
10800 mPolicy.keyFeedbackFromInput(event);
10801 }
10802
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010803 /**
10804 * DimAnimator class that controls the dim animation. This holds the surface and
10805 * all state used for dim animation.
10806 */
10807 private static class DimAnimator {
10808 Surface mDimSurface;
10809 boolean mDimShown = false;
10810 float mDimCurrentAlpha;
10811 float mDimTargetAlpha;
10812 float mDimDeltaPerMs;
10813 long mLastDimAnimTime;
10814
10815 DimAnimator (SurfaceSession session) {
10816 if (mDimSurface == null) {
10817 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
10818 + mDimSurface + ": CREATE");
10819 try {
10820 mDimSurface = new Surface(session, 0, -1, 16, 16, PixelFormat.OPAQUE,
10821 Surface.FX_SURFACE_DIM);
10822 } catch (Exception e) {
10823 Log.e(TAG, "Exception creating Dim surface", e);
10824 }
10825 }
10826 }
10827
10828 /**
10829 * Show the dim surface.
10830 */
10831 void show(int dw, int dh) {
10832 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
10833 dw + "x" + dh + ")");
10834 mDimShown = true;
10835 try {
10836 mDimSurface.setPosition(0, 0);
10837 mDimSurface.setSize(dw, dh);
10838 mDimSurface.show();
10839 } catch (RuntimeException e) {
10840 Log.w(TAG, "Failure showing dim surface", e);
10841 }
10842 }
10843
10844 /**
10845 * Set's the dim surface's layer and update dim parameters that will be used in
10846 * {@link updateSurface} after all windows are examined.
10847 */
10848 void updateParameters(WindowState w, long currentTime) {
10849 mDimSurface.setLayer(w.mAnimLayer-1);
10850
10851 final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010852 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface
10853 + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010854 if (mDimTargetAlpha != target) {
10855 // If the desired dim level has changed, then
10856 // start an animation to it.
10857 mLastDimAnimTime = currentTime;
10858 long duration = (w.mAnimating && w.mAnimation != null)
10859 ? w.mAnimation.computeDurationHint()
10860 : DEFAULT_DIM_DURATION;
10861 if (target > mDimTargetAlpha) {
10862 // This is happening behind the activity UI,
10863 // so we can make it run a little longer to
10864 // give a stronger impression without disrupting
10865 // the user.
10866 duration *= DIM_DURATION_MULTIPLIER;
10867 }
10868 if (duration < 1) {
10869 // Don't divide by zero
10870 duration = 1;
10871 }
10872 mDimTargetAlpha = target;
10873 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
10874 }
10875 }
10876
10877 /**
10878 * Updating the surface's alpha. Returns true if the animation continues, or returns
10879 * false when the animation is finished and the dim surface is hidden.
10880 */
10881 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
10882 if (!dimming) {
10883 if (mDimTargetAlpha != 0) {
10884 mLastDimAnimTime = currentTime;
10885 mDimTargetAlpha = 0;
10886 mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
10887 }
10888 }
10889
10890 boolean animating = false;
10891 if (mLastDimAnimTime != 0) {
10892 mDimCurrentAlpha += mDimDeltaPerMs
10893 * (currentTime-mLastDimAnimTime);
10894 boolean more = true;
10895 if (displayFrozen) {
10896 // If the display is frozen, there is no reason to animate.
10897 more = false;
10898 } else if (mDimDeltaPerMs > 0) {
10899 if (mDimCurrentAlpha > mDimTargetAlpha) {
10900 more = false;
10901 }
10902 } else if (mDimDeltaPerMs < 0) {
10903 if (mDimCurrentAlpha < mDimTargetAlpha) {
10904 more = false;
10905 }
10906 } else {
10907 more = false;
10908 }
10909
10910 // Do we need to continue animating?
10911 if (more) {
10912 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
10913 + mDimSurface + ": alpha=" + mDimCurrentAlpha);
10914 mLastDimAnimTime = currentTime;
10915 mDimSurface.setAlpha(mDimCurrentAlpha);
10916 animating = true;
10917 } else {
10918 mDimCurrentAlpha = mDimTargetAlpha;
10919 mLastDimAnimTime = 0;
10920 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
10921 + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
10922 mDimSurface.setAlpha(mDimCurrentAlpha);
10923 if (!dimming) {
10924 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface
10925 + ": HIDE");
10926 try {
10927 mDimSurface.hide();
10928 } catch (RuntimeException e) {
10929 Log.w(TAG, "Illegal argument exception hiding dim surface");
10930 }
10931 mDimShown = false;
10932 }
10933 }
10934 }
10935 return animating;
10936 }
10937
10938 public void printTo(PrintWriter pw) {
10939 pw.print(" mDimShown="); pw.print(mDimShown);
10940 pw.print(" current="); pw.print(mDimCurrentAlpha);
10941 pw.print(" target="); pw.print(mDimTargetAlpha);
10942 pw.print(" delta="); pw.print(mDimDeltaPerMs);
10943 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
10944 }
10945 }
10946
10947 /**
10948 * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
10949 * This is used for opening/closing transition for apps in compatible mode.
10950 */
10951 private static class FadeInOutAnimation extends Animation {
10952 int mWidth;
10953 boolean mFadeIn;
10954
10955 public FadeInOutAnimation(boolean fadeIn) {
10956 setInterpolator(new AccelerateInterpolator());
10957 setDuration(DEFAULT_FADE_IN_OUT_DURATION);
10958 mFadeIn = fadeIn;
10959 }
10960
10961 @Override
10962 protected void applyTransformation(float interpolatedTime, Transformation t) {
10963 float x = interpolatedTime;
10964 if (!mFadeIn) {
10965 x = 1.0f - x; // reverse the interpolation for fade out
10966 }
10967 if (x < 0.5) {
10968 // move the window out of the screen.
10969 t.getMatrix().setTranslate(mWidth, 0);
10970 } else {
10971 t.getMatrix().setTranslate(0, 0);// show
10972 t.setAlpha((x - 0.5f) * 2);
10973 }
10974 }
10975
10976 @Override
10977 public void initialize(int width, int height, int parentWidth, int parentHeight) {
10978 // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
10979 mWidth = width;
10980 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010981
10982 @Override
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -070010983 public int getZAdjustment() {
10984 return Animation.ZORDER_TOP;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010985 }
10986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987}