blob: cf4a60e5cd27fac381ec8b3c7cbe8acee7e720eb [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import static android.os.LocalPowerManager.CHEEK_EVENT;
20import static android.os.LocalPowerManager.OTHER_EVENT;
21import static android.os.LocalPowerManager.TOUCH_EVENT;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -070022import static android.os.LocalPowerManager.LONG_TOUCH_EVENT;
23import static android.os.LocalPowerManager.TOUCH_UP_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
25import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
26import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070027import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
29import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -070030import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
32import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
33import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070034import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
36import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_PUSH_BUFFERS;
38import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
39import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
40import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
41import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070042import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043
44import com.android.internal.app.IBatteryStats;
45import com.android.internal.policy.PolicyManager;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080046import com.android.internal.policy.impl.PhoneWindowManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import com.android.internal.view.IInputContext;
48import com.android.internal.view.IInputMethodClient;
49import com.android.internal.view.IInputMethodManager;
Dianne Hackbornac3587d2010-03-11 11:12:11 -080050import com.android.internal.view.WindowManagerPolicyThread;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import com.android.server.KeyInputQueue.QueuedEvent;
52import com.android.server.am.BatteryStatsService;
53
54import android.Manifest;
55import android.app.ActivityManagerNative;
56import android.app.IActivityManager;
Jim Millerd6b57052010-06-07 17:52:42 -070057import android.app.admin.DevicePolicyManager;
Jim Miller284b62e2010-06-08 14:27:42 -070058import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import android.content.Context;
Jim Miller284b62e2010-06-08 14:27:42 -070060import android.content.Intent;
61import android.content.IntentFilter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.content.pm.ActivityInfo;
63import android.content.pm.PackageManager;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070064import android.content.res.CompatibilityInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065import android.content.res.Configuration;
66import android.graphics.Matrix;
67import android.graphics.PixelFormat;
68import android.graphics.Rect;
69import android.graphics.Region;
70import android.os.BatteryStats;
71import android.os.Binder;
Dianne Hackborn75804932009-10-20 20:15:20 -070072import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.os.Debug;
74import android.os.Handler;
75import android.os.IBinder;
Michael Chan53071d62009-05-13 17:29:48 -070076import android.os.LatencyTimer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.os.LocalPowerManager;
78import android.os.Looper;
79import android.os.Message;
80import android.os.Parcel;
81import android.os.ParcelFileDescriptor;
82import android.os.Power;
83import android.os.PowerManager;
84import android.os.Process;
85import android.os.RemoteException;
86import android.os.ServiceManager;
87import android.os.SystemClock;
88import android.os.SystemProperties;
89import android.os.TokenWatcher;
90import android.provider.Settings;
Dianne Hackborn723738c2009-06-25 19:48:04 -070091import android.util.DisplayMetrics;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092import android.util.EventLog;
Jim Millerd6b57052010-06-07 17:52:42 -070093import android.util.Log;
Joe Onorato8a9b2202010-02-26 18:56:32 -080094import android.util.Slog;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095import android.util.SparseIntArray;
96import android.view.Display;
97import android.view.Gravity;
98import android.view.IApplicationToken;
99import android.view.IOnKeyguardExitResult;
100import android.view.IRotationWatcher;
101import android.view.IWindow;
102import android.view.IWindowManager;
103import android.view.IWindowSession;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700104import android.view.InputChannel;
105import android.view.InputQueue;
106import android.view.InputTarget;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107import android.view.KeyEvent;
108import android.view.MotionEvent;
109import android.view.RawInputEvent;
110import android.view.Surface;
111import android.view.SurfaceSession;
112import android.view.View;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700113import android.view.ViewConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114import android.view.ViewTreeObserver;
115import android.view.WindowManager;
116import android.view.WindowManagerImpl;
117import android.view.WindowManagerPolicy;
118import android.view.WindowManager.LayoutParams;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700119import android.view.animation.AccelerateInterpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120import android.view.animation.Animation;
121import android.view.animation.AnimationUtils;
122import android.view.animation.Transformation;
123
124import java.io.BufferedWriter;
125import java.io.File;
126import java.io.FileDescriptor;
127import java.io.IOException;
128import java.io.OutputStream;
129import java.io.OutputStreamWriter;
130import java.io.PrintWriter;
131import java.io.StringWriter;
132import java.net.Socket;
133import java.util.ArrayList;
134import java.util.HashMap;
135import java.util.HashSet;
136import java.util.Iterator;
137import java.util.List;
138
139/** {@hide} */
Dianne Hackbornddca3ee2009-07-23 19:01:31 -0700140public class WindowManagerService extends IWindowManager.Stub
141 implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 static final String TAG = "WindowManager";
143 static final boolean DEBUG = false;
144 static final boolean DEBUG_FOCUS = false;
145 static final boolean DEBUG_ANIM = false;
Dianne Hackborn9b52a212009-12-11 14:51:35 -0800146 static final boolean DEBUG_LAYOUT = false;
Dianne Hackbornac3587d2010-03-11 11:12:11 -0800147 static final boolean DEBUG_RESIZE = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 static final boolean DEBUG_LAYERS = false;
149 static final boolean DEBUG_INPUT = false;
150 static final boolean DEBUG_INPUT_METHOD = false;
151 static final boolean DEBUG_VISIBILITY = false;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -0700152 static final boolean DEBUG_WINDOW_MOVEMENT = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 static final boolean DEBUG_ORIENTATION = false;
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700154 static final boolean DEBUG_CONFIGURATION = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 static final boolean DEBUG_APP_TRANSITIONS = false;
156 static final boolean DEBUG_STARTING_WINDOW = false;
157 static final boolean DEBUG_REORDER = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700158 static final boolean DEBUG_WALLPAPER = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 static final boolean SHOW_TRANSACTIONS = false;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700160 static final boolean HIDE_STACK_CRAWLS = true;
Michael Chan53071d62009-05-13 17:29:48 -0700161 static final boolean MEASURE_LATENCY = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700162 static final boolean ENABLE_NATIVE_INPUT_DISPATCH =
163 WindowManagerPolicy.ENABLE_NATIVE_INPUT_DISPATCH;
Michael Chan53071d62009-05-13 17:29:48 -0700164 static private LatencyTimer lt;
165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 static final boolean PROFILE_ORIENTATION = false;
167 static final boolean BLUR = true;
Dave Bortcfe65242009-04-09 14:51:04 -0700168 static final boolean localLOGV = DEBUG;
Romain Guy06882f82009-06-10 13:36:04 -0700169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800170 /** How long to wait for subsequent key repeats, in milliseconds */
171 static final int KEY_REPEAT_DELAY = 50;
172
173 /** How much to multiply the policy's type layer, to reserve room
174 * for multiple windows of the same type and Z-ordering adjustment
175 * with TYPE_LAYER_OFFSET. */
176 static final int TYPE_LAYER_MULTIPLIER = 10000;
Romain Guy06882f82009-06-10 13:36:04 -0700177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
179 * or below others in the same layer. */
180 static final int TYPE_LAYER_OFFSET = 1000;
Romain Guy06882f82009-06-10 13:36:04 -0700181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 /** How much to increment the layer for each window, to reserve room
183 * for effect surfaces between them.
184 */
185 static final int WINDOW_LAYER_MULTIPLIER = 5;
Romain Guy06882f82009-06-10 13:36:04 -0700186
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 /** The maximum length we will accept for a loaded animation duration:
188 * this is 10 seconds.
189 */
190 static final int MAX_ANIMATION_DURATION = 10*1000;
191
192 /** Amount of time (in milliseconds) to animate the dim surface from one
193 * value to another, when no window animation is driving it.
194 */
195 static final int DEFAULT_DIM_DURATION = 200;
196
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700197 /** Amount of time (in milliseconds) to animate the fade-in-out transition for
198 * compatible windows.
199 */
200 static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 /** Adjustment to time to perform a dim, to make it more dramatic.
203 */
204 static final int DIM_DURATION_MULTIPLIER = 6;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700205
206 // Maximum number of milliseconds to wait for input event injection.
207 // FIXME is this value reasonable?
208 private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
Romain Guy06882f82009-06-10 13:36:04 -0700209
Dianne Hackborncfaef692009-06-15 14:24:44 -0700210 static final int INJECT_FAILED = 0;
211 static final int INJECT_SUCCEEDED = 1;
212 static final int INJECT_NO_PERMISSION = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 static final int UPDATE_FOCUS_NORMAL = 0;
215 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
216 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
217 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
Romain Guy06882f82009-06-10 13:36:04 -0700218
Michael Chane96440f2009-05-06 10:27:36 -0700219 /** The minimum time between dispatching touch events. */
220 int mMinWaitTimeBetweenTouchEvents = 1000 / 35;
221
222 // Last touch event time
223 long mLastTouchEventTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700224
Michael Chane96440f2009-05-06 10:27:36 -0700225 // Last touch event type
226 int mLastTouchEventType = OTHER_EVENT;
Romain Guy06882f82009-06-10 13:36:04 -0700227
Michael Chane96440f2009-05-06 10:27:36 -0700228 // Time to wait before calling useractivity again. This saves CPU usage
229 // when we get a flood of touch events.
230 static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000;
231
232 // Last time we call user activity
233 long mLastUserActivityCallTime = 0;
234
Romain Guy06882f82009-06-10 13:36:04 -0700235 // Last time we updated battery stats
Michael Chane96440f2009-05-06 10:27:36 -0700236 long mLastBatteryStatsCallTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 private static final String SYSTEM_SECURE = "ro.secure";
Romain Guy06882f82009-06-10 13:36:04 -0700239 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240
241 /**
242 * Condition waited on by {@link #reenableKeyguard} to know the call to
243 * the window policy has finished.
Mike Lockwood983ee092009-11-22 01:42:24 -0500244 * This is set to true only if mKeyguardTokenWatcher.acquired() has
245 * actually disabled the keyguard.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 */
Mike Lockwood983ee092009-11-22 01:42:24 -0500247 private boolean mKeyguardDisabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248
Jim Miller284b62e2010-06-08 14:27:42 -0700249 private static final int ALLOW_DISABLE_YES = 1;
250 private static final int ALLOW_DISABLE_NO = 0;
251 private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
252 private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
253
Mike Lockwood983ee092009-11-22 01:42:24 -0500254 final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
255 new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 public void acquired() {
Jim Miller284b62e2010-06-08 14:27:42 -0700257 if (shouldAllowDisableKeyguard()) {
258 mPolicy.enableKeyguard(false);
259 mKeyguardDisabled = true;
260 } else {
261 Log.v(TAG, "Not disabling keyguard since device policy is enforced");
262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 }
264 public void released() {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700265 mPolicy.enableKeyguard(true);
Mike Lockwood983ee092009-11-22 01:42:24 -0500266 synchronized (mKeyguardTokenWatcher) {
267 mKeyguardDisabled = false;
268 mKeyguardTokenWatcher.notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 }
270 }
271 };
272
Jim Miller284b62e2010-06-08 14:27:42 -0700273 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
274 @Override
275 public void onReceive(Context context, Intent intent) {
276 mPolicy.enableKeyguard(true);
277 synchronized(mKeyguardTokenWatcher) {
278 // lazily evaluate this next time we're asked to disable keyguard
279 mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
280 mKeyguardDisabled = false;
281 }
282 }
283 };
284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285 final Context mContext;
286
287 final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 final boolean mLimitedAlphaCompositing;
Romain Guy06882f82009-06-10 13:36:04 -0700290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
292
293 final IActivityManager mActivityManager;
Romain Guy06882f82009-06-10 13:36:04 -0700294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295 final IBatteryStats mBatteryStats;
Romain Guy06882f82009-06-10 13:36:04 -0700296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 /**
298 * All currently active sessions with clients.
299 */
300 final HashSet<Session> mSessions = new HashSet<Session>();
Romain Guy06882f82009-06-10 13:36:04 -0700301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 /**
303 * Mapping from an IWindow IBinder to the server's Window object.
304 * This is also used as the lock for all of our state.
305 */
306 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
307
308 /**
309 * Mapping from a token IBinder to a WindowToken object.
310 */
311 final HashMap<IBinder, WindowToken> mTokenMap =
312 new HashMap<IBinder, WindowToken>();
313
314 /**
315 * The same tokens as mTokenMap, stored in a list for efficient iteration
316 * over them.
317 */
318 final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 /**
321 * Window tokens that are in the process of exiting, but still
322 * on screen for animations.
323 */
324 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
325
326 /**
327 * Z-ordered (bottom-most first) list of all application tokens, for
328 * controlling the ordering of windows in different applications. This
329 * contains WindowToken objects.
330 */
331 final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
332
333 /**
334 * Application tokens that are in the process of exiting, but still
335 * on screen for animations.
336 */
337 final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
338
339 /**
340 * List of window tokens that have finished starting their application,
341 * and now need to have the policy remove their windows.
342 */
343 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
344
345 /**
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700346 * This was the app token that was used to retrieve the last enter
347 * animation. It will be used for the next exit animation.
348 */
349 AppWindowToken mLastEnterAnimToken;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800350
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700351 /**
352 * These were the layout params used to retrieve the last enter animation.
353 * They will be used for the next exit animation.
354 */
355 LayoutParams mLastEnterAnimParams;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800356
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700357 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800358 * Z-ordered (bottom-most first) list of all Window objects.
359 */
360 final ArrayList mWindows = new ArrayList();
361
362 /**
363 * Windows that are being resized. Used so we can tell the client about
364 * the resize after closing the transaction in which we resized the
365 * underlying surface.
366 */
367 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
368
369 /**
370 * Windows whose animations have ended and now must be removed.
371 */
372 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
373
374 /**
375 * Windows whose surface should be destroyed.
376 */
377 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
378
379 /**
380 * Windows that have lost input focus and are waiting for the new
381 * focus window to be displayed before they are told about this.
382 */
383 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
384
385 /**
386 * This is set when we have run out of memory, and will either be an empty
387 * list or contain windows that need to be force removed.
388 */
389 ArrayList<WindowState> mForceRemoves;
Romain Guy06882f82009-06-10 13:36:04 -0700390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 IInputMethodManager mInputMethodManager;
Romain Guy06882f82009-06-10 13:36:04 -0700392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 SurfaceSession mFxSession;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700394 private DimAnimator mDimAnimator = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800395 Surface mBlurSurface;
396 boolean mBlurShown;
Romain Guy06882f82009-06-10 13:36:04 -0700397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 int mTransactionSequence = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 final float[] mTmpFloats = new float[9];
401
402 boolean mSafeMode;
403 boolean mDisplayEnabled = false;
404 boolean mSystemBooted = false;
Christopher Tateb696aee2010-04-02 19:08:30 -0700405 int mInitialDisplayWidth = 0;
406 int mInitialDisplayHeight = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800407 int mRotation = 0;
408 int mRequestedRotation = 0;
409 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Dianne Hackborn321ae682009-03-27 16:16:03 -0700410 int mLastRotationFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 ArrayList<IRotationWatcher> mRotationWatchers
412 = new ArrayList<IRotationWatcher>();
Romain Guy06882f82009-06-10 13:36:04 -0700413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 boolean mLayoutNeeded = true;
415 boolean mAnimationPending = false;
416 boolean mDisplayFrozen = false;
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800417 boolean mWaitingForConfig = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 boolean mWindowsFreezingScreen = false;
419 long mFreezeGcPending = 0;
420 int mAppsFreezingScreen = 0;
421
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800422 int mLayoutSeq = 0;
423
Dianne Hackbornb601ce12010-03-01 23:36:02 -0800424 // State while inside of layoutAndPlaceSurfacesLocked().
425 boolean mFocusMayChange;
426
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800427 Configuration mCurConfiguration = new Configuration();
428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 // This is held as long as we have the screen frozen, to give us time to
430 // perform a rotation animation when turning off shows the lock screen which
431 // changes the orientation.
432 PowerManager.WakeLock mScreenFrozenLock;
Romain Guy06882f82009-06-10 13:36:04 -0700433
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 // State management of app transitions. When we are preparing for a
435 // transition, mNextAppTransition will be the kind of transition to
436 // perform or TRANSIT_NONE if we are not waiting. If we are waiting,
437 // mOpeningApps and mClosingApps are the lists of tokens that will be
438 // made visible or hidden at the next transition.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700439 int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700440 String mNextAppTransitionPackage;
441 int mNextAppTransitionEnter;
442 int mNextAppTransitionExit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 boolean mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -0700444 boolean mAppTransitionRunning = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 boolean mAppTransitionTimeout = false;
446 boolean mStartingIconInTransition = false;
447 boolean mSkipAppTransitionAnimation = false;
448 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
449 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
Dianne Hackborna8f60182009-09-01 19:01:50 -0700450 final ArrayList<AppWindowToken> mToTopApps = new ArrayList<AppWindowToken>();
451 final ArrayList<AppWindowToken> mToBottomApps = new ArrayList<AppWindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 Display mDisplay;
Romain Guy06882f82009-06-10 13:36:04 -0700454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800455 H mH = new H();
456
457 WindowState mCurrentFocus = null;
458 WindowState mLastFocus = null;
Romain Guy06882f82009-06-10 13:36:04 -0700459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 // This just indicates the window the input method is on top of, not
461 // necessarily the window its input is going to.
462 WindowState mInputMethodTarget = null;
463 WindowState mUpcomingInputMethodTarget = null;
464 boolean mInputMethodTargetWaitingAnim;
465 int mInputMethodAnimLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -0700466
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 WindowState mInputMethodWindow = null;
468 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
469
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700470 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800471
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700472 // If non-null, this is the currently visible window that is associated
473 // with the wallpaper.
474 WindowState mWallpaperTarget = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700475 // If non-null, we are in the middle of animating from one wallpaper target
476 // to another, and this is the lower one in Z-order.
477 WindowState mLowerWallpaperTarget = null;
478 // If non-null, we are in the middle of animating from one wallpaper target
479 // to another, and this is the higher one in Z-order.
480 WindowState mUpperWallpaperTarget = null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700481 int mWallpaperAnimLayerAdjustment;
Dianne Hackborn73e92b42009-10-15 14:29:19 -0700482 float mLastWallpaperX = -1;
483 float mLastWallpaperY = -1;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800484 float mLastWallpaperXStep = -1;
485 float mLastWallpaperYStep = -1;
Dianne Hackborn6adba242009-11-10 11:10:09 -0800486 boolean mSendingPointersToWallpaper = false;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700487 // This is set when we are waiting for a wallpaper to tell us it is done
488 // changing its scroll position.
489 WindowState mWaitingOnWallpaper;
490 // The last time we had a timeout when waiting for a wallpaper.
491 long mLastWallpaperTimeoutTime;
492 // We give a wallpaper up to 150ms to finish scrolling.
493 static final long WALLPAPER_TIMEOUT = 150;
494 // Time we wait after a timeout before trying to wait again.
495 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 AppWindowToken mFocusedApp = null;
498
499 PowerManagerService mPowerManager;
Romain Guy06882f82009-06-10 13:36:04 -0700500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 float mWindowAnimationScale = 1.0f;
502 float mTransitionAnimationScale = 1.0f;
Romain Guy06882f82009-06-10 13:36:04 -0700503
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 final KeyWaiter mKeyWaiter = new KeyWaiter();
505 final KeyQ mQueue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700506 final InputManager mInputManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 final InputDispatcherThread mInputThread;
508
509 // Who is holding the screen on.
510 Session mHoldingScreenOn;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700511 PowerManager.WakeLock mHoldingScreenWakeLock;
Romain Guy06882f82009-06-10 13:36:04 -0700512
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700513 boolean mTurnOnScreen;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800514
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 /**
516 * Whether the UI is currently running in touch mode (not showing
517 * navigational focus because the user is directly pressing the screen).
518 */
519 boolean mInTouchMode = false;
520
521 private ViewServer mViewServer;
522
523 final Rect mTempRect = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -0700524
Dianne Hackbornc485a602009-03-24 22:39:49 -0700525 final Configuration mTempConfiguration = new Configuration();
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700526 int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700527
528 // The frame use to limit the size of the app running in compatibility mode.
529 Rect mCompatibleScreenFrame = new Rect();
530 // The surface used to fill the outer rim of the app running in compatibility mode.
531 Surface mBackgroundFillerSurface = null;
532 boolean mBackgroundFillerShown = false;
533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 public static WindowManagerService main(Context context,
535 PowerManagerService pm, boolean haveInputMethods) {
536 WMThread thr = new WMThread(context, pm, haveInputMethods);
537 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 synchronized (thr) {
540 while (thr.mService == null) {
541 try {
542 thr.wait();
543 } catch (InterruptedException e) {
544 }
545 }
546 }
Romain Guy06882f82009-06-10 13:36:04 -0700547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 return thr.mService;
549 }
Romain Guy06882f82009-06-10 13:36:04 -0700550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 static class WMThread extends Thread {
552 WindowManagerService mService;
Romain Guy06882f82009-06-10 13:36:04 -0700553
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 private final Context mContext;
555 private final PowerManagerService mPM;
556 private final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 public WMThread(Context context, PowerManagerService pm,
559 boolean haveInputMethods) {
560 super("WindowManager");
561 mContext = context;
562 mPM = pm;
563 mHaveInputMethods = haveInputMethods;
564 }
Romain Guy06882f82009-06-10 13:36:04 -0700565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 public void run() {
567 Looper.prepare();
568 WindowManagerService s = new WindowManagerService(mContext, mPM,
569 mHaveInputMethods);
570 android.os.Process.setThreadPriority(
571 android.os.Process.THREAD_PRIORITY_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -0700572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800573 synchronized (this) {
574 mService = s;
575 notifyAll();
576 }
Romain Guy06882f82009-06-10 13:36:04 -0700577
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800578 Looper.loop();
579 }
580 }
581
582 static class PolicyThread extends Thread {
583 private final WindowManagerPolicy mPolicy;
584 private final WindowManagerService mService;
585 private final Context mContext;
586 private final PowerManagerService mPM;
587 boolean mRunning = false;
Romain Guy06882f82009-06-10 13:36:04 -0700588
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800589 public PolicyThread(WindowManagerPolicy policy,
590 WindowManagerService service, Context context,
591 PowerManagerService pm) {
592 super("WindowManagerPolicy");
593 mPolicy = policy;
594 mService = service;
595 mContext = context;
596 mPM = pm;
597 }
Romain Guy06882f82009-06-10 13:36:04 -0700598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800599 public void run() {
600 Looper.prepare();
Dianne Hackbornac3587d2010-03-11 11:12:11 -0800601 WindowManagerPolicyThread.set(this, Looper.myLooper());
602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 //Looper.myLooper().setMessageLogging(new LogPrinter(
Joe Onorato8a9b2202010-02-26 18:56:32 -0800604 // Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 android.os.Process.setThreadPriority(
606 android.os.Process.THREAD_PRIORITY_FOREGROUND);
607 mPolicy.init(mContext, mService, mPM);
Romain Guy06882f82009-06-10 13:36:04 -0700608
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800609 synchronized (this) {
610 mRunning = true;
611 notifyAll();
612 }
Romain Guy06882f82009-06-10 13:36:04 -0700613
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 Looper.loop();
615 }
616 }
617
618 private WindowManagerService(Context context, PowerManagerService pm,
619 boolean haveInputMethods) {
Michael Chan53071d62009-05-13 17:29:48 -0700620 if (MEASURE_LATENCY) {
621 lt = new LatencyTimer(100, 1000);
622 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 mContext = context;
625 mHaveInputMethods = haveInputMethods;
626 mLimitedAlphaCompositing = context.getResources().getBoolean(
627 com.android.internal.R.bool.config_sf_limitedAlpha);
Romain Guy06882f82009-06-10 13:36:04 -0700628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 mPowerManager = pm;
630 mPowerManager.setPolicy(mPolicy);
631 PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
632 mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
633 "SCREEN_FROZEN");
634 mScreenFrozenLock.setReferenceCounted(false);
635
636 mActivityManager = ActivityManagerNative.getDefault();
637 mBatteryStats = BatteryStatsService.getService();
638
639 // Get persisted window scale setting
640 mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
641 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
642 mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
643 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
Romain Guy06882f82009-06-10 13:36:04 -0700644
Jim Miller284b62e2010-06-08 14:27:42 -0700645 // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
646 IntentFilter filter = new IntentFilter();
647 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
648 mContext.registerReceiver(mBroadcastReceiver, filter);
649
Michael Chan9f028e62009-08-04 17:37:46 -0700650 int max_events_per_sec = 35;
651 try {
652 max_events_per_sec = Integer.parseInt(SystemProperties
653 .get("windowsmgr.max_events_per_sec"));
654 if (max_events_per_sec < 1) {
655 max_events_per_sec = 35;
656 }
657 } catch (NumberFormatException e) {
658 }
659 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
660
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700661 mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
662 "KEEP_SCREEN_ON_FLAG");
663 mHoldingScreenWakeLock.setReferenceCounted(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700665 if (ENABLE_NATIVE_INPUT_DISPATCH) {
666 mInputManager = new InputManager(context, this, mPolicy, pmc, mPowerManager);
667 } else {
668 mInputManager = null;
669 }
670 mQueue = new KeyQ();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671 mInputThread = new InputDispatcherThread();
Romain Guy06882f82009-06-10 13:36:04 -0700672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800673 PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
674 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 synchronized (thr) {
677 while (!thr.mRunning) {
678 try {
679 thr.wait();
680 } catch (InterruptedException e) {
681 }
682 }
683 }
Romain Guy06882f82009-06-10 13:36:04 -0700684
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700685 if (ENABLE_NATIVE_INPUT_DISPATCH) {
686 mInputManager.start();
687 } else {
688 mInputThread.start();
689 }
Romain Guy06882f82009-06-10 13:36:04 -0700690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800691 // Add ourself to the Watchdog monitors.
692 Watchdog.getInstance().addMonitor(this);
693 }
694
695 @Override
696 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
697 throws RemoteException {
698 try {
699 return super.onTransact(code, data, reply, flags);
700 } catch (RuntimeException e) {
701 // The window manager only throws security exceptions, so let's
702 // log all others.
703 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800704 Slog.e(TAG, "Window Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 }
706 throw e;
707 }
708 }
709
710 private void placeWindowAfter(Object pos, WindowState window) {
711 final int i = mWindows.indexOf(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800712 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 TAG, "Adding window " + window + " at "
714 + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
715 mWindows.add(i+1, window);
716 }
717
718 private void placeWindowBefore(Object pos, WindowState window) {
719 final int i = mWindows.indexOf(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800720 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800721 TAG, "Adding window " + window + " at "
722 + i + " of " + mWindows.size() + " (before " + pos + ")");
723 mWindows.add(i, window);
724 }
725
726 //This method finds out the index of a window that has the same app token as
727 //win. used for z ordering the windows in mWindows
728 private int findIdxBasedOnAppTokens(WindowState win) {
729 //use a local variable to cache mWindows
730 ArrayList localmWindows = mWindows;
731 int jmax = localmWindows.size();
732 if(jmax == 0) {
733 return -1;
734 }
735 for(int j = (jmax-1); j >= 0; j--) {
736 WindowState wentry = (WindowState)localmWindows.get(j);
737 if(wentry.mAppToken == win.mAppToken) {
738 return j;
739 }
740 }
741 return -1;
742 }
Romain Guy06882f82009-06-10 13:36:04 -0700743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744 private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
745 final IWindow client = win.mClient;
746 final WindowToken token = win.mToken;
747 final ArrayList localmWindows = mWindows;
Romain Guy06882f82009-06-10 13:36:04 -0700748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749 final int N = localmWindows.size();
750 final WindowState attached = win.mAttachedWindow;
751 int i;
752 if (attached == null) {
753 int tokenWindowsPos = token.windows.size();
754 if (token.appWindowToken != null) {
755 int index = tokenWindowsPos-1;
756 if (index >= 0) {
757 // If this application has existing windows, we
758 // simply place the new window on top of them... but
759 // keep the starting window on top.
760 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
761 // Base windows go behind everything else.
762 placeWindowBefore(token.windows.get(0), win);
763 tokenWindowsPos = 0;
764 } else {
765 AppWindowToken atoken = win.mAppToken;
766 if (atoken != null &&
767 token.windows.get(index) == atoken.startingWindow) {
768 placeWindowBefore(token.windows.get(index), win);
769 tokenWindowsPos--;
770 } else {
771 int newIdx = findIdxBasedOnAppTokens(win);
772 if(newIdx != -1) {
Romain Guy06882f82009-06-10 13:36:04 -0700773 //there is a window above this one associated with the same
774 //apptoken note that the window could be a floating window
775 //that was created later or a window at the top of the list of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776 //windows associated with this token.
Joe Onorato8a9b2202010-02-26 18:56:32 -0800777 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700778 TAG, "Adding window " + win + " at "
779 + (newIdx+1) + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 localmWindows.add(newIdx+1, win);
Romain Guy06882f82009-06-10 13:36:04 -0700781 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 }
783 }
784 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800785 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 TAG, "Figuring out where to add app window "
787 + client.asBinder() + " (token=" + token + ")");
788 // Figure out where the window should go, based on the
789 // order of applications.
790 final int NA = mAppTokens.size();
791 Object pos = null;
792 for (i=NA-1; i>=0; i--) {
793 AppWindowToken t = mAppTokens.get(i);
794 if (t == token) {
795 i--;
796 break;
797 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800798
Dianne Hackborna8f60182009-09-01 19:01:50 -0700799 // We haven't reached the token yet; if this token
800 // is not going to the bottom and has windows, we can
801 // use it as an anchor for when we do reach the token.
802 if (!t.sendingToBottom && t.windows.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800803 pos = t.windows.get(0);
804 }
805 }
806 // We now know the index into the apps. If we found
807 // an app window above, that gives us the position; else
808 // we need to look some more.
809 if (pos != null) {
810 // Move behind any windows attached to this one.
Romain Guy06882f82009-06-10 13:36:04 -0700811 WindowToken atoken =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812 mTokenMap.get(((WindowState)pos).mClient.asBinder());
813 if (atoken != null) {
814 final int NC = atoken.windows.size();
815 if (NC > 0) {
816 WindowState bottom = atoken.windows.get(0);
817 if (bottom.mSubLayer < 0) {
818 pos = bottom;
819 }
820 }
821 }
822 placeWindowBefore(pos, win);
823 } else {
Dianne Hackborna8f60182009-09-01 19:01:50 -0700824 // Continue looking down until we find the first
825 // token that has windows.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 while (i >= 0) {
827 AppWindowToken t = mAppTokens.get(i);
828 final int NW = t.windows.size();
829 if (NW > 0) {
830 pos = t.windows.get(NW-1);
831 break;
832 }
833 i--;
834 }
835 if (pos != null) {
836 // Move in front of any windows attached to this
837 // one.
838 WindowToken atoken =
839 mTokenMap.get(((WindowState)pos).mClient.asBinder());
840 if (atoken != null) {
841 final int NC = atoken.windows.size();
842 if (NC > 0) {
843 WindowState top = atoken.windows.get(NC-1);
844 if (top.mSubLayer >= 0) {
845 pos = top;
846 }
847 }
848 }
849 placeWindowAfter(pos, win);
850 } else {
851 // Just search for the start of this layer.
852 final int myLayer = win.mBaseLayer;
853 for (i=0; i<N; i++) {
854 WindowState w = (WindowState)localmWindows.get(i);
855 if (w.mBaseLayer > myLayer) {
856 break;
857 }
858 }
Joe Onorato8a9b2202010-02-26 18:56:32 -0800859 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700860 TAG, "Adding window " + win + " at "
861 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 localmWindows.add(i, win);
863 }
864 }
865 }
866 } else {
867 // Figure out where window should go, based on layer.
868 final int myLayer = win.mBaseLayer;
869 for (i=N-1; i>=0; i--) {
870 if (((WindowState)localmWindows.get(i)).mBaseLayer <= myLayer) {
871 i++;
872 break;
873 }
874 }
875 if (i < 0) i = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800876 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700877 TAG, "Adding window " + win + " at "
878 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 localmWindows.add(i, win);
880 }
881 if (addToToken) {
882 token.windows.add(tokenWindowsPos, win);
883 }
884
885 } else {
886 // Figure out this window's ordering relative to the window
887 // it is attached to.
888 final int NA = token.windows.size();
889 final int sublayer = win.mSubLayer;
890 int largestSublayer = Integer.MIN_VALUE;
891 WindowState windowWithLargestSublayer = null;
892 for (i=0; i<NA; i++) {
893 WindowState w = token.windows.get(i);
894 final int wSublayer = w.mSubLayer;
895 if (wSublayer >= largestSublayer) {
896 largestSublayer = wSublayer;
897 windowWithLargestSublayer = w;
898 }
899 if (sublayer < 0) {
900 // For negative sublayers, we go below all windows
901 // in the same sublayer.
902 if (wSublayer >= sublayer) {
903 if (addToToken) {
904 token.windows.add(i, win);
905 }
906 placeWindowBefore(
907 wSublayer >= 0 ? attached : w, win);
908 break;
909 }
910 } else {
911 // For positive sublayers, we go above all windows
912 // in the same sublayer.
913 if (wSublayer > sublayer) {
914 if (addToToken) {
915 token.windows.add(i, win);
916 }
917 placeWindowBefore(w, win);
918 break;
919 }
920 }
921 }
922 if (i >= NA) {
923 if (addToToken) {
924 token.windows.add(win);
925 }
926 if (sublayer < 0) {
927 placeWindowBefore(attached, win);
928 } else {
929 placeWindowAfter(largestSublayer >= 0
930 ? windowWithLargestSublayer
931 : attached,
932 win);
933 }
934 }
935 }
Romain Guy06882f82009-06-10 13:36:04 -0700936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937 if (win.mAppToken != null && addToToken) {
938 win.mAppToken.allAppWindows.add(win);
939 }
940 }
Romain Guy06882f82009-06-10 13:36:04 -0700941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 static boolean canBeImeTarget(WindowState w) {
943 final int fl = w.mAttrs.flags
944 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
945 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
946 return w.isVisibleOrAdding();
947 }
948 return false;
949 }
Romain Guy06882f82009-06-10 13:36:04 -0700950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
952 final ArrayList localmWindows = mWindows;
953 final int N = localmWindows.size();
954 WindowState w = null;
955 int i = N;
956 while (i > 0) {
957 i--;
958 w = (WindowState)localmWindows.get(i);
Romain Guy06882f82009-06-10 13:36:04 -0700959
Joe Onorato8a9b2202010-02-26 18:56:32 -0800960 //Slog.i(TAG, "Checking window @" + i + " " + w + " fl=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 // + Integer.toHexString(w.mAttrs.flags));
962 if (canBeImeTarget(w)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800963 //Slog.i(TAG, "Putting input method here!");
Romain Guy06882f82009-06-10 13:36:04 -0700964
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 // Yet more tricksyness! If this window is a "starting"
966 // window, we do actually want to be on top of it, but
967 // it is not -really- where input will go. So if the caller
968 // is not actually looking to move the IME, look down below
969 // for a real window to target...
970 if (!willMove
971 && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
972 && i > 0) {
973 WindowState wb = (WindowState)localmWindows.get(i-1);
974 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
975 i--;
976 w = wb;
977 }
978 }
979 break;
980 }
981 }
Romain Guy06882f82009-06-10 13:36:04 -0700982
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800983 mUpcomingInputMethodTarget = w;
Romain Guy06882f82009-06-10 13:36:04 -0700984
Joe Onorato8a9b2202010-02-26 18:56:32 -0800985 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800986 + w + " willMove=" + willMove);
Romain Guy06882f82009-06-10 13:36:04 -0700987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 if (willMove && w != null) {
989 final WindowState curTarget = mInputMethodTarget;
990 if (curTarget != null && curTarget.mAppToken != null) {
Romain Guy06882f82009-06-10 13:36:04 -0700991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 // Now some fun for dealing with window animations that
993 // modify the Z order. We need to look at all windows below
994 // the current target that are in this app, finding the highest
995 // visible one in layering.
996 AppWindowToken token = curTarget.mAppToken;
997 WindowState highestTarget = null;
998 int highestPos = 0;
999 if (token.animating || token.animation != null) {
1000 int pos = 0;
1001 pos = localmWindows.indexOf(curTarget);
1002 while (pos >= 0) {
1003 WindowState win = (WindowState)localmWindows.get(pos);
1004 if (win.mAppToken != token) {
1005 break;
1006 }
1007 if (!win.mRemoved) {
1008 if (highestTarget == null || win.mAnimLayer >
1009 highestTarget.mAnimLayer) {
1010 highestTarget = win;
1011 highestPos = pos;
1012 }
1013 }
1014 pos--;
1015 }
1016 }
Romain Guy06882f82009-06-10 13:36:04 -07001017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001018 if (highestTarget != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001019 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "mNextAppTransition="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 + mNextAppTransition + " " + highestTarget
1021 + " animating=" + highestTarget.isAnimating()
1022 + " layer=" + highestTarget.mAnimLayer
1023 + " new layer=" + w.mAnimLayer);
Romain Guy06882f82009-06-10 13:36:04 -07001024
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001025 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 // If we are currently setting up for an animation,
1027 // hold everything until we can find out what will happen.
1028 mInputMethodTargetWaitingAnim = true;
1029 mInputMethodTarget = highestTarget;
1030 return highestPos + 1;
1031 } else if (highestTarget.isAnimating() &&
1032 highestTarget.mAnimLayer > w.mAnimLayer) {
1033 // If the window we are currently targeting is involved
1034 // with an animation, and it is on top of the next target
1035 // we will be over, then hold off on moving until
1036 // that is done.
1037 mInputMethodTarget = highestTarget;
1038 return highestPos + 1;
1039 }
1040 }
1041 }
1042 }
Romain Guy06882f82009-06-10 13:36:04 -07001043
Joe Onorato8a9b2202010-02-26 18:56:32 -08001044 //Slog.i(TAG, "Placing input method @" + (i+1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 if (w != null) {
1046 if (willMove) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08001047 if (DEBUG_INPUT_METHOD) {
1048 RuntimeException e = null;
1049 if (!HIDE_STACK_CRAWLS) {
1050 e = new RuntimeException();
1051 e.fillInStackTrace();
1052 }
1053 Slog.w(TAG, "Moving IM target from "
1054 + mInputMethodTarget + " to " + w, e);
1055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001056 mInputMethodTarget = w;
1057 if (w.mAppToken != null) {
1058 setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
1059 } else {
1060 setInputMethodAnimLayerAdjustment(0);
1061 }
1062 }
1063 return i+1;
1064 }
1065 if (willMove) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08001066 if (DEBUG_INPUT_METHOD) {
1067 RuntimeException e = null;
1068 if (!HIDE_STACK_CRAWLS) {
1069 e = new RuntimeException();
1070 e.fillInStackTrace();
1071 }
1072 Slog.w(TAG, "Moving IM target from "
1073 + mInputMethodTarget + " to null", e);
1074 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 mInputMethodTarget = null;
1076 setInputMethodAnimLayerAdjustment(0);
1077 }
1078 return -1;
1079 }
Romain Guy06882f82009-06-10 13:36:04 -07001080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001081 void addInputMethodWindowToListLocked(WindowState win) {
1082 int pos = findDesiredInputMethodWindowIndexLocked(true);
1083 if (pos >= 0) {
1084 win.mTargetAppToken = mInputMethodTarget.mAppToken;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001085 if (DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001086 TAG, "Adding input method window " + win + " at " + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 mWindows.add(pos, win);
1088 moveInputMethodDialogsLocked(pos+1);
1089 return;
1090 }
1091 win.mTargetAppToken = null;
1092 addWindowToListInOrderLocked(win, true);
1093 moveInputMethodDialogsLocked(pos);
1094 }
Romain Guy06882f82009-06-10 13:36:04 -07001095
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 void setInputMethodAnimLayerAdjustment(int adj) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001097 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 mInputMethodAnimLayerAdjustment = adj;
1099 WindowState imw = mInputMethodWindow;
1100 if (imw != null) {
1101 imw.mAnimLayer = imw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001102 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 + " anim layer: " + imw.mAnimLayer);
1104 int wi = imw.mChildWindows.size();
1105 while (wi > 0) {
1106 wi--;
1107 WindowState cw = (WindowState)imw.mChildWindows.get(wi);
1108 cw.mAnimLayer = cw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001109 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 + " anim layer: " + cw.mAnimLayer);
1111 }
1112 }
1113 int di = mInputMethodDialogs.size();
1114 while (di > 0) {
1115 di --;
1116 imw = mInputMethodDialogs.get(di);
1117 imw.mAnimLayer = imw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001118 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 + " anim layer: " + imw.mAnimLayer);
1120 }
1121 }
Romain Guy06882f82009-06-10 13:36:04 -07001122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1124 int wpos = mWindows.indexOf(win);
1125 if (wpos >= 0) {
1126 if (wpos < interestingPos) interestingPos--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001127 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 mWindows.remove(wpos);
1129 int NC = win.mChildWindows.size();
1130 while (NC > 0) {
1131 NC--;
1132 WindowState cw = (WindowState)win.mChildWindows.get(NC);
1133 int cpos = mWindows.indexOf(cw);
1134 if (cpos >= 0) {
1135 if (cpos < interestingPos) interestingPos--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001136 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001137 + cpos + ": " + cw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 mWindows.remove(cpos);
1139 }
1140 }
1141 }
1142 return interestingPos;
1143 }
Romain Guy06882f82009-06-10 13:36:04 -07001144
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 private void reAddWindowToListInOrderLocked(WindowState win) {
1146 addWindowToListInOrderLocked(win, false);
1147 // This is a hack to get all of the child windows added as well
1148 // at the right position. Child windows should be rare and
1149 // this case should be rare, so it shouldn't be that big a deal.
1150 int wpos = mWindows.indexOf(win);
1151 if (wpos >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001152 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001153 + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 mWindows.remove(wpos);
1155 reAddWindowLocked(wpos, win);
1156 }
1157 }
Romain Guy06882f82009-06-10 13:36:04 -07001158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 void logWindowList(String prefix) {
1160 int N = mWindows.size();
1161 while (N > 0) {
1162 N--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001163 Slog.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 }
1165 }
Romain Guy06882f82009-06-10 13:36:04 -07001166
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 void moveInputMethodDialogsLocked(int pos) {
1168 ArrayList<WindowState> dialogs = mInputMethodDialogs;
Romain Guy06882f82009-06-10 13:36:04 -07001169
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 final int N = dialogs.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001171 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 for (int i=0; i<N; i++) {
1173 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1174 }
1175 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001176 Slog.v(TAG, "Window list w/pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 logWindowList(" ");
1178 }
Romain Guy06882f82009-06-10 13:36:04 -07001179
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 if (pos >= 0) {
1181 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1182 if (pos < mWindows.size()) {
1183 WindowState wp = (WindowState)mWindows.get(pos);
1184 if (wp == mInputMethodWindow) {
1185 pos++;
1186 }
1187 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001188 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 for (int i=0; i<N; i++) {
1190 WindowState win = dialogs.get(i);
1191 win.mTargetAppToken = targetAppToken;
1192 pos = reAddWindowLocked(pos, win);
1193 }
1194 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001195 Slog.v(TAG, "Final window list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 logWindowList(" ");
1197 }
1198 return;
1199 }
1200 for (int i=0; i<N; i++) {
1201 WindowState win = dialogs.get(i);
1202 win.mTargetAppToken = null;
1203 reAddWindowToListInOrderLocked(win);
1204 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001205 Slog.v(TAG, "No IM target, final list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 logWindowList(" ");
1207 }
1208 }
1209 }
Romain Guy06882f82009-06-10 13:36:04 -07001210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001211 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1212 final WindowState imWin = mInputMethodWindow;
1213 final int DN = mInputMethodDialogs.size();
1214 if (imWin == null && DN == 0) {
1215 return false;
1216 }
Romain Guy06882f82009-06-10 13:36:04 -07001217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1219 if (imPos >= 0) {
1220 // In this case, the input method windows are to be placed
1221 // immediately above the window they are targeting.
Romain Guy06882f82009-06-10 13:36:04 -07001222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 // First check to see if the input method windows are already
1224 // located here, and contiguous.
1225 final int N = mWindows.size();
1226 WindowState firstImWin = imPos < N
1227 ? (WindowState)mWindows.get(imPos) : null;
Romain Guy06882f82009-06-10 13:36:04 -07001228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 // Figure out the actual input method window that should be
1230 // at the bottom of their stack.
1231 WindowState baseImWin = imWin != null
1232 ? imWin : mInputMethodDialogs.get(0);
1233 if (baseImWin.mChildWindows.size() > 0) {
1234 WindowState cw = (WindowState)baseImWin.mChildWindows.get(0);
1235 if (cw.mSubLayer < 0) baseImWin = cw;
1236 }
Romain Guy06882f82009-06-10 13:36:04 -07001237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 if (firstImWin == baseImWin) {
1239 // The windows haven't moved... but are they still contiguous?
1240 // First find the top IM window.
1241 int pos = imPos+1;
1242 while (pos < N) {
1243 if (!((WindowState)mWindows.get(pos)).mIsImWindow) {
1244 break;
1245 }
1246 pos++;
1247 }
1248 pos++;
1249 // Now there should be no more input method windows above.
1250 while (pos < N) {
1251 if (((WindowState)mWindows.get(pos)).mIsImWindow) {
1252 break;
1253 }
1254 pos++;
1255 }
1256 if (pos >= N) {
1257 // All is good!
1258 return false;
1259 }
1260 }
Romain Guy06882f82009-06-10 13:36:04 -07001261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001262 if (imWin != null) {
1263 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001264 Slog.v(TAG, "Moving IM from " + imPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001265 logWindowList(" ");
1266 }
1267 imPos = tmpRemoveWindowLocked(imPos, imWin);
1268 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001269 Slog.v(TAG, "List after moving with new pos " + imPos + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 logWindowList(" ");
1271 }
1272 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1273 reAddWindowLocked(imPos, imWin);
1274 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001275 Slog.v(TAG, "List after moving IM to " + imPos + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001276 logWindowList(" ");
1277 }
1278 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1279 } else {
1280 moveInputMethodDialogsLocked(imPos);
1281 }
Romain Guy06882f82009-06-10 13:36:04 -07001282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 } else {
1284 // In this case, the input method windows go in a fixed layer,
1285 // because they aren't currently associated with a focus window.
Romain Guy06882f82009-06-10 13:36:04 -07001286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 if (imWin != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001288 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 tmpRemoveWindowLocked(0, imWin);
1290 imWin.mTargetAppToken = null;
1291 reAddWindowToListInOrderLocked(imWin);
1292 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001293 Slog.v(TAG, "List with no IM target:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001294 logWindowList(" ");
1295 }
1296 if (DN > 0) moveInputMethodDialogsLocked(-1);;
1297 } else {
1298 moveInputMethodDialogsLocked(-1);;
1299 }
Romain Guy06882f82009-06-10 13:36:04 -07001300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001301 }
Romain Guy06882f82009-06-10 13:36:04 -07001302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 if (needAssignLayers) {
1304 assignLayersLocked();
1305 }
Romain Guy06882f82009-06-10 13:36:04 -07001306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001307 return true;
1308 }
Romain Guy06882f82009-06-10 13:36:04 -07001309
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001310 void adjustInputMethodDialogsLocked() {
1311 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
1312 }
Romain Guy06882f82009-06-10 13:36:04 -07001313
Dianne Hackborn25994b42009-09-04 14:21:19 -07001314 final boolean isWallpaperVisible(WindowState wallpaperTarget) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001315 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target obscured="
Dianne Hackborn25994b42009-09-04 14:21:19 -07001316 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1317 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1318 ? wallpaperTarget.mAppToken.animation : null)
1319 + " upper=" + mUpperWallpaperTarget
1320 + " lower=" + mLowerWallpaperTarget);
1321 return (wallpaperTarget != null
1322 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1323 && wallpaperTarget.mAppToken.animation != null)))
1324 || mUpperWallpaperTarget != null
1325 || mLowerWallpaperTarget != null;
1326 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001327
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001328 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1329 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001330
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001331 int adjustWallpaperWindowsLocked() {
1332 int changed = 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001333
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001334 final int dw = mDisplay.getWidth();
1335 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001336
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001337 // First find top-most window that has asked to be on top of the
1338 // wallpaper; all wallpapers go behind it.
1339 final ArrayList localmWindows = mWindows;
1340 int N = localmWindows.size();
1341 WindowState w = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001342 WindowState foundW = null;
1343 int foundI = 0;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001344 WindowState topCurW = null;
1345 int topCurI = 0;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001346 int i = N;
1347 while (i > 0) {
1348 i--;
1349 w = (WindowState)localmWindows.get(i);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001350 if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
1351 if (topCurW == null) {
1352 topCurW = w;
1353 topCurI = i;
1354 }
1355 continue;
1356 }
1357 topCurW = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001358 if (w.mAppToken != null) {
1359 // If this window's app token is hidden and not animating,
1360 // it is of no interest to us.
1361 if (w.mAppToken.hidden && w.mAppToken.animation == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001362 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001363 "Skipping hidden or animating token: " + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001364 topCurW = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001365 continue;
1366 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001367 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001368 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": readyfordisplay="
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001369 + w.isReadyForDisplay() + " drawpending=" + w.mDrawPending
1370 + " commitdrawpending=" + w.mCommitDrawPending);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001371 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07001372 && (mWallpaperTarget == w
1373 || (!w.mDrawPending && !w.mCommitDrawPending))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001374 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001375 "Found wallpaper activity: #" + i + "=" + w);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001376 foundW = w;
1377 foundI = i;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001378 if (w == mWallpaperTarget && ((w.mAppToken != null
1379 && w.mAppToken.animation != null)
1380 || w.mAnimation != null)) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001381 // The current wallpaper target is animating, so we'll
1382 // look behind it for another possible target and figure
1383 // out what is going on below.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001384 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001385 + ": token animating, looking behind.");
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001386 continue;
1387 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001388 break;
1389 }
1390 }
1391
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001392 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001393 // If we are currently waiting for an app transition, and either
1394 // the current target or the next target are involved with it,
1395 // then hold off on doing anything with the wallpaper.
1396 // Note that we are checking here for just whether the target
1397 // is part of an app token... which is potentially overly aggressive
1398 // (the app token may not be involved in the transition), but good
1399 // enough (we'll just wait until whatever transition is pending
1400 // executes).
1401 if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001402 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001403 "Wallpaper not changing: waiting for app anim in current target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001404 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001405 }
1406 if (foundW != null && foundW.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001407 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001408 "Wallpaper not changing: waiting for app anim in found target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001409 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001410 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001411 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001412
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001413 if (mWallpaperTarget != foundW) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001414 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001415 Slog.v(TAG, "New wallpaper target: " + foundW
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001416 + " oldTarget: " + mWallpaperTarget);
1417 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001418
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001419 mLowerWallpaperTarget = null;
1420 mUpperWallpaperTarget = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001421
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001422 WindowState oldW = mWallpaperTarget;
1423 mWallpaperTarget = foundW;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001424
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001425 // Now what is happening... if the current and new targets are
1426 // animating, then we are in our super special mode!
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001427 if (foundW != null && oldW != null) {
1428 boolean oldAnim = oldW.mAnimation != null
1429 || (oldW.mAppToken != null && oldW.mAppToken.animation != null);
1430 boolean foundAnim = foundW.mAnimation != null
1431 || (foundW.mAppToken != null && foundW.mAppToken.animation != null);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001432 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001433 Slog.v(TAG, "New animation: " + foundAnim
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001434 + " old animation: " + oldAnim);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001435 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001436 if (foundAnim && oldAnim) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001437 int oldI = localmWindows.indexOf(oldW);
1438 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001439 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001440 }
1441 if (oldI >= 0) {
1442 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001443 Slog.v(TAG, "Animating wallpapers: old#" + oldI
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001444 + "=" + oldW + "; new#" + foundI
1445 + "=" + foundW);
1446 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001447
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001448 // Set the new target correctly.
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001449 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001450 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001451 Slog.v(TAG, "Old wallpaper still the target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001452 }
1453 mWallpaperTarget = oldW;
1454 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001455
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001456 // Now set the upper and lower wallpaper targets
1457 // correctly, and make sure that we are positioning
1458 // the wallpaper below the lower.
1459 if (foundI > oldI) {
1460 // The new target is on top of the old one.
1461 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001462 Slog.v(TAG, "Found target above old target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001463 }
1464 mUpperWallpaperTarget = foundW;
1465 mLowerWallpaperTarget = oldW;
1466 foundW = oldW;
1467 foundI = oldI;
1468 } else {
1469 // The new target is below the old one.
1470 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001471 Slog.v(TAG, "Found target below old target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001472 }
1473 mUpperWallpaperTarget = oldW;
1474 mLowerWallpaperTarget = foundW;
1475 }
1476 }
1477 }
1478 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001479
Dianne Hackborn6b1cb352009-09-28 18:27:26 -07001480 } else if (mLowerWallpaperTarget != null) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001481 // Is it time to stop animating?
Dianne Hackborn6b1cb352009-09-28 18:27:26 -07001482 boolean lowerAnimating = mLowerWallpaperTarget.mAnimation != null
1483 || (mLowerWallpaperTarget.mAppToken != null
1484 && mLowerWallpaperTarget.mAppToken.animation != null);
1485 boolean upperAnimating = mUpperWallpaperTarget.mAnimation != null
1486 || (mUpperWallpaperTarget.mAppToken != null
1487 && mUpperWallpaperTarget.mAppToken.animation != null);
1488 if (!lowerAnimating || !upperAnimating) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001489 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001490 Slog.v(TAG, "No longer animating wallpaper targets!");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001491 }
1492 mLowerWallpaperTarget = null;
1493 mUpperWallpaperTarget = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001494 }
1495 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001496
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001497 boolean visible = foundW != null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001498 if (visible) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001499 // The window is visible to the compositor... but is it visible
1500 // to the user? That is what the wallpaper cares about.
Dianne Hackborn25994b42009-09-04 14:21:19 -07001501 visible = isWallpaperVisible(foundW);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001502 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001503
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001504 // If the wallpaper target is animating, we may need to copy
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001505 // its layer adjustment. Only do this if we are not transfering
1506 // between two wallpaper targets.
1507 mWallpaperAnimLayerAdjustment =
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001508 (mLowerWallpaperTarget == null && foundW.mAppToken != null)
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001509 ? foundW.mAppToken.animLayerAdjustment : 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001510
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001511 final int maxLayer = mPolicy.getMaxWallpaperLayer()
1512 * TYPE_LAYER_MULTIPLIER
1513 + TYPE_LAYER_OFFSET;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001514
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001515 // Now w is the window we are supposed to be behind... but we
1516 // need to be sure to also be behind any of its attached windows,
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001517 // AND any starting window associated with it, AND below the
1518 // maximum layer the policy allows for wallpapers.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001519 while (foundI > 0) {
1520 WindowState wb = (WindowState)localmWindows.get(foundI-1);
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001521 if (wb.mBaseLayer < maxLayer &&
1522 wb.mAttachedWindow != foundW &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001523 (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001524 wb.mToken != foundW.mToken)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001525 // This window is not related to the previous one in any
1526 // interesting way, so stop here.
1527 break;
1528 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001529 foundW = wb;
1530 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001531 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07001532 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001533 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001534 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001535
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001536 if (foundW == null && topCurW != null) {
1537 // There is no wallpaper target, so it goes at the bottom.
1538 // We will assume it is the same place as last time, if known.
1539 foundW = topCurW;
1540 foundI = topCurI+1;
1541 } else {
1542 // Okay i is the position immediately above the wallpaper. Look at
1543 // what is below it for later.
1544 foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
1545 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001546
Dianne Hackborn284ac932009-08-28 10:34:25 -07001547 if (visible) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001548 if (mWallpaperTarget.mWallpaperX >= 0) {
1549 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001550 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001551 }
1552 if (mWallpaperTarget.mWallpaperY >= 0) {
1553 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001554 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001555 }
Dianne Hackborn284ac932009-08-28 10:34:25 -07001556 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001557
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001558 // Start stepping backwards from here, ensuring that our wallpaper windows
1559 // are correctly placed.
1560 int curTokenIndex = mWallpaperTokens.size();
1561 while (curTokenIndex > 0) {
1562 curTokenIndex--;
1563 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001564 if (token.hidden == visible) {
1565 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1566 token.hidden = !visible;
1567 // Need to do a layout to ensure the wallpaper now has the
1568 // correct size.
1569 mLayoutNeeded = true;
1570 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001571
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001572 int curWallpaperIndex = token.windows.size();
1573 while (curWallpaperIndex > 0) {
1574 curWallpaperIndex--;
1575 WindowState wallpaper = token.windows.get(curWallpaperIndex);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001576
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001577 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001578 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001579 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001580
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001581 // First, make sure the client has the current visibility
1582 // state.
1583 if (wallpaper.mWallpaperVisible != visible) {
1584 wallpaper.mWallpaperVisible = visible;
1585 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001586 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001587 "Setting visibility of wallpaper " + wallpaper
1588 + ": " + visible);
1589 wallpaper.mClient.dispatchAppVisibility(visible);
1590 } catch (RemoteException e) {
1591 }
1592 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001593
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001594 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001595 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001596 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001597
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001598 // First, if this window is at the current index, then all
1599 // is well.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001600 if (wallpaper == foundW) {
1601 foundI--;
1602 foundW = foundI > 0
1603 ? (WindowState)localmWindows.get(foundI-1) : null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001604 continue;
1605 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001606
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001607 // The window didn't match... the current wallpaper window,
1608 // wherever it is, is in the wrong place, so make sure it is
1609 // not in the list.
1610 int oldIndex = localmWindows.indexOf(wallpaper);
1611 if (oldIndex >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001612 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001613 + oldIndex + ": " + wallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001614 localmWindows.remove(oldIndex);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001615 if (oldIndex < foundI) {
1616 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001617 }
1618 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001619
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001620 // Now stick it in.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001621 if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001622 "Moving wallpaper " + wallpaper
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001623 + " from " + oldIndex + " to " + foundI);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001624
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001625 localmWindows.add(foundI, wallpaper);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001626 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001627 }
1628 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001629
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001630 return changed;
1631 }
1632
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001633 void setWallpaperAnimLayerAdjustmentLocked(int adj) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001634 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001635 "Setting wallpaper layer adj to " + adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001636 mWallpaperAnimLayerAdjustment = adj;
1637 int curTokenIndex = mWallpaperTokens.size();
1638 while (curTokenIndex > 0) {
1639 curTokenIndex--;
1640 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1641 int curWallpaperIndex = token.windows.size();
1642 while (curWallpaperIndex > 0) {
1643 curWallpaperIndex--;
1644 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1645 wallpaper.mAnimLayer = wallpaper.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001646 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001647 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001648 }
1649 }
1650 }
1651
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001652 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1653 boolean sync) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001654 boolean changed = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001655 boolean rawChanged = false;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001656 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001657 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001658 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1659 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1660 changed = wallpaperWin.mXOffset != offset;
1661 if (changed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001662 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001663 + wallpaperWin + " x: " + offset);
1664 wallpaperWin.mXOffset = offset;
1665 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001666 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001667 wallpaperWin.mWallpaperX = wpx;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001668 wallpaperWin.mWallpaperXStep = wpxs;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001669 rawChanged = true;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001670 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001671
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001672 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001673 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001674 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1675 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
1676 if (wallpaperWin.mYOffset != offset) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001677 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001678 + wallpaperWin + " y: " + offset);
1679 changed = true;
1680 wallpaperWin.mYOffset = offset;
1681 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001682 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001683 wallpaperWin.mWallpaperY = wpy;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001684 wallpaperWin.mWallpaperYStep = wpys;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001685 rawChanged = true;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001686 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001687
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001688 if (rawChanged) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001689 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001690 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001691 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1692 + " y=" + wallpaperWin.mWallpaperY);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001693 if (sync) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001694 mWaitingOnWallpaper = wallpaperWin;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001695 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001696 wallpaperWin.mClient.dispatchWallpaperOffsets(
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001697 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
1698 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001699 if (sync) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001700 if (mWaitingOnWallpaper != null) {
1701 long start = SystemClock.uptimeMillis();
1702 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
1703 < start) {
1704 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001705 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn75804932009-10-20 20:15:20 -07001706 "Waiting for offset complete...");
1707 mWindowMap.wait(WALLPAPER_TIMEOUT);
1708 } catch (InterruptedException e) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001709 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001710 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
Dianne Hackborn75804932009-10-20 20:15:20 -07001711 if ((start+WALLPAPER_TIMEOUT)
1712 < SystemClock.uptimeMillis()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001713 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
Dianne Hackborn75804932009-10-20 20:15:20 -07001714 + wallpaperWin);
1715 mLastWallpaperTimeoutTime = start;
1716 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001717 }
Dianne Hackborn75804932009-10-20 20:15:20 -07001718 mWaitingOnWallpaper = null;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001719 }
1720 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001721 } catch (RemoteException e) {
1722 }
1723 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001724
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001725 return changed;
1726 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001727
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001728 void wallpaperOffsetsComplete(IBinder window) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001729 synchronized (mWindowMap) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001730 if (mWaitingOnWallpaper != null &&
1731 mWaitingOnWallpaper.mClient.asBinder() == window) {
1732 mWaitingOnWallpaper = null;
Dianne Hackborn75804932009-10-20 20:15:20 -07001733 mWindowMap.notifyAll();
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001734 }
1735 }
1736 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001737
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001738 boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001739 final int dw = mDisplay.getWidth();
1740 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001741
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001742 boolean changed = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001743
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001744 WindowState target = mWallpaperTarget;
1745 if (target != null) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001746 if (target.mWallpaperX >= 0) {
1747 mLastWallpaperX = target.mWallpaperX;
1748 } else if (changingTarget.mWallpaperX >= 0) {
1749 mLastWallpaperX = changingTarget.mWallpaperX;
1750 }
1751 if (target.mWallpaperY >= 0) {
1752 mLastWallpaperY = target.mWallpaperY;
1753 } else if (changingTarget.mWallpaperY >= 0) {
1754 mLastWallpaperY = changingTarget.mWallpaperY;
1755 }
1756 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001757
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001758 int curTokenIndex = mWallpaperTokens.size();
1759 while (curTokenIndex > 0) {
1760 curTokenIndex--;
1761 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1762 int curWallpaperIndex = token.windows.size();
1763 while (curWallpaperIndex > 0) {
1764 curWallpaperIndex--;
1765 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1766 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
1767 wallpaper.computeShownFrameLocked();
1768 changed = true;
1769 // We only want to be synchronous with one wallpaper.
1770 sync = false;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001771 }
1772 }
1773 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001774
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001775 return changed;
1776 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001777
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001778 void updateWallpaperVisibilityLocked() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07001779 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001780 final int dw = mDisplay.getWidth();
1781 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001782
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001783 int curTokenIndex = mWallpaperTokens.size();
1784 while (curTokenIndex > 0) {
1785 curTokenIndex--;
1786 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001787 if (token.hidden == visible) {
1788 token.hidden = !visible;
1789 // Need to do a layout to ensure the wallpaper now has the
1790 // correct size.
1791 mLayoutNeeded = true;
1792 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001793
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001794 int curWallpaperIndex = token.windows.size();
1795 while (curWallpaperIndex > 0) {
1796 curWallpaperIndex--;
1797 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1798 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001799 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001800 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001801
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001802 if (wallpaper.mWallpaperVisible != visible) {
1803 wallpaper.mWallpaperVisible = visible;
1804 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001805 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07001806 "Updating visibility of wallpaper " + wallpaper
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001807 + ": " + visible);
1808 wallpaper.mClient.dispatchAppVisibility(visible);
1809 } catch (RemoteException e) {
1810 }
1811 }
1812 }
1813 }
1814 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001815
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001816 void sendPointerToWallpaperLocked(WindowState srcWin,
1817 MotionEvent pointer, long eventTime) {
1818 int curTokenIndex = mWallpaperTokens.size();
1819 while (curTokenIndex > 0) {
1820 curTokenIndex--;
1821 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1822 int curWallpaperIndex = token.windows.size();
1823 while (curWallpaperIndex > 0) {
1824 curWallpaperIndex--;
1825 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1826 if ((wallpaper.mAttrs.flags &
1827 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
1828 continue;
1829 }
1830 try {
1831 MotionEvent ev = MotionEvent.obtainNoHistory(pointer);
Dianne Hackborn6adba242009-11-10 11:10:09 -08001832 if (srcWin != null) {
1833 ev.offsetLocation(srcWin.mFrame.left-wallpaper.mFrame.left,
1834 srcWin.mFrame.top-wallpaper.mFrame.top);
1835 } else {
1836 ev.offsetLocation(-wallpaper.mFrame.left, -wallpaper.mFrame.top);
1837 }
1838 switch (pointer.getAction()) {
1839 case MotionEvent.ACTION_DOWN:
1840 mSendingPointersToWallpaper = true;
1841 break;
1842 case MotionEvent.ACTION_UP:
1843 mSendingPointersToWallpaper = false;
1844 break;
1845 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001846 wallpaper.mClient.dispatchPointer(ev, eventTime, false);
1847 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001848 Slog.w(TAG, "Failure sending pointer to wallpaper", e);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001849 }
1850 }
1851 }
1852 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001853
Dianne Hackborn90d2db32010-02-11 22:19:06 -08001854 void dispatchPointerElsewhereLocked(WindowState srcWin, WindowState relWin,
1855 MotionEvent pointer, long eventTime, boolean skipped) {
1856 if (relWin != null) {
1857 mPolicy.dispatchedPointerEventLw(pointer, relWin.mFrame.left, relWin.mFrame.top);
1858 } else {
1859 mPolicy.dispatchedPointerEventLw(pointer, 0, 0);
1860 }
1861
1862 // If we sent an initial down to the wallpaper, then continue
1863 // sending events until the final up.
1864 if (mSendingPointersToWallpaper) {
1865 if (skipped) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001866 Slog.i(TAG, "Sending skipped pointer to wallpaper!");
Dianne Hackborn90d2db32010-02-11 22:19:06 -08001867 }
1868 sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1869
1870 // If we are on top of the wallpaper, then the wallpaper also
1871 // gets to see this movement.
1872 } else if (srcWin != null
1873 && pointer.getAction() == MotionEvent.ACTION_DOWN
1874 && mWallpaperTarget == srcWin
1875 && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
1876 sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1877 }
1878 }
1879
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001880 public int addWindow(Session session, IWindow client,
1881 WindowManager.LayoutParams attrs, int viewVisibility,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001882 Rect outContentInsets, InputChannel outInputChannel) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001883 int res = mPolicy.checkAddPermission(attrs);
1884 if (res != WindowManagerImpl.ADD_OKAY) {
1885 return res;
1886 }
Romain Guy06882f82009-06-10 13:36:04 -07001887
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001888 boolean reportNewConfig = false;
1889 WindowState attachedWindow = null;
1890 WindowState win = null;
Romain Guy06882f82009-06-10 13:36:04 -07001891
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 synchronized(mWindowMap) {
1893 // Instantiating a Display requires talking with the simulator,
1894 // so don't do it until we know the system is mostly up and
1895 // running.
1896 if (mDisplay == null) {
1897 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1898 mDisplay = wm.getDefaultDisplay();
Christopher Tateb696aee2010-04-02 19:08:30 -07001899 mInitialDisplayWidth = mDisplay.getWidth();
1900 mInitialDisplayHeight = mDisplay.getHeight();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001901 if (ENABLE_NATIVE_INPUT_DISPATCH) {
1902 mInputManager.setDisplaySize(0,
1903 mInitialDisplayWidth, mInitialDisplayHeight);
1904 } else {
1905 mQueue.setDisplay(mDisplay);
1906 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001907 reportNewConfig = true;
1908 }
Romain Guy06882f82009-06-10 13:36:04 -07001909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 if (mWindowMap.containsKey(client.asBinder())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001911 Slog.w(TAG, "Window " + client + " is already added");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001912 return WindowManagerImpl.ADD_DUPLICATE_ADD;
1913 }
1914
1915 if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001916 attachedWindow = windowForClientLocked(null, attrs.token, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001917 if (attachedWindow == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001918 Slog.w(TAG, "Attempted to add window with token that is not a window: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001919 + attrs.token + ". Aborting.");
1920 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1921 }
1922 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1923 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001924 Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001925 + attrs.token + ". Aborting.");
1926 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1927 }
1928 }
1929
1930 boolean addToken = false;
1931 WindowToken token = mTokenMap.get(attrs.token);
1932 if (token == null) {
1933 if (attrs.type >= FIRST_APPLICATION_WINDOW
1934 && attrs.type <= LAST_APPLICATION_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001935 Slog.w(TAG, "Attempted to add application window with unknown token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001936 + attrs.token + ". Aborting.");
1937 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1938 }
1939 if (attrs.type == TYPE_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001940 Slog.w(TAG, "Attempted to add input method window with unknown token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941 + attrs.token + ". Aborting.");
1942 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1943 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001944 if (attrs.type == TYPE_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001945 Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001946 + attrs.token + ". Aborting.");
1947 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1948 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001949 token = new WindowToken(attrs.token, -1, false);
1950 addToken = true;
1951 } else if (attrs.type >= FIRST_APPLICATION_WINDOW
1952 && attrs.type <= LAST_APPLICATION_WINDOW) {
1953 AppWindowToken atoken = token.appWindowToken;
1954 if (atoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001955 Slog.w(TAG, "Attempted to add window with non-application token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 + token + ". Aborting.");
1957 return WindowManagerImpl.ADD_NOT_APP_TOKEN;
1958 } else if (atoken.removed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001959 Slog.w(TAG, "Attempted to add window with exiting application token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001960 + token + ". Aborting.");
1961 return WindowManagerImpl.ADD_APP_EXITING;
1962 }
1963 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1964 // No need for this guy!
Joe Onorato8a9b2202010-02-26 18:56:32 -08001965 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001966 TAG, "**** NO NEED TO START: " + attrs.getTitle());
1967 return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
1968 }
1969 } else if (attrs.type == TYPE_INPUT_METHOD) {
1970 if (token.windowType != TYPE_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001971 Slog.w(TAG, "Attempted to add input method window with bad token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001972 + attrs.token + ". Aborting.");
1973 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1974 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001975 } else if (attrs.type == TYPE_WALLPAPER) {
1976 if (token.windowType != TYPE_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001977 Slog.w(TAG, "Attempted to add wallpaper window with bad token "
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001978 + attrs.token + ". Aborting.");
1979 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1980 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001981 }
1982
1983 win = new WindowState(session, client, token,
1984 attachedWindow, attrs, viewVisibility);
1985 if (win.mDeathRecipient == null) {
1986 // Client has apparently died, so there is no reason to
1987 // continue.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001988 Slog.w(TAG, "Adding window client " + client.asBinder()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001989 + " that is dead, aborting.");
1990 return WindowManagerImpl.ADD_APP_EXITING;
1991 }
1992
1993 mPolicy.adjustWindowParamsLw(win.mAttrs);
Romain Guy06882f82009-06-10 13:36:04 -07001994
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001995 res = mPolicy.prepareAddWindowLw(win, attrs);
1996 if (res != WindowManagerImpl.ADD_OKAY) {
1997 return res;
1998 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001999
2000 if (ENABLE_NATIVE_INPUT_DISPATCH) {
2001 if (outInputChannel != null) {
2002 String name = win.makeInputChannelName();
2003 InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
2004 win.mInputChannel = inputChannels[0];
2005 inputChannels[1].transferToBinderOutParameter(outInputChannel);
2006
2007 mInputManager.registerInputChannel(win.mInputChannel);
2008 }
2009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010
2011 // From now on, no exceptions or errors allowed!
2012
2013 res = WindowManagerImpl.ADD_OKAY;
Romain Guy06882f82009-06-10 13:36:04 -07002014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 if (addToken) {
2018 mTokenMap.put(attrs.token, token);
2019 mTokenList.add(token);
2020 }
2021 win.attach();
2022 mWindowMap.put(client.asBinder(), win);
2023
2024 if (attrs.type == TYPE_APPLICATION_STARTING &&
2025 token.appWindowToken != null) {
2026 token.appWindowToken.startingWindow = win;
2027 }
2028
2029 boolean imMayMove = true;
Romain Guy06882f82009-06-10 13:36:04 -07002030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 if (attrs.type == TYPE_INPUT_METHOD) {
2032 mInputMethodWindow = win;
2033 addInputMethodWindowToListLocked(win);
2034 imMayMove = false;
2035 } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
2036 mInputMethodDialogs.add(win);
2037 addWindowToListInOrderLocked(win, true);
2038 adjustInputMethodDialogsLocked();
2039 imMayMove = false;
2040 } else {
2041 addWindowToListInOrderLocked(win, true);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002042 if (attrs.type == TYPE_WALLPAPER) {
2043 mLastWallpaperTimeoutTime = 0;
2044 adjustWallpaperWindowsLocked();
2045 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002046 adjustWallpaperWindowsLocked();
2047 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 }
Romain Guy06882f82009-06-10 13:36:04 -07002049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 win.mEnterAnimationPending = true;
Romain Guy06882f82009-06-10 13:36:04 -07002051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002052 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
Romain Guy06882f82009-06-10 13:36:04 -07002053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 if (mInTouchMode) {
2055 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
2056 }
2057 if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
2058 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
2059 }
Romain Guy06882f82009-06-10 13:36:04 -07002060
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002061 boolean focusChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002062 if (win.canReceiveKeys()) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002063 if ((focusChanged=updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS))
2064 == true) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 imMayMove = false;
2066 }
2067 }
Romain Guy06882f82009-06-10 13:36:04 -07002068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 if (imMayMove) {
Romain Guy06882f82009-06-10 13:36:04 -07002070 moveInputMethodWindowsIfNeededLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002071 }
Romain Guy06882f82009-06-10 13:36:04 -07002072
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 assignLayersLocked();
2074 // Don't do layout here, the window must call
2075 // relayout to be displayed, so we'll do it there.
Romain Guy06882f82009-06-10 13:36:04 -07002076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002077 //dump();
2078
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002079 if (focusChanged) {
2080 if (mCurrentFocus != null) {
2081 mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
2082 }
2083 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002084 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002085 TAG, "New client " + client.asBinder()
2086 + ": window=" + win);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002087
2088 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked()) {
2089 reportNewConfig = true;
2090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 }
2092
2093 // sendNewConfiguration() checks caller permissions so we must call it with
2094 // privilege. updateOrientationFromAppTokens() clears and resets the caller
2095 // identity anyway, so it's safe to just clear & restore around this whole
2096 // block.
2097 final long origId = Binder.clearCallingIdentity();
2098 if (reportNewConfig) {
2099 sendNewConfiguration();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002100 }
2101 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07002102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002103 return res;
2104 }
Romain Guy06882f82009-06-10 13:36:04 -07002105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002106 public void removeWindow(Session session, IWindow client) {
2107 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002108 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 if (win == null) {
2110 return;
2111 }
2112 removeWindowLocked(session, win);
2113 }
2114 }
Romain Guy06882f82009-06-10 13:36:04 -07002115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002116 public void removeWindowLocked(Session session, WindowState win) {
2117
Joe Onorato8a9b2202010-02-26 18:56:32 -08002118 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002119 TAG, "Remove " + win + " client="
2120 + Integer.toHexString(System.identityHashCode(
2121 win.mClient.asBinder()))
2122 + ", surface=" + win.mSurface);
2123
2124 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002125
Joe Onorato8a9b2202010-02-26 18:56:32 -08002126 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 TAG, "Remove " + win + ": mSurface=" + win.mSurface
2128 + " mExiting=" + win.mExiting
2129 + " isAnimating=" + win.isAnimating()
2130 + " app-animation="
2131 + (win.mAppToken != null ? win.mAppToken.animation : null)
2132 + " inPendingTransaction="
2133 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2134 + " mDisplayFrozen=" + mDisplayFrozen);
2135 // Visibility of the removed window. Will be used later to update orientation later on.
2136 boolean wasVisible = false;
2137 // First, see if we need to run an animation. If we do, we have
2138 // to hold off on removing the window until the animation is done.
2139 // If the display is frozen, just remove immediately, since the
2140 // animation wouldn't be seen.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002141 if (win.mSurface != null && !mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 // If we are not currently running the exit animation, we
2143 // need to see about starting one.
2144 if (wasVisible=win.isWinVisibleLw()) {
Romain Guy06882f82009-06-10 13:36:04 -07002145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002146 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2147 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2148 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2149 }
2150 // Try starting an animation.
2151 if (applyAnimationLocked(win, transit, false)) {
2152 win.mExiting = true;
2153 }
2154 }
2155 if (win.mExiting || win.isAnimating()) {
2156 // The exit animation is running... wait for it!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002157 //Slog.i(TAG, "*** Running exit animation...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002158 win.mExiting = true;
2159 win.mRemoveOnExit = true;
2160 mLayoutNeeded = true;
2161 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
2162 performLayoutAndPlaceSurfacesLocked();
2163 if (win.mAppToken != null) {
2164 win.mAppToken.updateReportedVisibilityLocked();
2165 }
2166 //dump();
2167 Binder.restoreCallingIdentity(origId);
2168 return;
2169 }
2170 }
2171
2172 removeWindowInnerLocked(session, win);
2173 // Removing a visible window will effect the computed orientation
2174 // So just update orientation if needed.
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002175 if (wasVisible && computeForcedAppOrientationLocked()
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002176 != mForcedAppOrientation
2177 && updateOrientationFromAppTokensLocked()) {
2178 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 }
2180 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2181 Binder.restoreCallingIdentity(origId);
2182 }
Romain Guy06882f82009-06-10 13:36:04 -07002183
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002184 private void removeWindowInnerLocked(Session session, WindowState win) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07002185 mKeyWaiter.finishedKey(session, win.mClient, true,
2186 KeyWaiter.RETURN_NOTHING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002187 mKeyWaiter.releasePendingPointerLocked(win.mSession);
2188 mKeyWaiter.releasePendingTrackballLocked(win.mSession);
Romain Guy06882f82009-06-10 13:36:04 -07002189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002190 win.mRemoved = true;
Romain Guy06882f82009-06-10 13:36:04 -07002191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002192 if (mInputMethodTarget == win) {
2193 moveInputMethodWindowsIfNeededLocked(false);
2194 }
Romain Guy06882f82009-06-10 13:36:04 -07002195
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002196 if (false) {
2197 RuntimeException e = new RuntimeException("here");
2198 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002199 Slog.w(TAG, "Removing window " + win, e);
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002200 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002202 mPolicy.removeWindowLw(win);
2203 win.removeLocked();
2204
2205 mWindowMap.remove(win.mClient.asBinder());
2206 mWindows.remove(win);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002207 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208
2209 if (mInputMethodWindow == win) {
2210 mInputMethodWindow = null;
2211 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2212 mInputMethodDialogs.remove(win);
2213 }
Romain Guy06882f82009-06-10 13:36:04 -07002214
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002215 final WindowToken token = win.mToken;
2216 final AppWindowToken atoken = win.mAppToken;
2217 token.windows.remove(win);
2218 if (atoken != null) {
2219 atoken.allAppWindows.remove(win);
2220 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002221 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 TAG, "**** Removing window " + win + ": count="
2223 + token.windows.size());
2224 if (token.windows.size() == 0) {
2225 if (!token.explicit) {
2226 mTokenMap.remove(token.token);
2227 mTokenList.remove(token);
2228 } else if (atoken != null) {
2229 atoken.firstWindowDrawn = false;
2230 }
2231 }
2232
2233 if (atoken != null) {
2234 if (atoken.startingWindow == win) {
2235 atoken.startingWindow = null;
2236 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2237 // If this is the last window and we had requested a starting
2238 // transition window, well there is no point now.
2239 atoken.startingData = null;
2240 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2241 // If this is the last window except for a starting transition
2242 // window, we need to get rid of the starting transition.
2243 if (DEBUG_STARTING_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002244 Slog.v(TAG, "Schedule remove starting " + token
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002245 + ": no more real windows");
2246 }
2247 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
2248 mH.sendMessage(m);
2249 }
2250 }
Romain Guy06882f82009-06-10 13:36:04 -07002251
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002252 if (win.mAttrs.type == TYPE_WALLPAPER) {
2253 mLastWallpaperTimeoutTime = 0;
2254 adjustWallpaperWindowsLocked();
2255 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07002256 adjustWallpaperWindowsLocked();
2257 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002259 if (!mInLayout) {
2260 assignLayersLocked();
2261 mLayoutNeeded = true;
2262 performLayoutAndPlaceSurfacesLocked();
2263 if (win.mAppToken != null) {
2264 win.mAppToken.updateReportedVisibilityLocked();
2265 }
2266 }
2267 }
2268
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002269 private static void logSurface(WindowState w, String msg, RuntimeException where) {
2270 String str = " SURFACE " + Integer.toHexString(w.hashCode())
2271 + ": " + msg + " / " + w.mAttrs.getTitle();
2272 if (where != null) {
2273 Slog.i(TAG, str, where);
2274 } else {
2275 Slog.i(TAG, str);
2276 }
2277 }
2278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002279 private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2280 long origId = Binder.clearCallingIdentity();
2281 try {
2282 synchronized (mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002283 WindowState w = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002284 if ((w != null) && (w.mSurface != null)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002285 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002286 Surface.openTransaction();
2287 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002288 if (SHOW_TRANSACTIONS) logSurface(w,
2289 "transparentRegionHint=" + region, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 w.mSurface.setTransparentRegionHint(region);
2291 } finally {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002292 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002293 Surface.closeTransaction();
2294 }
2295 }
2296 }
2297 } finally {
2298 Binder.restoreCallingIdentity(origId);
2299 }
2300 }
2301
2302 void setInsetsWindow(Session session, IWindow client,
Romain Guy06882f82009-06-10 13:36:04 -07002303 int touchableInsets, Rect contentInsets,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002304 Rect visibleInsets) {
2305 long origId = Binder.clearCallingIdentity();
2306 try {
2307 synchronized (mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002308 WindowState w = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002309 if (w != null) {
2310 w.mGivenInsetsPending = false;
2311 w.mGivenContentInsets.set(contentInsets);
2312 w.mGivenVisibleInsets.set(visibleInsets);
2313 w.mTouchableInsets = touchableInsets;
2314 mLayoutNeeded = true;
2315 performLayoutAndPlaceSurfacesLocked();
2316 }
2317 }
2318 } finally {
2319 Binder.restoreCallingIdentity(origId);
2320 }
2321 }
Romain Guy06882f82009-06-10 13:36:04 -07002322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 public void getWindowDisplayFrame(Session session, IWindow client,
2324 Rect outDisplayFrame) {
2325 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002326 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002327 if (win == null) {
2328 outDisplayFrame.setEmpty();
2329 return;
2330 }
2331 outDisplayFrame.set(win.mDisplayFrame);
2332 }
2333 }
2334
Marco Nelissenbf6956b2009-11-09 15:21:13 -08002335 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2336 float xStep, float yStep) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002337 if (window.mWallpaperX != x || window.mWallpaperY != y) {
2338 window.mWallpaperX = x;
2339 window.mWallpaperY = y;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08002340 window.mWallpaperXStep = xStep;
2341 window.mWallpaperYStep = yStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07002342 if (updateWallpaperOffsetLocked(window, true)) {
2343 performLayoutAndPlaceSurfacesLocked();
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002344 }
2345 }
2346 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002347
Dianne Hackborn75804932009-10-20 20:15:20 -07002348 void wallpaperCommandComplete(IBinder window, Bundle result) {
2349 synchronized (mWindowMap) {
2350 if (mWaitingOnWallpaper != null &&
2351 mWaitingOnWallpaper.mClient.asBinder() == window) {
2352 mWaitingOnWallpaper = null;
2353 mWindowMap.notifyAll();
2354 }
2355 }
2356 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002357
Dianne Hackborn75804932009-10-20 20:15:20 -07002358 public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2359 String action, int x, int y, int z, Bundle extras, boolean sync) {
2360 if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2361 || window == mUpperWallpaperTarget) {
2362 boolean doWait = sync;
2363 int curTokenIndex = mWallpaperTokens.size();
2364 while (curTokenIndex > 0) {
2365 curTokenIndex--;
2366 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2367 int curWallpaperIndex = token.windows.size();
2368 while (curWallpaperIndex > 0) {
2369 curWallpaperIndex--;
2370 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2371 try {
2372 wallpaper.mClient.dispatchWallpaperCommand(action,
2373 x, y, z, extras, sync);
2374 // We only want to be synchronous with one wallpaper.
2375 sync = false;
2376 } catch (RemoteException e) {
2377 }
2378 }
2379 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002380
Dianne Hackborn75804932009-10-20 20:15:20 -07002381 if (doWait) {
2382 // XXX Need to wait for result.
2383 }
2384 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002385
Dianne Hackborn75804932009-10-20 20:15:20 -07002386 return null;
2387 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002389 public int relayoutWindow(Session session, IWindow client,
2390 WindowManager.LayoutParams attrs, int requestedWidth,
2391 int requestedHeight, int viewVisibility, boolean insetsPending,
2392 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07002393 Configuration outConfig, Surface outSurface) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002394 boolean displayed = false;
2395 boolean inTouchMode;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002396 boolean configChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002397 long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002400 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002401 if (win == null) {
2402 return 0;
2403 }
2404 win.mRequestedWidth = requestedWidth;
2405 win.mRequestedHeight = requestedHeight;
2406
2407 if (attrs != null) {
2408 mPolicy.adjustWindowParamsLw(attrs);
2409 }
Romain Guy06882f82009-06-10 13:36:04 -07002410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002411 int attrChanges = 0;
2412 int flagChanges = 0;
2413 if (attrs != null) {
2414 flagChanges = win.mAttrs.flags ^= attrs.flags;
2415 attrChanges = win.mAttrs.copyFrom(attrs);
2416 }
2417
Joe Onorato8a9b2202010-02-26 18:56:32 -08002418 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": " + win.mAttrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002419
2420 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2421 win.mAlpha = attrs.alpha;
2422 }
2423
2424 final boolean scaledWindow =
2425 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2426
2427 if (scaledWindow) {
2428 // requested{Width|Height} Surface's physical size
2429 // attrs.{width|height} Size on screen
2430 win.mHScale = (attrs.width != requestedWidth) ?
2431 (attrs.width / (float)requestedWidth) : 1.0f;
2432 win.mVScale = (attrs.height != requestedHeight) ?
2433 (attrs.height / (float)requestedHeight) : 1.0f;
Dianne Hackborn9b52a212009-12-11 14:51:35 -08002434 } else {
2435 win.mHScale = win.mVScale = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002436 }
2437
2438 boolean imMayMove = (flagChanges&(
2439 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
2440 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07002441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 boolean focusMayChange = win.mViewVisibility != viewVisibility
2443 || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
2444 || (!win.mRelayoutCalled);
Romain Guy06882f82009-06-10 13:36:04 -07002445
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002446 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2447 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002448
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002449 win.mRelayoutCalled = true;
2450 final int oldVisibility = win.mViewVisibility;
2451 win.mViewVisibility = viewVisibility;
2452 if (viewVisibility == View.VISIBLE &&
2453 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2454 displayed = !win.isVisibleLw();
2455 if (win.mExiting) {
2456 win.mExiting = false;
2457 win.mAnimation = null;
2458 }
2459 if (win.mDestroying) {
2460 win.mDestroying = false;
2461 mDestroySurface.remove(win);
2462 }
2463 if (oldVisibility == View.GONE) {
2464 win.mEnterAnimationPending = true;
2465 }
Dianne Hackborn694f79b2010-03-17 19:44:59 -07002466 if (displayed) {
2467 if (win.mSurface != null && !win.mDrawPending
2468 && !win.mCommitDrawPending && !mDisplayFrozen
2469 && mPolicy.isScreenOn()) {
2470 applyEnterAnimationLocked(win);
2471 }
2472 if ((win.mAttrs.flags
2473 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2474 if (DEBUG_VISIBILITY) Slog.v(TAG,
2475 "Relayout window turning screen on: " + win);
2476 win.mTurnOnScreen = true;
2477 }
2478 int diff = 0;
2479 if (win.mConfiguration != mCurConfiguration
2480 && (win.mConfiguration == null
2481 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0)) {
2482 win.mConfiguration = mCurConfiguration;
2483 if (DEBUG_CONFIGURATION) {
2484 Slog.i(TAG, "Window " + win + " visible with new config: "
2485 + win.mConfiguration + " / 0x"
2486 + Integer.toHexString(diff));
2487 }
2488 outConfig.setTo(mCurConfiguration);
2489 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07002490 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002491 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2492 // To change the format, we need to re-build the surface.
2493 win.destroySurfaceLocked();
2494 displayed = true;
2495 }
2496 try {
2497 Surface surface = win.createSurfaceLocked();
2498 if (surface != null) {
2499 outSurface.copyFrom(surface);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002500 win.mReportDestroySurface = false;
2501 win.mSurfacePendingDestroy = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002502 if (SHOW_TRANSACTIONS) Slog.i(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002503 " OUT SURFACE " + outSurface + ": copied");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002504 } else {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002505 // For some reason there isn't a surface. Clear the
2506 // caller's object so they see the same state.
2507 outSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002508 }
2509 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002510 Slog.w(TAG, "Exception thrown when creating surface for client "
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002511 + client + " (" + win.mAttrs.getTitle() + ")",
2512 e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002513 Binder.restoreCallingIdentity(origId);
2514 return 0;
2515 }
2516 if (displayed) {
2517 focusMayChange = true;
2518 }
2519 if (win.mAttrs.type == TYPE_INPUT_METHOD
2520 && mInputMethodWindow == null) {
2521 mInputMethodWindow = win;
2522 imMayMove = true;
2523 }
Dianne Hackborn558947c2009-12-18 16:02:50 -08002524 if (win.mAttrs.type == TYPE_BASE_APPLICATION
2525 && win.mAppToken != null
2526 && win.mAppToken.startingWindow != null) {
2527 // Special handling of starting window over the base
2528 // window of the app: propagate lock screen flags to it,
2529 // to provide the correct semantics while starting.
2530 final int mask =
2531 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
Mike Lockwoodef731622010-01-27 17:51:34 -05002532 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
2533 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
Dianne Hackborn558947c2009-12-18 16:02:50 -08002534 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
2535 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
2536 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002537 } else {
2538 win.mEnterAnimationPending = false;
2539 if (win.mSurface != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002540 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002541 + ": mExiting=" + win.mExiting
2542 + " mSurfacePendingDestroy=" + win.mSurfacePendingDestroy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002543 // If we are not currently running the exit animation, we
2544 // need to see about starting one.
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002545 if (!win.mExiting || win.mSurfacePendingDestroy) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002546 // Try starting an animation; if there isn't one, we
2547 // can destroy the surface right away.
2548 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2549 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2550 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2551 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002552 if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002553 applyAnimationLocked(win, transit, false)) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002554 focusMayChange = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002555 win.mExiting = true;
2556 mKeyWaiter.finishedKey(session, client, true,
2557 KeyWaiter.RETURN_NOTHING);
2558 } else if (win.isAnimating()) {
2559 // Currently in a hide animation... turn this into
2560 // an exit.
2561 win.mExiting = true;
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07002562 } else if (win == mWallpaperTarget) {
2563 // If the wallpaper is currently behind this
2564 // window, we need to change both of them inside
2565 // of a transaction to avoid artifacts.
2566 win.mExiting = true;
2567 win.mAnimating = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002568 } else {
2569 if (mInputMethodWindow == win) {
2570 mInputMethodWindow = null;
2571 }
2572 win.destroySurfaceLocked();
2573 }
2574 }
2575 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002576
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002577 if (win.mSurface == null || (win.getAttrs().flags
2578 & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0
2579 || win.mSurfacePendingDestroy) {
2580 // We are being called from a local process, which
2581 // means outSurface holds its current surface. Ensure the
2582 // surface object is cleared, but we don't want it actually
2583 // destroyed at this point.
2584 win.mSurfacePendingDestroy = false;
2585 outSurface.release();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002586 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002587 } else if (win.mSurface != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002588 if (DEBUG_VISIBILITY) Slog.i(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002589 "Keeping surface, will report destroy: " + win);
2590 win.mReportDestroySurface = true;
2591 outSurface.copyFrom(win.mSurface);
2592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 }
2594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002595 if (focusMayChange) {
2596 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2597 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002598 imMayMove = false;
2599 }
2600 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2601 }
Romain Guy06882f82009-06-10 13:36:04 -07002602
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002603 // updateFocusedWindowLocked() already assigned layers so we only need to
2604 // reassign them at this point if the IM window state gets shuffled
2605 boolean assignLayers = false;
Romain Guy06882f82009-06-10 13:36:04 -07002606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 if (imMayMove) {
Dianne Hackborn8abd5f02009-11-20 18:09:03 -08002608 if (moveInputMethodWindowsIfNeededLocked(false) || displayed) {
2609 // Little hack here -- we -should- be able to rely on the
2610 // function to return true if the IME has moved and needs
2611 // its layer recomputed. However, if the IME was hidden
2612 // and isn't actually moved in the list, its layer may be
2613 // out of data so we make sure to recompute it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002614 assignLayers = true;
2615 }
2616 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002617 if (wallpaperMayMove) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002618 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002619 assignLayers = true;
2620 }
2621 }
Romain Guy06882f82009-06-10 13:36:04 -07002622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 mLayoutNeeded = true;
2624 win.mGivenInsetsPending = insetsPending;
2625 if (assignLayers) {
2626 assignLayersLocked();
2627 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002628 configChanged = updateOrientationFromAppTokensLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002629 performLayoutAndPlaceSurfacesLocked();
Dianne Hackborn284ac932009-08-28 10:34:25 -07002630 if (displayed && win.mIsWallpaper) {
2631 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002632 mDisplay.getHeight(), false);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002634 if (win.mAppToken != null) {
2635 win.mAppToken.updateReportedVisibilityLocked();
2636 }
2637 outFrame.set(win.mFrame);
2638 outContentInsets.set(win.mContentInsets);
2639 outVisibleInsets.set(win.mVisibleInsets);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002640 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002641 TAG, "Relayout given client " + client.asBinder()
Romain Guy06882f82009-06-10 13:36:04 -07002642 + ", requestedWidth=" + requestedWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002643 + ", requestedHeight=" + requestedHeight
2644 + ", viewVisibility=" + viewVisibility
2645 + "\nRelayout returning frame=" + outFrame
2646 + ", surface=" + outSurface);
2647
Joe Onorato8a9b2202010-02-26 18:56:32 -08002648 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002649 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2650
2651 inTouchMode = mInTouchMode;
2652 }
2653
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002654 if (configChanged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002655 sendNewConfiguration();
2656 }
Romain Guy06882f82009-06-10 13:36:04 -07002657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002658 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07002659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002660 return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
2661 | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
2662 }
2663
2664 public void finishDrawingWindow(Session session, IWindow client) {
2665 final long origId = Binder.clearCallingIdentity();
2666 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002667 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002668 if (win != null && win.finishDrawingLocked()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07002669 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2670 adjustWallpaperWindowsLocked();
2671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002672 mLayoutNeeded = true;
2673 performLayoutAndPlaceSurfacesLocked();
2674 }
2675 }
2676 Binder.restoreCallingIdentity(origId);
2677 }
2678
2679 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002680 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002681 + (lp != null ? lp.packageName : null)
2682 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
2683 if (lp != null && lp.windowAnimations != 0) {
2684 // If this is a system resource, don't try to load it from the
2685 // application resources. It is nice to avoid loading application
2686 // resources if we can.
2687 String packageName = lp.packageName != null ? lp.packageName : "android";
2688 int resId = lp.windowAnimations;
2689 if ((resId&0xFF000000) == 0x01000000) {
2690 packageName = "android";
2691 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002692 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002693 + packageName);
2694 return AttributeCache.instance().get(packageName, resId,
2695 com.android.internal.R.styleable.WindowAnimation);
2696 }
2697 return null;
2698 }
Romain Guy06882f82009-06-10 13:36:04 -07002699
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002700 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002701 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002702 + packageName + " resId=0x" + Integer.toHexString(resId));
2703 if (packageName != null) {
2704 if ((resId&0xFF000000) == 0x01000000) {
2705 packageName = "android";
2706 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002707 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002708 + packageName);
2709 return AttributeCache.instance().get(packageName, resId,
2710 com.android.internal.R.styleable.WindowAnimation);
2711 }
2712 return null;
2713 }
2714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002715 private void applyEnterAnimationLocked(WindowState win) {
2716 int transit = WindowManagerPolicy.TRANSIT_SHOW;
2717 if (win.mEnterAnimationPending) {
2718 win.mEnterAnimationPending = false;
2719 transit = WindowManagerPolicy.TRANSIT_ENTER;
2720 }
2721
2722 applyAnimationLocked(win, transit, true);
2723 }
2724
2725 private boolean applyAnimationLocked(WindowState win,
2726 int transit, boolean isEntrance) {
2727 if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
2728 // If we are trying to apply an animation, but already running
2729 // an animation of the same type, then just leave that one alone.
2730 return true;
2731 }
Romain Guy06882f82009-06-10 13:36:04 -07002732
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002733 // Only apply an animation if the display isn't frozen. If it is
2734 // frozen, there is no reason to animate and it can cause strange
2735 // artifacts when we unfreeze the display if some different animation
2736 // is running.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002737 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 int anim = mPolicy.selectAnimationLw(win, transit);
2739 int attr = -1;
2740 Animation a = null;
2741 if (anim != 0) {
2742 a = AnimationUtils.loadAnimation(mContext, anim);
2743 } else {
2744 switch (transit) {
2745 case WindowManagerPolicy.TRANSIT_ENTER:
2746 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
2747 break;
2748 case WindowManagerPolicy.TRANSIT_EXIT:
2749 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
2750 break;
2751 case WindowManagerPolicy.TRANSIT_SHOW:
2752 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
2753 break;
2754 case WindowManagerPolicy.TRANSIT_HIDE:
2755 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
2756 break;
2757 }
2758 if (attr >= 0) {
2759 a = loadAnimation(win.mAttrs, attr);
2760 }
2761 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002762 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: win=" + win
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
2764 + " mAnimation=" + win.mAnimation
2765 + " isEntrance=" + isEntrance);
2766 if (a != null) {
2767 if (DEBUG_ANIM) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002768 RuntimeException e = null;
2769 if (!HIDE_STACK_CRAWLS) {
2770 e = new RuntimeException();
2771 e.fillInStackTrace();
2772 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002773 Slog.v(TAG, "Loaded animation " + a + " for " + win, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002774 }
2775 win.setAnimation(a);
2776 win.mAnimationIsEntrance = isEntrance;
2777 }
2778 } else {
2779 win.clearAnimation();
2780 }
2781
2782 return win.mAnimation != null;
2783 }
2784
2785 private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
2786 int anim = 0;
2787 Context context = mContext;
2788 if (animAttr >= 0) {
2789 AttributeCache.Entry ent = getCachedAnimations(lp);
2790 if (ent != null) {
2791 context = ent.context;
2792 anim = ent.array.getResourceId(animAttr, 0);
2793 }
2794 }
2795 if (anim != 0) {
2796 return AnimationUtils.loadAnimation(context, anim);
2797 }
2798 return null;
2799 }
Romain Guy06882f82009-06-10 13:36:04 -07002800
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002801 private Animation loadAnimation(String packageName, int resId) {
2802 int anim = 0;
2803 Context context = mContext;
2804 if (resId >= 0) {
2805 AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
2806 if (ent != null) {
2807 context = ent.context;
2808 anim = resId;
2809 }
2810 }
2811 if (anim != 0) {
2812 return AnimationUtils.loadAnimation(context, anim);
2813 }
2814 return null;
2815 }
2816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002817 private boolean applyAnimationLocked(AppWindowToken wtoken,
2818 WindowManager.LayoutParams lp, int transit, boolean enter) {
2819 // Only apply an animation if the display isn't frozen. If it is
2820 // frozen, there is no reason to animate and it can cause strange
2821 // artifacts when we unfreeze the display if some different animation
2822 // is running.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002823 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002824 Animation a;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07002825 if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002826 a = new FadeInOutAnimation(enter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002827 if (DEBUG_ANIM) Slog.v(TAG,
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002828 "applying FadeInOutAnimation for a window in compatibility mode");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002829 } else if (mNextAppTransitionPackage != null) {
2830 a = loadAnimation(mNextAppTransitionPackage, enter ?
2831 mNextAppTransitionEnter : mNextAppTransitionExit);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002832 } else {
2833 int animAttr = 0;
2834 switch (transit) {
2835 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
2836 animAttr = enter
2837 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
2838 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
2839 break;
2840 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
2841 animAttr = enter
2842 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
2843 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
2844 break;
2845 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
2846 animAttr = enter
2847 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
2848 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
2849 break;
2850 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
2851 animAttr = enter
2852 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
2853 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
2854 break;
2855 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
2856 animAttr = enter
2857 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
2858 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
2859 break;
2860 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
2861 animAttr = enter
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07002862 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002863 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
2864 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002865 case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002866 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002867 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation
2868 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002869 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002870 case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002871 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002872 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation
2873 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
2874 break;
2875 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN:
2876 animAttr = enter
2877 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation
2878 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
2879 break;
2880 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE:
2881 animAttr = enter
2882 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation
2883 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002884 break;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002885 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002886 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002887 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002888 + " anim=" + a
2889 + " animAttr=0x" + Integer.toHexString(animAttr)
2890 + " transit=" + transit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002891 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002892 if (a != null) {
2893 if (DEBUG_ANIM) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002894 RuntimeException e = null;
2895 if (!HIDE_STACK_CRAWLS) {
2896 e = new RuntimeException();
2897 e.fillInStackTrace();
2898 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002899 Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002900 }
2901 wtoken.setAnimation(a);
2902 }
2903 } else {
2904 wtoken.clearAnimation();
2905 }
2906
2907 return wtoken.animation != null;
2908 }
2909
2910 // -------------------------------------------------------------
2911 // Application Window Tokens
2912 // -------------------------------------------------------------
2913
2914 public void validateAppTokens(List tokens) {
2915 int v = tokens.size()-1;
2916 int m = mAppTokens.size()-1;
2917 while (v >= 0 && m >= 0) {
2918 AppWindowToken wtoken = mAppTokens.get(m);
2919 if (wtoken.removed) {
2920 m--;
2921 continue;
2922 }
2923 if (tokens.get(v) != wtoken.token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002924 Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
2926 }
2927 v--;
2928 m--;
2929 }
2930 while (v >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002931 Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 v--;
2933 }
2934 while (m >= 0) {
2935 AppWindowToken wtoken = mAppTokens.get(m);
2936 if (!wtoken.removed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002937 Slog.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 }
2939 m--;
2940 }
2941 }
2942
2943 boolean checkCallingPermission(String permission, String func) {
2944 // Quick check: if the calling permission is me, it's all okay.
2945 if (Binder.getCallingPid() == Process.myPid()) {
2946 return true;
2947 }
Romain Guy06882f82009-06-10 13:36:04 -07002948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002949 if (mContext.checkCallingPermission(permission)
2950 == PackageManager.PERMISSION_GRANTED) {
2951 return true;
2952 }
2953 String msg = "Permission Denial: " + func + " from pid="
2954 + Binder.getCallingPid()
2955 + ", uid=" + Binder.getCallingUid()
2956 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002957 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 return false;
2959 }
Romain Guy06882f82009-06-10 13:36:04 -07002960
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002961 AppWindowToken findAppWindowToken(IBinder token) {
2962 WindowToken wtoken = mTokenMap.get(token);
2963 if (wtoken == null) {
2964 return null;
2965 }
2966 return wtoken.appWindowToken;
2967 }
Romain Guy06882f82009-06-10 13:36:04 -07002968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002969 public void addWindowToken(IBinder token, int type) {
2970 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2971 "addWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002972 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002973 }
Romain Guy06882f82009-06-10 13:36:04 -07002974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002975 synchronized(mWindowMap) {
2976 WindowToken wtoken = mTokenMap.get(token);
2977 if (wtoken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002978 Slog.w(TAG, "Attempted to add existing input method token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002979 return;
2980 }
2981 wtoken = new WindowToken(token, type, true);
2982 mTokenMap.put(token, wtoken);
2983 mTokenList.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002984 if (type == TYPE_WALLPAPER) {
2985 mWallpaperTokens.add(wtoken);
2986 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002987 }
2988 }
Romain Guy06882f82009-06-10 13:36:04 -07002989
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002990 public void removeWindowToken(IBinder token) {
2991 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2992 "removeWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002993 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002994 }
2995
2996 final long origId = Binder.clearCallingIdentity();
2997 synchronized(mWindowMap) {
2998 WindowToken wtoken = mTokenMap.remove(token);
2999 mTokenList.remove(wtoken);
3000 if (wtoken != null) {
3001 boolean delayed = false;
3002 if (!wtoken.hidden) {
3003 wtoken.hidden = true;
Romain Guy06882f82009-06-10 13:36:04 -07003004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003005 final int N = wtoken.windows.size();
3006 boolean changed = false;
Romain Guy06882f82009-06-10 13:36:04 -07003007
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003008 for (int i=0; i<N; i++) {
3009 WindowState win = wtoken.windows.get(i);
3010
3011 if (win.isAnimating()) {
3012 delayed = true;
3013 }
Romain Guy06882f82009-06-10 13:36:04 -07003014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003015 if (win.isVisibleNow()) {
3016 applyAnimationLocked(win,
3017 WindowManagerPolicy.TRANSIT_EXIT, false);
3018 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
3019 KeyWaiter.RETURN_NOTHING);
3020 changed = true;
3021 }
3022 }
3023
3024 if (changed) {
3025 mLayoutNeeded = true;
3026 performLayoutAndPlaceSurfacesLocked();
3027 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3028 }
Romain Guy06882f82009-06-10 13:36:04 -07003029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 if (delayed) {
3031 mExitingTokens.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07003032 } else if (wtoken.windowType == TYPE_WALLPAPER) {
3033 mWallpaperTokens.remove(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 }
3035 }
Romain Guy06882f82009-06-10 13:36:04 -07003036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003038 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003039 }
3040 }
3041 Binder.restoreCallingIdentity(origId);
3042 }
3043
3044 public void addAppToken(int addPos, IApplicationToken token,
3045 int groupId, int requestedOrientation, boolean fullscreen) {
3046 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3047 "addAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003048 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003049 }
Romain Guy06882f82009-06-10 13:36:04 -07003050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003051 synchronized(mWindowMap) {
3052 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3053 if (wtoken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003054 Slog.w(TAG, "Attempted to add existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003055 return;
3056 }
3057 wtoken = new AppWindowToken(token);
3058 wtoken.groupId = groupId;
3059 wtoken.appFullscreen = fullscreen;
3060 wtoken.requestedOrientation = requestedOrientation;
3061 mAppTokens.add(addPos, wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003062 if (localLOGV) Slog.v(TAG, "Adding new app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003063 mTokenMap.put(token.asBinder(), wtoken);
3064 mTokenList.add(wtoken);
Romain Guy06882f82009-06-10 13:36:04 -07003065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003066 // Application tokens start out hidden.
3067 wtoken.hidden = true;
3068 wtoken.hiddenRequested = true;
Romain Guy06882f82009-06-10 13:36:04 -07003069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003070 //dump();
3071 }
3072 }
Romain Guy06882f82009-06-10 13:36:04 -07003073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003074 public void setAppGroupId(IBinder token, int groupId) {
3075 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3076 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003077 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 }
3079
3080 synchronized(mWindowMap) {
3081 AppWindowToken wtoken = findAppWindowToken(token);
3082 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003083 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003084 return;
3085 }
3086 wtoken.groupId = groupId;
3087 }
3088 }
Romain Guy06882f82009-06-10 13:36:04 -07003089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003090 public int getOrientationFromWindowsLocked() {
3091 int pos = mWindows.size() - 1;
3092 while (pos >= 0) {
3093 WindowState wtoken = (WindowState) mWindows.get(pos);
3094 pos--;
3095 if (wtoken.mAppToken != null) {
3096 // We hit an application window. so the orientation will be determined by the
3097 // app window. No point in continuing further.
3098 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3099 }
Christopher Tateb696aee2010-04-02 19:08:30 -07003100 if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003101 continue;
3102 }
3103 int req = wtoken.mAttrs.screenOrientation;
3104 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3105 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3106 continue;
3107 } else {
3108 return req;
3109 }
3110 }
3111 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3112 }
Romain Guy06882f82009-06-10 13:36:04 -07003113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003114 public int getOrientationFromAppTokensLocked() {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003115 int pos = mAppTokens.size() - 1;
3116 int curGroup = 0;
3117 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3118 boolean findingBehind = false;
3119 boolean haveGroup = false;
3120 boolean lastFullscreen = false;
3121 while (pos >= 0) {
3122 AppWindowToken wtoken = mAppTokens.get(pos);
3123 pos--;
3124 // if we're about to tear down this window and not seek for
3125 // the behind activity, don't use it for orientation
3126 if (!findingBehind
3127 && (!wtoken.hidden && wtoken.hiddenRequested)) {
3128 continue;
3129 }
3130
3131 if (!haveGroup) {
3132 // We ignore any hidden applications on the top.
3133 if (wtoken.hiddenRequested || wtoken.willBeHidden) {
The Android Open Source Project10592532009-03-18 17:39:46 -07003134 continue;
3135 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003136 haveGroup = true;
3137 curGroup = wtoken.groupId;
3138 lastOrientation = wtoken.requestedOrientation;
3139 } else if (curGroup != wtoken.groupId) {
3140 // If we have hit a new application group, and the bottom
3141 // of the previous group didn't explicitly say to use
3142 // the orientation behind it, and the last app was
3143 // full screen, then we'll stick with the
3144 // user's orientation.
3145 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3146 && lastFullscreen) {
3147 return lastOrientation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003148 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003149 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003150 int or = wtoken.requestedOrientation;
3151 // If this application is fullscreen, and didn't explicitly say
3152 // to use the orientation behind it, then just take whatever
3153 // orientation it has and ignores whatever is under it.
3154 lastFullscreen = wtoken.appFullscreen;
3155 if (lastFullscreen
3156 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3157 return or;
3158 }
3159 // If this application has requested an explicit orientation,
3160 // then use it.
3161 if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
3162 or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
3163 or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
3164 or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
3165 or == ActivityInfo.SCREEN_ORIENTATION_USER) {
3166 return or;
3167 }
3168 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3169 }
3170 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003171 }
Romain Guy06882f82009-06-10 13:36:04 -07003172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003173 public Configuration updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003174 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003175 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3176 "updateOrientationFromAppTokens()")) {
3177 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3178 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003179
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003180 Configuration config = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003181 long ident = Binder.clearCallingIdentity();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003182
3183 synchronized(mWindowMap) {
3184 if (updateOrientationFromAppTokensLocked()) {
3185 if (freezeThisOneIfNeeded != null) {
3186 AppWindowToken wtoken = findAppWindowToken(
3187 freezeThisOneIfNeeded);
3188 if (wtoken != null) {
3189 startAppFreezingScreenLocked(wtoken,
3190 ActivityInfo.CONFIG_ORIENTATION);
3191 }
3192 }
3193 config = computeNewConfigurationLocked();
3194
3195 } else if (currentConfig != null) {
3196 // No obvious action we need to take, but if our current
3197 // state mismatches the activity maanager's, update it
3198 mTempConfiguration.setToDefaults();
3199 if (computeNewConfigurationLocked(mTempConfiguration)) {
3200 if (currentConfig.diff(mTempConfiguration) != 0) {
3201 mWaitingForConfig = true;
3202 mLayoutNeeded = true;
3203 startFreezingDisplayLocked();
3204 config = new Configuration(mTempConfiguration);
3205 }
3206 }
3207 }
3208 }
3209
Dianne Hackborncfaef692009-06-15 14:24:44 -07003210 Binder.restoreCallingIdentity(ident);
3211 return config;
3212 }
3213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 /*
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003215 * Determine the new desired orientation of the display, returning
3216 * a non-null new Configuration if it has changed from the current
3217 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
3218 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3219 * SCREEN. This will typically be done for you if you call
3220 * sendNewConfiguration().
3221 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 * The orientation is computed from non-application windows first. If none of
3223 * the non-application windows specify orientation, the orientation is computed from
Romain Guy06882f82009-06-10 13:36:04 -07003224 * application tokens.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003225 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3226 * android.os.IBinder)
3227 */
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003228 boolean updateOrientationFromAppTokensLocked() {
Christopher Tateb696aee2010-04-02 19:08:30 -07003229 if (mDisplayFrozen) {
3230 // If the display is frozen, some activities may be in the middle
3231 // of restarting, and thus have removed their old window. If the
3232 // window has the flag to hide the lock screen, then the lock screen
3233 // can re-appear and inflict its own orientation on us. Keep the
3234 // orientation stable until this all settles down.
3235 return false;
3236 }
3237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003238 boolean changed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003239 long ident = Binder.clearCallingIdentity();
3240 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003241 int req = computeForcedAppOrientationLocked();
Romain Guy06882f82009-06-10 13:36:04 -07003242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003243 if (req != mForcedAppOrientation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003244 mForcedAppOrientation = req;
3245 //send a message to Policy indicating orientation change to take
3246 //action like disabling/enabling sensors etc.,
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003247 mPolicy.setCurrentOrientationLw(req);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003248 if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
3249 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)) {
3250 changed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 }
3252 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003253
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003254 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 } finally {
3256 Binder.restoreCallingIdentity(ident);
3257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 }
Romain Guy06882f82009-06-10 13:36:04 -07003259
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003260 int computeForcedAppOrientationLocked() {
3261 int req = getOrientationFromWindowsLocked();
3262 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3263 req = getOrientationFromAppTokensLocked();
3264 }
3265 return req;
3266 }
Romain Guy06882f82009-06-10 13:36:04 -07003267
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003268 public void setNewConfiguration(Configuration config) {
3269 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3270 "setNewConfiguration()")) {
3271 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3272 }
3273
3274 synchronized(mWindowMap) {
3275 mCurConfiguration = new Configuration(config);
3276 mWaitingForConfig = false;
3277 performLayoutAndPlaceSurfacesLocked();
3278 }
3279 }
3280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003281 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3282 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3283 "setAppOrientation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003284 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003285 }
Romain Guy06882f82009-06-10 13:36:04 -07003286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003287 synchronized(mWindowMap) {
3288 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3289 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003290 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003291 return;
3292 }
Romain Guy06882f82009-06-10 13:36:04 -07003293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 wtoken.requestedOrientation = requestedOrientation;
3295 }
3296 }
Romain Guy06882f82009-06-10 13:36:04 -07003297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003298 public int getAppOrientation(IApplicationToken token) {
3299 synchronized(mWindowMap) {
3300 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3301 if (wtoken == null) {
3302 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3303 }
Romain Guy06882f82009-06-10 13:36:04 -07003304
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003305 return wtoken.requestedOrientation;
3306 }
3307 }
Romain Guy06882f82009-06-10 13:36:04 -07003308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3310 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3311 "setFocusedApp()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003312 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 }
3314
3315 synchronized(mWindowMap) {
3316 boolean changed = false;
3317 if (token == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003318 if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 changed = mFocusedApp != null;
3320 mFocusedApp = null;
3321 mKeyWaiter.tickle();
3322 } else {
3323 AppWindowToken newFocus = findAppWindowToken(token);
3324 if (newFocus == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003325 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003326 return;
3327 }
3328 changed = mFocusedApp != newFocus;
3329 mFocusedApp = newFocus;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003330 if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003331 mKeyWaiter.tickle();
3332 }
3333
3334 if (moveFocusNow && changed) {
3335 final long origId = Binder.clearCallingIdentity();
3336 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3337 Binder.restoreCallingIdentity(origId);
3338 }
3339 }
3340 }
3341
3342 public void prepareAppTransition(int transit) {
3343 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3344 "prepareAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003345 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003346 }
Romain Guy06882f82009-06-10 13:36:04 -07003347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003348 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003349 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003350 TAG, "Prepare app transition: transit=" + transit
3351 + " mNextAppTransition=" + mNextAppTransition);
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003352 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003353 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
3354 || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003355 mNextAppTransition = transit;
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07003356 } else if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
3357 && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) {
3358 // Opening a new task always supersedes a close for the anim.
3359 mNextAppTransition = transit;
3360 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
3361 && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) {
3362 // Opening a new activity always supersedes a close for the anim.
3363 mNextAppTransition = transit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364 }
3365 mAppTransitionReady = false;
3366 mAppTransitionTimeout = false;
3367 mStartingIconInTransition = false;
3368 mSkipAppTransitionAnimation = false;
3369 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3370 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT),
3371 5000);
3372 }
3373 }
3374 }
3375
3376 public int getPendingAppTransition() {
3377 return mNextAppTransition;
3378 }
Romain Guy06882f82009-06-10 13:36:04 -07003379
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003380 public void overridePendingAppTransition(String packageName,
3381 int enterAnim, int exitAnim) {
Dianne Hackborn8b571a82009-09-25 16:09:43 -07003382 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003383 mNextAppTransitionPackage = packageName;
3384 mNextAppTransitionEnter = enterAnim;
3385 mNextAppTransitionExit = exitAnim;
3386 }
3387 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003389 public void executeAppTransition() {
3390 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3391 "executeAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003392 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003393 }
Romain Guy06882f82009-06-10 13:36:04 -07003394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 synchronized(mWindowMap) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003396 if (DEBUG_APP_TRANSITIONS) {
3397 RuntimeException e = new RuntimeException("here");
3398 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -08003399 Slog.w(TAG, "Execute app transition: mNextAppTransition="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003400 + mNextAppTransition, e);
3401 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003402 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003403 mAppTransitionReady = true;
3404 final long origId = Binder.clearCallingIdentity();
3405 performLayoutAndPlaceSurfacesLocked();
3406 Binder.restoreCallingIdentity(origId);
3407 }
3408 }
3409 }
3410
3411 public void setAppStartingWindow(IBinder token, String pkg,
3412 int theme, CharSequence nonLocalizedLabel, int labelRes, int icon,
3413 IBinder transferFrom, boolean createIfNeeded) {
3414 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3415 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003416 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003417 }
3418
3419 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003420 if (DEBUG_STARTING_WINDOW) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
3422 + " transferFrom=" + transferFrom);
Romain Guy06882f82009-06-10 13:36:04 -07003423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003424 AppWindowToken wtoken = findAppWindowToken(token);
3425 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003426 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003427 return;
3428 }
3429
3430 // If the display is frozen, we won't do anything until the
3431 // actual window is displayed so there is no reason to put in
3432 // the starting window.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08003433 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 return;
3435 }
Romain Guy06882f82009-06-10 13:36:04 -07003436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003437 if (wtoken.startingData != null) {
3438 return;
3439 }
Romain Guy06882f82009-06-10 13:36:04 -07003440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003441 if (transferFrom != null) {
3442 AppWindowToken ttoken = findAppWindowToken(transferFrom);
3443 if (ttoken != null) {
3444 WindowState startingWindow = ttoken.startingWindow;
3445 if (startingWindow != null) {
3446 if (mStartingIconInTransition) {
3447 // In this case, the starting icon has already
3448 // been displayed, so start letting windows get
3449 // shown immediately without any more transitions.
3450 mSkipAppTransitionAnimation = true;
3451 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003452 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003453 "Moving existing starting from " + ttoken
3454 + " to " + wtoken);
3455 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07003456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003457 // Transfer the starting window over to the new
3458 // token.
3459 wtoken.startingData = ttoken.startingData;
3460 wtoken.startingView = ttoken.startingView;
3461 wtoken.startingWindow = startingWindow;
3462 ttoken.startingData = null;
3463 ttoken.startingView = null;
3464 ttoken.startingWindow = null;
3465 ttoken.startingMoved = true;
3466 startingWindow.mToken = wtoken;
Dianne Hackbornef49c572009-03-24 19:27:32 -07003467 startingWindow.mRootToken = wtoken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003468 startingWindow.mAppToken = wtoken;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003469 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003470 "Removing starting window: " + startingWindow);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471 mWindows.remove(startingWindow);
3472 ttoken.windows.remove(startingWindow);
3473 ttoken.allAppWindows.remove(startingWindow);
3474 addWindowToListInOrderLocked(startingWindow, true);
Romain Guy06882f82009-06-10 13:36:04 -07003475
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003476 // Propagate other interesting state between the
3477 // tokens. If the old token is displayed, we should
3478 // immediately force the new one to be displayed. If
3479 // it is animating, we need to move that animation to
3480 // the new one.
3481 if (ttoken.allDrawn) {
3482 wtoken.allDrawn = true;
3483 }
3484 if (ttoken.firstWindowDrawn) {
3485 wtoken.firstWindowDrawn = true;
3486 }
3487 if (!ttoken.hidden) {
3488 wtoken.hidden = false;
3489 wtoken.hiddenRequested = false;
3490 wtoken.willBeHidden = false;
3491 }
3492 if (wtoken.clientHidden != ttoken.clientHidden) {
3493 wtoken.clientHidden = ttoken.clientHidden;
3494 wtoken.sendAppVisibilityToClients();
3495 }
3496 if (ttoken.animation != null) {
3497 wtoken.animation = ttoken.animation;
3498 wtoken.animating = ttoken.animating;
3499 wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
3500 ttoken.animation = null;
3501 ttoken.animLayerAdjustment = 0;
3502 wtoken.updateLayers();
3503 ttoken.updateLayers();
3504 }
Romain Guy06882f82009-06-10 13:36:04 -07003505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003506 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003507 mLayoutNeeded = true;
3508 performLayoutAndPlaceSurfacesLocked();
3509 Binder.restoreCallingIdentity(origId);
3510 return;
3511 } else if (ttoken.startingData != null) {
3512 // The previous app was getting ready to show a
3513 // starting window, but hasn't yet done so. Steal it!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003514 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003515 "Moving pending starting from " + ttoken
3516 + " to " + wtoken);
3517 wtoken.startingData = ttoken.startingData;
3518 ttoken.startingData = null;
3519 ttoken.startingMoved = true;
3520 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3521 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3522 // want to process the message ASAP, before any other queued
3523 // messages.
3524 mH.sendMessageAtFrontOfQueue(m);
3525 return;
3526 }
3527 }
3528 }
3529
3530 // There is no existing starting window, and the caller doesn't
3531 // want us to create one, so that's it!
3532 if (!createIfNeeded) {
3533 return;
3534 }
Romain Guy06882f82009-06-10 13:36:04 -07003535
Dianne Hackborn284ac932009-08-28 10:34:25 -07003536 // If this is a translucent or wallpaper window, then don't
3537 // show a starting window -- the current effect (a full-screen
3538 // opaque starting window that fades away to the real contents
3539 // when it is ready) does not work for this.
3540 if (theme != 0) {
3541 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
3542 com.android.internal.R.styleable.Window);
3543 if (ent.array.getBoolean(
3544 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
3545 return;
3546 }
3547 if (ent.array.getBoolean(
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07003548 com.android.internal.R.styleable.Window_windowIsFloating, false)) {
3549 return;
3550 }
3551 if (ent.array.getBoolean(
Dianne Hackborn284ac932009-08-28 10:34:25 -07003552 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
3553 return;
3554 }
3555 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003557 mStartingIconInTransition = true;
3558 wtoken.startingData = new StartingData(
3559 pkg, theme, nonLocalizedLabel,
3560 labelRes, icon);
3561 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3562 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3563 // want to process the message ASAP, before any other queued
3564 // messages.
3565 mH.sendMessageAtFrontOfQueue(m);
3566 }
3567 }
3568
3569 public void setAppWillBeHidden(IBinder token) {
3570 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3571 "setAppWillBeHidden()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003572 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003573 }
3574
3575 AppWindowToken wtoken;
3576
3577 synchronized(mWindowMap) {
3578 wtoken = findAppWindowToken(token);
3579 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003580 Slog.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581 return;
3582 }
3583 wtoken.willBeHidden = true;
3584 }
3585 }
Romain Guy06882f82009-06-10 13:36:04 -07003586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003587 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
3588 boolean visible, int transit, boolean performLayout) {
3589 boolean delayed = false;
3590
3591 if (wtoken.clientHidden == visible) {
3592 wtoken.clientHidden = !visible;
3593 wtoken.sendAppVisibilityToClients();
3594 }
Romain Guy06882f82009-06-10 13:36:04 -07003595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003596 wtoken.willBeHidden = false;
3597 if (wtoken.hidden == visible) {
3598 final int N = wtoken.allAppWindows.size();
3599 boolean changed = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003600 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003601 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
3602 + " performLayout=" + performLayout);
Romain Guy06882f82009-06-10 13:36:04 -07003603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003604 boolean runningAppAnimation = false;
Romain Guy06882f82009-06-10 13:36:04 -07003605
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003606 if (transit != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003607 if (wtoken.animation == sDummyAnimation) {
3608 wtoken.animation = null;
3609 }
3610 applyAnimationLocked(wtoken, lp, transit, visible);
3611 changed = true;
3612 if (wtoken.animation != null) {
3613 delayed = runningAppAnimation = true;
3614 }
3615 }
Romain Guy06882f82009-06-10 13:36:04 -07003616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003617 for (int i=0; i<N; i++) {
3618 WindowState win = wtoken.allAppWindows.get(i);
3619 if (win == wtoken.startingWindow) {
3620 continue;
3621 }
3622
3623 if (win.isAnimating()) {
3624 delayed = true;
3625 }
Romain Guy06882f82009-06-10 13:36:04 -07003626
Joe Onorato8a9b2202010-02-26 18:56:32 -08003627 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003628 //win.dump(" ");
3629 if (visible) {
3630 if (!win.isVisibleNow()) {
3631 if (!runningAppAnimation) {
3632 applyAnimationLocked(win,
3633 WindowManagerPolicy.TRANSIT_ENTER, true);
3634 }
3635 changed = true;
3636 }
3637 } else if (win.isVisibleNow()) {
3638 if (!runningAppAnimation) {
3639 applyAnimationLocked(win,
3640 WindowManagerPolicy.TRANSIT_EXIT, false);
3641 }
3642 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
3643 KeyWaiter.RETURN_NOTHING);
3644 changed = true;
3645 }
3646 }
3647
3648 wtoken.hidden = wtoken.hiddenRequested = !visible;
3649 if (!visible) {
3650 unsetAppFreezingScreenLocked(wtoken, true, true);
3651 } else {
3652 // If we are being set visible, and the starting window is
3653 // not yet displayed, then make sure it doesn't get displayed.
3654 WindowState swin = wtoken.startingWindow;
3655 if (swin != null && (swin.mDrawPending
3656 || swin.mCommitDrawPending)) {
3657 swin.mPolicyVisibility = false;
3658 swin.mPolicyVisibilityAfterAnim = false;
3659 }
3660 }
Romain Guy06882f82009-06-10 13:36:04 -07003661
Joe Onorato8a9b2202010-02-26 18:56:32 -08003662 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003663 + ": hidden=" + wtoken.hidden + " hiddenRequested="
3664 + wtoken.hiddenRequested);
Romain Guy06882f82009-06-10 13:36:04 -07003665
Dianne Hackborn9b52a212009-12-11 14:51:35 -08003666 if (changed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 mLayoutNeeded = true;
Dianne Hackborn9b52a212009-12-11 14:51:35 -08003668 if (performLayout) {
3669 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
3670 performLayoutAndPlaceSurfacesLocked();
3671 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 }
3673 }
3674
3675 if (wtoken.animation != null) {
3676 delayed = true;
3677 }
Romain Guy06882f82009-06-10 13:36:04 -07003678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003679 return delayed;
3680 }
3681
3682 public void setAppVisibility(IBinder token, boolean visible) {
3683 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3684 "setAppVisibility()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003685 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003686 }
3687
3688 AppWindowToken wtoken;
3689
3690 synchronized(mWindowMap) {
3691 wtoken = findAppWindowToken(token);
3692 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003693 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003694 return;
3695 }
3696
3697 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08003698 RuntimeException e = null;
3699 if (!HIDE_STACK_CRAWLS) {
3700 e = new RuntimeException();
3701 e.fillInStackTrace();
3702 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003703 Slog.v(TAG, "setAppVisibility(" + token + ", " + visible
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003704 + "): mNextAppTransition=" + mNextAppTransition
3705 + " hidden=" + wtoken.hidden
3706 + " hiddenRequested=" + wtoken.hiddenRequested, e);
3707 }
Romain Guy06882f82009-06-10 13:36:04 -07003708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003709 // If we are preparing an app transition, then delay changing
3710 // the visibility of this token until we execute that transition.
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003711 if (!mDisplayFrozen && mPolicy.isScreenOn()
3712 && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003713 // Already in requested state, don't do anything more.
3714 if (wtoken.hiddenRequested != visible) {
3715 return;
3716 }
3717 wtoken.hiddenRequested = !visible;
Romain Guy06882f82009-06-10 13:36:04 -07003718
Joe Onorato8a9b2202010-02-26 18:56:32 -08003719 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 TAG, "Setting dummy animation on: " + wtoken);
3721 wtoken.setDummyAnimation();
3722 mOpeningApps.remove(wtoken);
3723 mClosingApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003724 wtoken.waitingToShow = wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003725 wtoken.inPendingTransaction = true;
3726 if (visible) {
3727 mOpeningApps.add(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003728 wtoken.startingDisplayed = false;
3729 wtoken.startingMoved = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003730
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003731 // If the token is currently hidden (should be the
3732 // common case), then we need to set up to wait for
3733 // its windows to be ready.
3734 if (wtoken.hidden) {
3735 wtoken.allDrawn = false;
3736 wtoken.waitingToShow = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003737
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003738 if (wtoken.clientHidden) {
3739 // In the case where we are making an app visible
3740 // but holding off for a transition, we still need
3741 // to tell the client to make its windows visible so
3742 // they get drawn. Otherwise, we will wait on
3743 // performing the transition until all windows have
3744 // been drawn, they never will be, and we are sad.
3745 wtoken.clientHidden = false;
3746 wtoken.sendAppVisibilityToClients();
3747 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003748 }
3749 } else {
3750 mClosingApps.add(wtoken);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003751
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003752 // If the token is currently visible (should be the
3753 // common case), then set up to wait for it to be hidden.
3754 if (!wtoken.hidden) {
3755 wtoken.waitingToHide = true;
3756 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003757 }
3758 return;
3759 }
Romain Guy06882f82009-06-10 13:36:04 -07003760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003761 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003762 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 wtoken.updateReportedVisibilityLocked();
3764 Binder.restoreCallingIdentity(origId);
3765 }
3766 }
3767
3768 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
3769 boolean unfreezeSurfaceNow, boolean force) {
3770 if (wtoken.freezingScreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003771 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 + " force=" + force);
3773 final int N = wtoken.allAppWindows.size();
3774 boolean unfrozeWindows = false;
3775 for (int i=0; i<N; i++) {
3776 WindowState w = wtoken.allAppWindows.get(i);
3777 if (w.mAppFreezing) {
3778 w.mAppFreezing = false;
3779 if (w.mSurface != null && !w.mOrientationChanging) {
3780 w.mOrientationChanging = true;
3781 }
3782 unfrozeWindows = true;
3783 }
3784 }
3785 if (force || unfrozeWindows) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003786 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003787 wtoken.freezingScreen = false;
3788 mAppsFreezingScreen--;
3789 }
3790 if (unfreezeSurfaceNow) {
3791 if (unfrozeWindows) {
3792 mLayoutNeeded = true;
3793 performLayoutAndPlaceSurfacesLocked();
3794 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003795 stopFreezingDisplayLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003796 }
3797 }
3798 }
Romain Guy06882f82009-06-10 13:36:04 -07003799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003800 public void startAppFreezingScreenLocked(AppWindowToken wtoken,
3801 int configChanges) {
3802 if (DEBUG_ORIENTATION) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08003803 RuntimeException e = null;
3804 if (!HIDE_STACK_CRAWLS) {
3805 e = new RuntimeException();
3806 e.fillInStackTrace();
3807 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003808 Slog.i(TAG, "Set freezing of " + wtoken.appToken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003809 + ": hidden=" + wtoken.hidden + " freezing="
3810 + wtoken.freezingScreen, e);
3811 }
3812 if (!wtoken.hiddenRequested) {
3813 if (!wtoken.freezingScreen) {
3814 wtoken.freezingScreen = true;
3815 mAppsFreezingScreen++;
3816 if (mAppsFreezingScreen == 1) {
3817 startFreezingDisplayLocked();
3818 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
3819 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
3820 5000);
3821 }
3822 }
3823 final int N = wtoken.allAppWindows.size();
3824 for (int i=0; i<N; i++) {
3825 WindowState w = wtoken.allAppWindows.get(i);
3826 w.mAppFreezing = true;
3827 }
3828 }
3829 }
Romain Guy06882f82009-06-10 13:36:04 -07003830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 public void startAppFreezingScreen(IBinder token, int configChanges) {
3832 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3833 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003834 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003835 }
3836
3837 synchronized(mWindowMap) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003838 if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOn()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003839 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003840 return;
3841 }
Romain Guy06882f82009-06-10 13:36:04 -07003842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003843 AppWindowToken wtoken = findAppWindowToken(token);
3844 if (wtoken == null || wtoken.appToken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003845 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003846 return;
3847 }
3848 final long origId = Binder.clearCallingIdentity();
3849 startAppFreezingScreenLocked(wtoken, configChanges);
3850 Binder.restoreCallingIdentity(origId);
3851 }
3852 }
Romain Guy06882f82009-06-10 13:36:04 -07003853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 public void stopAppFreezingScreen(IBinder token, boolean force) {
3855 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3856 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003857 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003858 }
3859
3860 synchronized(mWindowMap) {
3861 AppWindowToken wtoken = findAppWindowToken(token);
3862 if (wtoken == null || wtoken.appToken == null) {
3863 return;
3864 }
3865 final long origId = Binder.clearCallingIdentity();
Joe Onorato8a9b2202010-02-26 18:56:32 -08003866 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
3868 unsetAppFreezingScreenLocked(wtoken, true, force);
3869 Binder.restoreCallingIdentity(origId);
3870 }
3871 }
Romain Guy06882f82009-06-10 13:36:04 -07003872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003873 public void removeAppToken(IBinder token) {
3874 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3875 "removeAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003876 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 }
3878
3879 AppWindowToken wtoken = null;
3880 AppWindowToken startingToken = null;
3881 boolean delayed = false;
3882
3883 final long origId = Binder.clearCallingIdentity();
3884 synchronized(mWindowMap) {
3885 WindowToken basewtoken = mTokenMap.remove(token);
3886 mTokenList.remove(basewtoken);
3887 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003888 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003889 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 wtoken.inPendingTransaction = false;
3891 mOpeningApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003892 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003893 if (mClosingApps.contains(wtoken)) {
3894 delayed = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003895 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 mClosingApps.add(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003897 wtoken.waitingToHide = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 delayed = true;
3899 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003900 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003901 TAG, "Removing app " + wtoken + " delayed=" + delayed
3902 + " animation=" + wtoken.animation
3903 + " animating=" + wtoken.animating);
3904 if (delayed) {
3905 // set the token aside because it has an active animation to be finished
3906 mExitingAppTokens.add(wtoken);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003907 } else {
3908 // Make sure there is no animation running on this token,
3909 // so any windows associated with it will be removed as
3910 // soon as their animations are complete
3911 wtoken.animation = null;
3912 wtoken.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003913 }
3914 mAppTokens.remove(wtoken);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003915 if (mLastEnterAnimToken == wtoken) {
3916 mLastEnterAnimToken = null;
3917 mLastEnterAnimParams = null;
3918 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003919 wtoken.removed = true;
3920 if (wtoken.startingData != null) {
3921 startingToken = wtoken;
3922 }
3923 unsetAppFreezingScreenLocked(wtoken, true, true);
3924 if (mFocusedApp == wtoken) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003925 if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003926 mFocusedApp = null;
3927 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3928 mKeyWaiter.tickle();
3929 }
3930 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003931 Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 }
Romain Guy06882f82009-06-10 13:36:04 -07003933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003934 if (!delayed && wtoken != null) {
3935 wtoken.updateReportedVisibilityLocked();
3936 }
3937 }
3938 Binder.restoreCallingIdentity(origId);
3939
3940 if (startingToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003941 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 + startingToken + ": app token removed");
3943 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
3944 mH.sendMessage(m);
3945 }
3946 }
3947
3948 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
3949 final int NW = token.windows.size();
3950 for (int i=0; i<NW; i++) {
3951 WindowState win = token.windows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003952 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003953 mWindows.remove(win);
3954 int j = win.mChildWindows.size();
3955 while (j > 0) {
3956 j--;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003957 WindowState cwin = (WindowState)win.mChildWindows.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003958 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003959 "Tmp removing child window " + cwin);
3960 mWindows.remove(cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 }
3962 }
3963 return NW > 0;
3964 }
3965
3966 void dumpAppTokensLocked() {
3967 for (int i=mAppTokens.size()-1; i>=0; i--) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003968 Slog.v(TAG, " #" + i + ": " + mAppTokens.get(i).token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003969 }
3970 }
Romain Guy06882f82009-06-10 13:36:04 -07003971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003972 void dumpWindowsLocked() {
3973 for (int i=mWindows.size()-1; i>=0; i--) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003974 Slog.v(TAG, " #" + i + ": " + mWindows.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003975 }
3976 }
Romain Guy06882f82009-06-10 13:36:04 -07003977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003978 private int findWindowOffsetLocked(int tokenPos) {
3979 final int NW = mWindows.size();
3980
3981 if (tokenPos >= mAppTokens.size()) {
3982 int i = NW;
3983 while (i > 0) {
3984 i--;
3985 WindowState win = (WindowState)mWindows.get(i);
3986 if (win.getAppToken() != null) {
3987 return i+1;
3988 }
3989 }
3990 }
3991
3992 while (tokenPos > 0) {
3993 // Find the first app token below the new position that has
3994 // a window displayed.
3995 final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003996 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003997 + tokenPos + " -- " + wtoken.token);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003998 if (wtoken.sendingToBottom) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003999 if (DEBUG_REORDER) Slog.v(TAG,
Dianne Hackborna8f60182009-09-01 19:01:50 -07004000 "Skipping token -- currently sending to bottom");
4001 tokenPos--;
4002 continue;
4003 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004004 int i = wtoken.windows.size();
4005 while (i > 0) {
4006 i--;
4007 WindowState win = wtoken.windows.get(i);
4008 int j = win.mChildWindows.size();
4009 while (j > 0) {
4010 j--;
4011 WindowState cwin = (WindowState)win.mChildWindows.get(j);
Dianne Hackborna8f60182009-09-01 19:01:50 -07004012 if (cwin.mSubLayer >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004013 for (int pos=NW-1; pos>=0; pos--) {
4014 if (mWindows.get(pos) == cwin) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004015 if (DEBUG_REORDER) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004016 "Found child win @" + (pos+1));
4017 return pos+1;
4018 }
4019 }
4020 }
4021 }
4022 for (int pos=NW-1; pos>=0; pos--) {
4023 if (mWindows.get(pos) == win) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004024 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004025 return pos+1;
4026 }
4027 }
4028 }
4029 tokenPos--;
4030 }
4031
4032 return 0;
4033 }
4034
4035 private final int reAddWindowLocked(int index, WindowState win) {
4036 final int NCW = win.mChildWindows.size();
4037 boolean added = false;
4038 for (int j=0; j<NCW; j++) {
4039 WindowState cwin = (WindowState)win.mChildWindows.get(j);
4040 if (!added && cwin.mSubLayer >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004041 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004042 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004043 mWindows.add(index, win);
4044 index++;
4045 added = true;
4046 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004047 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004048 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 mWindows.add(index, cwin);
4050 index++;
4051 }
4052 if (!added) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004053 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004054 + index + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055 mWindows.add(index, win);
4056 index++;
4057 }
4058 return index;
4059 }
Romain Guy06882f82009-06-10 13:36:04 -07004060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061 private final int reAddAppWindowsLocked(int index, WindowToken token) {
4062 final int NW = token.windows.size();
4063 for (int i=0; i<NW; i++) {
4064 index = reAddWindowLocked(index, token.windows.get(i));
4065 }
4066 return index;
4067 }
4068
4069 public void moveAppToken(int index, IBinder token) {
4070 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4071 "moveAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004072 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004073 }
4074
4075 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004076 if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004077 if (DEBUG_REORDER) dumpAppTokensLocked();
4078 final AppWindowToken wtoken = findAppWindowToken(token);
4079 if (wtoken == null || !mAppTokens.remove(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004080 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004081 + token + " (" + wtoken + ")");
4082 return;
4083 }
4084 mAppTokens.add(index, wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004085 if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004086 if (DEBUG_REORDER) dumpAppTokensLocked();
Romain Guy06882f82009-06-10 13:36:04 -07004087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004088 final long origId = Binder.clearCallingIdentity();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004089 if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004090 if (DEBUG_REORDER) dumpWindowsLocked();
4091 if (tmpRemoveAppWindowsLocked(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004092 if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 if (DEBUG_REORDER) dumpWindowsLocked();
4094 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004095 if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004096 if (DEBUG_REORDER) dumpWindowsLocked();
4097 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 mLayoutNeeded = true;
4099 performLayoutAndPlaceSurfacesLocked();
4100 }
4101 Binder.restoreCallingIdentity(origId);
4102 }
4103 }
4104
4105 private void removeAppTokensLocked(List<IBinder> tokens) {
4106 // XXX This should be done more efficiently!
4107 // (take advantage of the fact that both lists should be
4108 // ordered in the same way.)
4109 int N = tokens.size();
4110 for (int i=0; i<N; i++) {
4111 IBinder token = tokens.get(i);
4112 final AppWindowToken wtoken = findAppWindowToken(token);
4113 if (!mAppTokens.remove(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004114 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004115 + token + " (" + wtoken + ")");
4116 i--;
4117 N--;
4118 }
4119 }
4120 }
4121
Dianne Hackborna8f60182009-09-01 19:01:50 -07004122 private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos,
4123 boolean updateFocusAndLayout) {
4124 // First remove all of the windows from the list.
4125 tmpRemoveAppWindowsLocked(wtoken);
4126
4127 // Where to start adding?
4128 int pos = findWindowOffsetLocked(tokenPos);
4129
4130 // And now add them back at the correct place.
4131 pos = reAddAppWindowsLocked(pos, wtoken);
4132
4133 if (updateFocusAndLayout) {
4134 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4135 assignLayersLocked();
4136 }
4137 mLayoutNeeded = true;
4138 performLayoutAndPlaceSurfacesLocked();
4139 }
4140 }
4141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004142 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
4143 // First remove all of the windows from the list.
4144 final int N = tokens.size();
4145 int i;
4146 for (i=0; i<N; i++) {
4147 WindowToken token = mTokenMap.get(tokens.get(i));
4148 if (token != null) {
4149 tmpRemoveAppWindowsLocked(token);
4150 }
4151 }
4152
4153 // Where to start adding?
4154 int pos = findWindowOffsetLocked(tokenPos);
4155
4156 // And now add them back at the correct place.
4157 for (i=0; i<N; i++) {
4158 WindowToken token = mTokenMap.get(tokens.get(i));
4159 if (token != null) {
4160 pos = reAddAppWindowsLocked(pos, token);
4161 }
4162 }
4163
Dianne Hackborna8f60182009-09-01 19:01:50 -07004164 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4165 assignLayersLocked();
4166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004167 mLayoutNeeded = true;
4168 performLayoutAndPlaceSurfacesLocked();
4169
4170 //dump();
4171 }
4172
4173 public void moveAppTokensToTop(List<IBinder> tokens) {
4174 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4175 "moveAppTokensToTop()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004176 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004177 }
4178
4179 final long origId = Binder.clearCallingIdentity();
4180 synchronized(mWindowMap) {
4181 removeAppTokensLocked(tokens);
4182 final int N = tokens.size();
4183 for (int i=0; i<N; i++) {
4184 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4185 if (wt != null) {
4186 mAppTokens.add(wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004187 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004188 mToTopApps.remove(wt);
4189 mToBottomApps.remove(wt);
4190 mToTopApps.add(wt);
4191 wt.sendingToBottom = false;
4192 wt.sendingToTop = true;
4193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004194 }
4195 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004196
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004197 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004198 moveAppWindowsLocked(tokens, mAppTokens.size());
4199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004200 }
4201 Binder.restoreCallingIdentity(origId);
4202 }
4203
4204 public void moveAppTokensToBottom(List<IBinder> tokens) {
4205 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4206 "moveAppTokensToBottom()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004207 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004208 }
4209
4210 final long origId = Binder.clearCallingIdentity();
4211 synchronized(mWindowMap) {
4212 removeAppTokensLocked(tokens);
4213 final int N = tokens.size();
4214 int pos = 0;
4215 for (int i=0; i<N; i++) {
4216 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4217 if (wt != null) {
4218 mAppTokens.add(pos, wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004219 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004220 mToTopApps.remove(wt);
4221 mToBottomApps.remove(wt);
4222 mToBottomApps.add(i, wt);
4223 wt.sendingToTop = false;
4224 wt.sendingToBottom = true;
4225 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004226 pos++;
4227 }
4228 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004229
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004230 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004231 moveAppWindowsLocked(tokens, 0);
4232 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004233 }
4234 Binder.restoreCallingIdentity(origId);
4235 }
4236
4237 // -------------------------------------------------------------
4238 // Misc IWindowSession methods
4239 // -------------------------------------------------------------
Romain Guy06882f82009-06-10 13:36:04 -07004240
Jim Miller284b62e2010-06-08 14:27:42 -07004241 private boolean shouldAllowDisableKeyguard()
Jim Millerd6b57052010-06-07 17:52:42 -07004242 {
Jim Miller284b62e2010-06-08 14:27:42 -07004243 // We fail safe and prevent disabling keyguard in the unlikely event this gets
4244 // called before DevicePolicyManagerService has started.
4245 if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
4246 DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
4247 Context.DEVICE_POLICY_SERVICE);
4248 if (dpm != null) {
4249 mAllowDisableKeyguard = dpm.getPasswordQuality(null)
4250 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
4251 ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
4252 }
Jim Millerd6b57052010-06-07 17:52:42 -07004253 }
Jim Miller284b62e2010-06-08 14:27:42 -07004254 return mAllowDisableKeyguard == ALLOW_DISABLE_YES;
Jim Millerd6b57052010-06-07 17:52:42 -07004255 }
4256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004257 public void disableKeyguard(IBinder token, String tag) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004258 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004259 != PackageManager.PERMISSION_GRANTED) {
4260 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4261 }
Jim Millerd6b57052010-06-07 17:52:42 -07004262
Jim Miller284b62e2010-06-08 14:27:42 -07004263 synchronized (mKeyguardTokenWatcher) {
4264 mKeyguardTokenWatcher.acquire(token, tag);
Mike Lockwooddd884682009-10-11 16:57:08 -04004265 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004266 }
4267
4268 public void reenableKeyguard(IBinder token) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004269 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004270 != PackageManager.PERMISSION_GRANTED) {
4271 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4272 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004273
Jim Miller284b62e2010-06-08 14:27:42 -07004274 synchronized (mKeyguardTokenWatcher) {
4275 mKeyguardTokenWatcher.release(token);
Jim Millerd6b57052010-06-07 17:52:42 -07004276
Jim Miller284b62e2010-06-08 14:27:42 -07004277 if (!mKeyguardTokenWatcher.isAcquired()) {
4278 // If we are the last one to reenable the keyguard wait until
4279 // we have actually finished reenabling until returning.
4280 // It is possible that reenableKeyguard() can be called before
4281 // the previous disableKeyguard() is handled, in which case
4282 // neither mKeyguardTokenWatcher.acquired() or released() would
4283 // be called. In that case mKeyguardDisabled will be false here
4284 // and we have nothing to wait for.
4285 while (mKeyguardDisabled) {
4286 try {
4287 mKeyguardTokenWatcher.wait();
4288 } catch (InterruptedException e) {
4289 Thread.currentThread().interrupt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004290 }
4291 }
4292 }
4293 }
4294 }
4295
4296 /**
4297 * @see android.app.KeyguardManager#exitKeyguardSecurely
4298 */
4299 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004300 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004301 != PackageManager.PERMISSION_GRANTED) {
4302 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4303 }
4304 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
4305 public void onKeyguardExitResult(boolean success) {
4306 try {
4307 callback.onKeyguardExitResult(success);
4308 } catch (RemoteException e) {
4309 // Client has died, we don't care.
4310 }
4311 }
4312 });
4313 }
4314
4315 public boolean inKeyguardRestrictedInputMode() {
4316 return mPolicy.inKeyguardRestrictedKeyInputMode();
4317 }
Romain Guy06882f82009-06-10 13:36:04 -07004318
Dianne Hackbornffa42482009-09-23 22:20:11 -07004319 public void closeSystemDialogs(String reason) {
4320 synchronized(mWindowMap) {
4321 for (int i=mWindows.size()-1; i>=0; i--) {
4322 WindowState w = (WindowState)mWindows.get(i);
4323 if (w.mSurface != null) {
4324 try {
4325 w.mClient.closeSystemDialogs(reason);
4326 } catch (RemoteException e) {
4327 }
4328 }
4329 }
4330 }
4331 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004333 static float fixScale(float scale) {
4334 if (scale < 0) scale = 0;
4335 else if (scale > 20) scale = 20;
4336 return Math.abs(scale);
4337 }
Romain Guy06882f82009-06-10 13:36:04 -07004338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 public void setAnimationScale(int which, float scale) {
4340 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4341 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004342 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004343 }
4344
4345 if (scale < 0) scale = 0;
4346 else if (scale > 20) scale = 20;
4347 scale = Math.abs(scale);
4348 switch (which) {
4349 case 0: mWindowAnimationScale = fixScale(scale); break;
4350 case 1: mTransitionAnimationScale = fixScale(scale); break;
4351 }
Romain Guy06882f82009-06-10 13:36:04 -07004352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004353 // Persist setting
4354 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4355 }
Romain Guy06882f82009-06-10 13:36:04 -07004356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004357 public void setAnimationScales(float[] scales) {
4358 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4359 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004360 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004361 }
4362
4363 if (scales != null) {
4364 if (scales.length >= 1) {
4365 mWindowAnimationScale = fixScale(scales[0]);
4366 }
4367 if (scales.length >= 2) {
4368 mTransitionAnimationScale = fixScale(scales[1]);
4369 }
4370 }
Romain Guy06882f82009-06-10 13:36:04 -07004371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 // Persist setting
4373 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4374 }
Romain Guy06882f82009-06-10 13:36:04 -07004375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 public float getAnimationScale(int which) {
4377 switch (which) {
4378 case 0: return mWindowAnimationScale;
4379 case 1: return mTransitionAnimationScale;
4380 }
4381 return 0;
4382 }
Romain Guy06882f82009-06-10 13:36:04 -07004383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004384 public float[] getAnimationScales() {
4385 return new float[] { mWindowAnimationScale, mTransitionAnimationScale };
4386 }
Romain Guy06882f82009-06-10 13:36:04 -07004387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004388 public int getSwitchState(int sw) {
4389 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4390 "getSwitchState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004391 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004392 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004393 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4394 return mInputManager.getSwitchState(sw);
4395 } else {
4396 return KeyInputQueue.getSwitchState(sw);
4397 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004398 }
Romain Guy06882f82009-06-10 13:36:04 -07004399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400 public int getSwitchStateForDevice(int devid, int sw) {
4401 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4402 "getSwitchStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004403 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004404 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004405 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4406 return mInputManager.getSwitchState(devid, sw);
4407 } else {
4408 return KeyInputQueue.getSwitchState(devid, sw);
4409 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004410 }
Romain Guy06882f82009-06-10 13:36:04 -07004411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 public int getScancodeState(int sw) {
4413 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4414 "getScancodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004415 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004416 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004417 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4418 return mInputManager.getScancodeState(sw);
4419 } else {
4420 return mQueue.getScancodeState(sw);
4421 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004422 }
Romain Guy06882f82009-06-10 13:36:04 -07004423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004424 public int getScancodeStateForDevice(int devid, int sw) {
4425 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4426 "getScancodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004427 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004428 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004429 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4430 return mInputManager.getScancodeState(devid, sw);
4431 } else {
4432 return mQueue.getScancodeState(devid, sw);
4433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004434 }
Romain Guy06882f82009-06-10 13:36:04 -07004435
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004436 public int getTrackballScancodeState(int sw) {
4437 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4438 "getTrackballScancodeState()")) {
4439 throw new SecurityException("Requires READ_INPUT_STATE permission");
4440 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004441 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4442 return mInputManager.getTrackballScancodeState(sw);
4443 } else {
4444 return mQueue.getTrackballScancodeState(sw);
4445 }
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004446 }
4447
4448 public int getDPadScancodeState(int sw) {
4449 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4450 "getDPadScancodeState()")) {
4451 throw new SecurityException("Requires READ_INPUT_STATE permission");
4452 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004453 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4454 return mInputManager.getDPadScancodeState(sw);
4455 } else {
4456 return mQueue.getDPadScancodeState(sw);
4457 }
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004458 }
4459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004460 public int getKeycodeState(int sw) {
4461 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4462 "getKeycodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004463 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004464 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004465 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4466 return mInputManager.getKeycodeState(sw);
4467 } else {
4468 return mQueue.getKeycodeState(sw);
4469 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004470 }
Romain Guy06882f82009-06-10 13:36:04 -07004471
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004472 public int getKeycodeStateForDevice(int devid, int sw) {
4473 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4474 "getKeycodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004475 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004476 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004477 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4478 return mInputManager.getKeycodeState(devid, sw);
4479 } else {
4480 return mQueue.getKeycodeState(devid, sw);
4481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 }
Romain Guy06882f82009-06-10 13:36:04 -07004483
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004484 public int getTrackballKeycodeState(int sw) {
4485 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4486 "getTrackballKeycodeState()")) {
4487 throw new SecurityException("Requires READ_INPUT_STATE permission");
4488 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004489 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4490 return mInputManager.getTrackballKeycodeState(sw);
4491 } else {
4492 return mQueue.getTrackballKeycodeState(sw);
4493 }
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004494 }
4495
4496 public int getDPadKeycodeState(int sw) {
4497 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4498 "getDPadKeycodeState()")) {
4499 throw new SecurityException("Requires READ_INPUT_STATE permission");
4500 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004501 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4502 return mInputManager.getDPadKeycodeState(sw);
4503 } else {
4504 return mQueue.getDPadKeycodeState(sw);
4505 }
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004506 }
4507
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004508 public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004509 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4510 return mInputManager.hasKeys(keycodes, keyExists);
4511 } else {
4512 return KeyInputQueue.hasKeys(keycodes, keyExists);
4513 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004514 }
Romain Guy06882f82009-06-10 13:36:04 -07004515
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 public void enableScreenAfterBoot() {
4517 synchronized(mWindowMap) {
4518 if (mSystemBooted) {
4519 return;
4520 }
4521 mSystemBooted = true;
4522 }
Romain Guy06882f82009-06-10 13:36:04 -07004523
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 performEnableScreen();
4525 }
Romain Guy06882f82009-06-10 13:36:04 -07004526
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004527 public void enableScreenIfNeededLocked() {
4528 if (mDisplayEnabled) {
4529 return;
4530 }
4531 if (!mSystemBooted) {
4532 return;
4533 }
4534 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
4535 }
Romain Guy06882f82009-06-10 13:36:04 -07004536
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004537 public void performEnableScreen() {
4538 synchronized(mWindowMap) {
4539 if (mDisplayEnabled) {
4540 return;
4541 }
4542 if (!mSystemBooted) {
4543 return;
4544 }
Romain Guy06882f82009-06-10 13:36:04 -07004545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004546 // Don't enable the screen until all existing windows
4547 // have been drawn.
4548 final int N = mWindows.size();
4549 for (int i=0; i<N; i++) {
4550 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -08004551 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004552 return;
4553 }
4554 }
Romain Guy06882f82009-06-10 13:36:04 -07004555
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 mDisplayEnabled = true;
4557 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004558 Slog.i(TAG, "ENABLING SCREEN!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 StringWriter sw = new StringWriter();
4560 PrintWriter pw = new PrintWriter(sw);
4561 this.dump(null, pw, null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004562 Slog.i(TAG, sw.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004563 }
4564 try {
4565 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
4566 if (surfaceFlinger != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004567 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004568 Parcel data = Parcel.obtain();
4569 data.writeInterfaceToken("android.ui.ISurfaceComposer");
4570 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
4571 data, null, 0);
4572 data.recycle();
4573 }
4574 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004575 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 }
4577 }
Romain Guy06882f82009-06-10 13:36:04 -07004578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 mPolicy.enableScreenAfterBoot();
Romain Guy06882f82009-06-10 13:36:04 -07004580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 // Make sure the last requested orientation has been applied.
Dianne Hackborn321ae682009-03-27 16:16:03 -07004582 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
4583 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004584 }
Romain Guy06882f82009-06-10 13:36:04 -07004585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004586 public void setInTouchMode(boolean mode) {
4587 synchronized(mWindowMap) {
4588 mInTouchMode = mode;
4589 }
4590 }
4591
Romain Guy06882f82009-06-10 13:36:04 -07004592 public void setRotation(int rotation,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004593 boolean alwaysSendConfiguration, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004595 "setRotation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004596 throw new SecurityException("Requires SET_ORIENTATION permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 }
4598
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004599 setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004600 }
Romain Guy06882f82009-06-10 13:36:04 -07004601
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004602 public void setRotationUnchecked(int rotation,
4603 boolean alwaysSendConfiguration, int animFlags) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004604 if(DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004605 "alwaysSendConfiguration set to "+alwaysSendConfiguration);
Romain Guy06882f82009-06-10 13:36:04 -07004606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004607 long origId = Binder.clearCallingIdentity();
4608 boolean changed;
4609 synchronized(mWindowMap) {
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004610 changed = setRotationUncheckedLocked(rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004611 }
Romain Guy06882f82009-06-10 13:36:04 -07004612
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004613 if (changed || alwaysSendConfiguration) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614 sendNewConfiguration();
4615 }
Romain Guy06882f82009-06-10 13:36:04 -07004616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004617 Binder.restoreCallingIdentity(origId);
4618 }
Romain Guy06882f82009-06-10 13:36:04 -07004619
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004620 /**
4621 * Apply a new rotation to the screen, respecting the requests of
4622 * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply
4623 * re-evaluate the desired rotation.
4624 *
4625 * Returns null if the rotation has been changed. In this case YOU
4626 * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
4627 */
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004628 public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 boolean changed;
4630 if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
4631 rotation = mRequestedRotation;
4632 } else {
4633 mRequestedRotation = rotation;
Dianne Hackborn321ae682009-03-27 16:16:03 -07004634 mLastRotationFlags = animFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004635 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004636 if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation);
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07004637 rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004638 mRotation, mDisplayEnabled);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004639 if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004640 changed = mDisplayEnabled && mRotation != rotation;
Romain Guy06882f82009-06-10 13:36:04 -07004641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004642 if (changed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004643 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004644 "Rotation changed to " + rotation
4645 + " from " + mRotation
4646 + " (forceApp=" + mForcedAppOrientation
4647 + ", req=" + mRequestedRotation + ")");
4648 mRotation = rotation;
4649 mWindowsFreezingScreen = true;
4650 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
4651 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
4652 2000);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004653 mWaitingForConfig = true;
4654 mLayoutNeeded = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004655 startFreezingDisplayLocked();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004656 Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004657 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4658 mInputManager.setDisplayOrientation(0, rotation);
4659 } else {
4660 mQueue.setOrientation(rotation);
4661 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004662 if (mDisplayEnabled) {
Dianne Hackborn321ae682009-03-27 16:16:03 -07004663 Surface.setOrientation(0, rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004664 }
4665 for (int i=mWindows.size()-1; i>=0; i--) {
4666 WindowState w = (WindowState)mWindows.get(i);
4667 if (w.mSurface != null) {
4668 w.mOrientationChanging = true;
4669 }
4670 }
4671 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
4672 try {
4673 mRotationWatchers.get(i).onRotationChanged(rotation);
4674 } catch (RemoteException e) {
4675 }
4676 }
4677 } //end if changed
Romain Guy06882f82009-06-10 13:36:04 -07004678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 return changed;
4680 }
Romain Guy06882f82009-06-10 13:36:04 -07004681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004682 public int getRotation() {
4683 return mRotation;
4684 }
4685
4686 public int watchRotation(IRotationWatcher watcher) {
4687 final IBinder watcherBinder = watcher.asBinder();
4688 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4689 public void binderDied() {
4690 synchronized (mWindowMap) {
4691 for (int i=0; i<mRotationWatchers.size(); i++) {
4692 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004693 IRotationWatcher removed = mRotationWatchers.remove(i);
4694 if (removed != null) {
4695 removed.asBinder().unlinkToDeath(this, 0);
4696 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004697 i--;
4698 }
4699 }
4700 }
4701 }
4702 };
Romain Guy06882f82009-06-10 13:36:04 -07004703
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004704 synchronized (mWindowMap) {
4705 try {
4706 watcher.asBinder().linkToDeath(dr, 0);
4707 mRotationWatchers.add(watcher);
4708 } catch (RemoteException e) {
4709 // Client died, no cleanup needed.
4710 }
Romain Guy06882f82009-06-10 13:36:04 -07004711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004712 return mRotation;
4713 }
4714 }
4715
4716 /**
4717 * Starts the view server on the specified port.
4718 *
4719 * @param port The port to listener to.
4720 *
4721 * @return True if the server was successfully started, false otherwise.
4722 *
4723 * @see com.android.server.ViewServer
4724 * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT
4725 */
4726 public boolean startViewServer(int port) {
Romain Guy06882f82009-06-10 13:36:04 -07004727 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004728 return false;
4729 }
4730
4731 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4732 return false;
4733 }
4734
4735 if (port < 1024) {
4736 return false;
4737 }
4738
4739 if (mViewServer != null) {
4740 if (!mViewServer.isRunning()) {
4741 try {
4742 return mViewServer.start();
4743 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004744 Slog.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004745 }
4746 }
4747 return false;
4748 }
4749
4750 try {
4751 mViewServer = new ViewServer(this, port);
4752 return mViewServer.start();
4753 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004754 Slog.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004755 }
4756 return false;
4757 }
4758
Romain Guy06882f82009-06-10 13:36:04 -07004759 private boolean isSystemSecure() {
4760 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4761 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4762 }
4763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004764 /**
4765 * Stops the view server if it exists.
4766 *
4767 * @return True if the server stopped, false if it wasn't started or
4768 * couldn't be stopped.
4769 *
4770 * @see com.android.server.ViewServer
4771 */
4772 public boolean stopViewServer() {
Romain Guy06882f82009-06-10 13:36:04 -07004773 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004774 return false;
4775 }
4776
4777 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4778 return false;
4779 }
4780
4781 if (mViewServer != null) {
4782 return mViewServer.stop();
4783 }
4784 return false;
4785 }
4786
4787 /**
4788 * Indicates whether the view server is running.
4789 *
4790 * @return True if the server is running, false otherwise.
4791 *
4792 * @see com.android.server.ViewServer
4793 */
4794 public boolean isViewServerRunning() {
Romain Guy06882f82009-06-10 13:36:04 -07004795 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004796 return false;
4797 }
4798
4799 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4800 return false;
4801 }
4802
4803 return mViewServer != null && mViewServer.isRunning();
4804 }
4805
4806 /**
4807 * Lists all availble windows in the system. The listing is written in the
4808 * specified Socket's output stream with the following syntax:
4809 * windowHashCodeInHexadecimal windowName
4810 * Each line of the ouput represents a different window.
4811 *
4812 * @param client The remote client to send the listing to.
4813 * @return False if an error occured, true otherwise.
4814 */
4815 boolean viewServerListWindows(Socket client) {
Romain Guy06882f82009-06-10 13:36:04 -07004816 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004817 return false;
4818 }
4819
4820 boolean result = true;
4821
4822 Object[] windows;
4823 synchronized (mWindowMap) {
4824 windows = new Object[mWindows.size()];
4825 //noinspection unchecked
4826 windows = mWindows.toArray(windows);
4827 }
4828
4829 BufferedWriter out = null;
4830
4831 // Any uncaught exception will crash the system process
4832 try {
4833 OutputStream clientStream = client.getOutputStream();
4834 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4835
4836 final int count = windows.length;
4837 for (int i = 0; i < count; i++) {
4838 final WindowState w = (WindowState) windows[i];
4839 out.write(Integer.toHexString(System.identityHashCode(w)));
4840 out.write(' ');
4841 out.append(w.mAttrs.getTitle());
4842 out.write('\n');
4843 }
4844
4845 out.write("DONE.\n");
4846 out.flush();
4847 } catch (Exception e) {
4848 result = false;
4849 } finally {
4850 if (out != null) {
4851 try {
4852 out.close();
4853 } catch (IOException e) {
4854 result = false;
4855 }
4856 }
4857 }
4858
4859 return result;
4860 }
4861
4862 /**
4863 * Sends a command to a target window. The result of the command, if any, will be
4864 * written in the output stream of the specified socket.
4865 *
4866 * The parameters must follow this syntax:
4867 * windowHashcode extra
4868 *
4869 * Where XX is the length in characeters of the windowTitle.
4870 *
4871 * The first parameter is the target window. The window with the specified hashcode
4872 * will be the target. If no target can be found, nothing happens. The extra parameters
4873 * will be delivered to the target window and as parameters to the command itself.
4874 *
4875 * @param client The remote client to sent the result, if any, to.
4876 * @param command The command to execute.
4877 * @param parameters The command parameters.
4878 *
4879 * @return True if the command was successfully delivered, false otherwise. This does
4880 * not indicate whether the command itself was successful.
4881 */
4882 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
Romain Guy06882f82009-06-10 13:36:04 -07004883 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004884 return false;
4885 }
4886
4887 boolean success = true;
4888 Parcel data = null;
4889 Parcel reply = null;
4890
4891 // Any uncaught exception will crash the system process
4892 try {
4893 // Find the hashcode of the window
4894 int index = parameters.indexOf(' ');
4895 if (index == -1) {
4896 index = parameters.length();
4897 }
4898 final String code = parameters.substring(0, index);
Romain Guy236092a2009-12-14 15:31:48 -08004899 int hashCode = (int) Long.parseLong(code, 16);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004900
4901 // Extract the command's parameter after the window description
4902 if (index < parameters.length()) {
4903 parameters = parameters.substring(index + 1);
4904 } else {
4905 parameters = "";
4906 }
4907
4908 final WindowManagerService.WindowState window = findWindow(hashCode);
4909 if (window == null) {
4910 return false;
4911 }
4912
4913 data = Parcel.obtain();
4914 data.writeInterfaceToken("android.view.IWindow");
4915 data.writeString(command);
4916 data.writeString(parameters);
4917 data.writeInt(1);
4918 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4919
4920 reply = Parcel.obtain();
4921
4922 final IBinder binder = window.mClient.asBinder();
4923 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4924 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4925
4926 reply.readException();
4927
4928 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004929 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004930 success = false;
4931 } finally {
4932 if (data != null) {
4933 data.recycle();
4934 }
4935 if (reply != null) {
4936 reply.recycle();
4937 }
4938 }
4939
4940 return success;
4941 }
4942
4943 private WindowState findWindow(int hashCode) {
4944 if (hashCode == -1) {
4945 return getFocusedWindow();
4946 }
4947
4948 synchronized (mWindowMap) {
4949 final ArrayList windows = mWindows;
4950 final int count = windows.size();
4951
4952 for (int i = 0; i < count; i++) {
4953 WindowState w = (WindowState) windows.get(i);
4954 if (System.identityHashCode(w) == hashCode) {
4955 return w;
4956 }
4957 }
4958 }
4959
4960 return null;
4961 }
4962
4963 /*
4964 * Instruct the Activity Manager to fetch the current configuration and broadcast
4965 * that to config-changed listeners if appropriate.
4966 */
4967 void sendNewConfiguration() {
4968 try {
4969 mActivityManager.updateConfiguration(null);
4970 } catch (RemoteException e) {
4971 }
4972 }
Romain Guy06882f82009-06-10 13:36:04 -07004973
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004974 public Configuration computeNewConfiguration() {
4975 synchronized (mWindowMap) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07004976 return computeNewConfigurationLocked();
4977 }
4978 }
Romain Guy06882f82009-06-10 13:36:04 -07004979
Dianne Hackbornc485a602009-03-24 22:39:49 -07004980 Configuration computeNewConfigurationLocked() {
4981 Configuration config = new Configuration();
4982 if (!computeNewConfigurationLocked(config)) {
4983 return null;
4984 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07004985 return config;
4986 }
Romain Guy06882f82009-06-10 13:36:04 -07004987
Dianne Hackbornc485a602009-03-24 22:39:49 -07004988 boolean computeNewConfigurationLocked(Configuration config) {
4989 if (mDisplay == null) {
4990 return false;
4991 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004992 if (ENABLE_NATIVE_INPUT_DISPATCH) {
4993 mInputManager.getInputConfiguration(config);
4994 } else {
4995 mQueue.getInputConfiguration(config);
4996 }
Christopher Tateb696aee2010-04-02 19:08:30 -07004997
4998 // Use the effective "visual" dimensions based on current rotation
4999 final boolean rotated = (mRotation == Surface.ROTATION_90
5000 || mRotation == Surface.ROTATION_270);
5001 final int dw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth;
5002 final int dh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight;
5003
Dianne Hackbornc485a602009-03-24 22:39:49 -07005004 int orientation = Configuration.ORIENTATION_SQUARE;
5005 if (dw < dh) {
5006 orientation = Configuration.ORIENTATION_PORTRAIT;
5007 } else if (dw > dh) {
5008 orientation = Configuration.ORIENTATION_LANDSCAPE;
5009 }
5010 config.orientation = orientation;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005011
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07005012 DisplayMetrics dm = new DisplayMetrics();
5013 mDisplay.getMetrics(dm);
5014 CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
5015
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005016 if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07005017 // Note we only do this once because at this point we don't
5018 // expect the screen to change in this way at runtime, and want
5019 // to avoid all of this computation for every config change.
Dianne Hackborn723738c2009-06-25 19:48:04 -07005020 int longSize = dw;
5021 int shortSize = dh;
5022 if (longSize < shortSize) {
5023 int tmp = longSize;
5024 longSize = shortSize;
5025 shortSize = tmp;
5026 }
5027 longSize = (int)(longSize/dm.density);
5028 shortSize = (int)(shortSize/dm.density);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07005029
Dianne Hackborn723738c2009-06-25 19:48:04 -07005030 // These semi-magic numbers define our compatibility modes for
5031 // applications with different screens. Don't change unless you
5032 // make sure to test lots and lots of apps!
5033 if (longSize < 470) {
5034 // This is shorter than an HVGA normal density screen (which
5035 // is 480 pixels on its long side).
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005036 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
5037 | Configuration.SCREENLAYOUT_LONG_NO;
Dianne Hackborn723738c2009-06-25 19:48:04 -07005038 } else {
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07005039 // What size is this screen screen?
5040 if (longSize >= 800 && shortSize >= 600) {
5041 // SVGA or larger screens at medium density are the point
5042 // at which we consider it to be an extra large screen.
5043 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE;
5044 } else if (longSize >= 640 && shortSize >= 480) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005045 // VGA or larger screens at medium density are the point
5046 // at which we consider it to be a large screen.
5047 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
5048 } else {
5049 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005050
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005051 // If this screen is wider than normal HVGA, or taller
5052 // than FWVGA, then for old apps we want to run in size
5053 // compatibility mode.
5054 if (shortSize > 321 || longSize > 570) {
5055 mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
5056 }
5057 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005058
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005059 // Is this a long screen?
5060 if (((longSize*3)/5) >= (shortSize-1)) {
5061 // Anything wider than WVGA (5:3) is considering to be long.
5062 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
5063 } else {
5064 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
5065 }
Dianne Hackborn723738c2009-06-25 19:48:04 -07005066 }
5067 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07005068 config.screenLayout = mScreenLayout;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005069
Dianne Hackbornc485a602009-03-24 22:39:49 -07005070 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
5071 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
5072 mPolicy.adjustConfigurationLw(config);
5073 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005074 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07005075
5076 /* Notifies the window manager about a broken input channel.
5077 *
5078 * Called by the InputManager.
5079 */
5080 public void notifyInputChannelBroken(InputChannel inputChannel) {
5081 synchronized (mWindowMap) {
5082 WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
5083 if (windowState == null) {
5084 return; // irrelevant
5085 }
5086
5087 Slog.i(TAG, "WINDOW DIED " + windowState);
5088 removeWindowLocked(windowState.mSession, windowState);
5089 }
5090 }
5091
5092 /* Notifies the window manager about a broken input channel.
5093 *
5094 * Called by the InputManager.
5095 */
5096 public long notifyInputChannelANR(InputChannel inputChannel) {
5097 IApplicationToken appToken;
5098 synchronized (mWindowMap) {
5099 WindowState windowState = getWindowStateForInputChannelLocked(inputChannel);
5100 if (windowState == null) {
5101 return -2; // irrelevant, abort dispatching (-2)
5102 }
5103
5104 Slog.i(TAG, "Input event dispatching timed out sending to "
5105 + windowState.mAttrs.getTitle());
5106 appToken = windowState.getAppToken();
5107 }
5108
5109 try {
5110 // Notify the activity manager about the timeout and let it decide whether
5111 // to abort dispatching or keep waiting.
5112 boolean abort = appToken.keyDispatchingTimedOut();
5113 if (abort) {
5114 return -2; // abort dispatching
5115 }
5116
5117 // Return new timeout.
5118 // We use -1 for infinite timeout to avoid clash with -2 magic number.
5119 long newTimeout = appToken.getKeyDispatchingTimeout() * 1000000;
5120 return newTimeout < 0 ? -1 : newTimeout;
5121 } catch (RemoteException ex) {
5122 return -2; // abort dispatching
5123 }
5124 }
5125
5126 /* Notifies the window manager about a broken input channel.
5127 *
5128 * Called by the InputManager.
5129 */
5130 public void notifyInputChannelRecoveredFromANR(InputChannel inputChannel) {
5131 // Nothing to do just now.
5132 // Just wait for the user to dismiss the ANR dialog.
5133
5134 // TODO We could try to automatically dismiss the ANR dialog on recovery
5135 // although that might be disorienting.
5136 }
5137
5138 private WindowState getWindowStateForInputChannelLocked(InputChannel inputChannel) {
5139 int windowCount = mWindows.size();
5140 for (int i = 0; i < windowCount; i++) {
5141 WindowState windowState = (WindowState) mWindows.get(i);
5142 if (windowState.mInputChannel == inputChannel) {
5143 return windowState;
5144 }
5145 }
5146
5147 return null;
5148 }
Romain Guy06882f82009-06-10 13:36:04 -07005149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005150 // -------------------------------------------------------------
5151 // Input Events and Focus Management
5152 // -------------------------------------------------------------
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005153
Jeff Brown7fbdc842010-06-17 20:52:56 -07005154 private boolean checkInjectionPermissionTd(WindowState focus,
5155 int injectorPid, int injectorUid) {
5156 if (injectorUid > 0 && (focus == null || injectorUid != focus.mSession.mUid)) {
5157 if (mContext.checkPermission(
5158 android.Manifest.permission.INJECT_EVENTS, injectorPid, injectorUid)
5159 != PackageManager.PERMISSION_GRANTED) {
5160 Slog.w(TAG, "Permission denied: injecting key event from pid "
5161 + injectorPid + " uid " + injectorUid + " to window " + focus
5162 + " owned by uid " + focus.mSession.mUid);
5163 return false;
5164 }
5165 }
5166 return true;
5167 }
5168
5169 /* Gets the input targets for a key event.
5170 *
5171 * Called by the InputManager on the InputDispatcher thread.
5172 */
5173 public int getKeyEventTargetsTd(InputTargetList inputTargets,
5174 KeyEvent event, int nature, int policyFlags, int injectorPid, int injectorUid) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005175 if (DEBUG_INPUT) Slog.v(TAG, "Dispatch key: " + event);
5176
5177 // TODO what do we do with mDisplayFrozen?
5178 // TODO what do we do with focus.mToken.paused?
5179
5180 WindowState focus = getFocusedWindow();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005181
Jeff Brown7fbdc842010-06-17 20:52:56 -07005182 if (! checkInjectionPermissionTd(focus, injectorPid, injectorUid)) {
5183 return InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005184 }
5185
Jeff Brown7fbdc842010-06-17 20:52:56 -07005186 if (mPolicy.interceptKeyTi(focus, event.getKeyCode(), event.getMetaState(),
5187 event.getAction() == KeyEvent.ACTION_DOWN,
5188 event.getRepeatCount(), event.getFlags())) {
5189 // Policy consumed the event.
5190 return InputManager.INPUT_EVENT_INJECTION_SUCCEEDED;
5191 }
5192
5193 if (focus == null) {
5194 return InputManager.INPUT_EVENT_INJECTION_FAILED;
5195 }
5196
5197 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
5198
5199 addInputTargetTd(inputTargets, focus, InputTarget.FLAG_SYNC);
5200 return InputManager.INPUT_EVENT_INJECTION_SUCCEEDED;
5201 }
5202
5203 /* Gets the input targets for a motion event.
5204 *
5205 * Called by the InputManager on the InputDispatcher thread.
5206 */
5207 public int getMotionEventTargetsTd(InputTargetList inputTargets,
5208 MotionEvent event, int nature, int policyFlags, int injectorPid, int injectorUid) {
5209 switch (nature) {
5210 case InputQueue.INPUT_EVENT_NATURE_TRACKBALL:
5211 return getMotionEventTargetsForTrackballTd(inputTargets, event, policyFlags,
5212 injectorPid, injectorUid);
5213
5214 case InputQueue.INPUT_EVENT_NATURE_TOUCH:
5215 return getMotionEventTargetsForTouchTd(inputTargets, event, policyFlags,
5216 injectorPid, injectorUid);
5217
5218 default:
5219 return InputManager.INPUT_EVENT_INJECTION_FAILED;
5220 }
5221 }
5222
5223 /* Gets the input targets for a trackball event.
5224 *
5225 * Called by the InputManager on the InputDispatcher thread.
5226 */
5227 private int getMotionEventTargetsForTrackballTd(InputTargetList inputTargets,
5228 MotionEvent event, int policyFlags, int injectorPid, int injectorUid) {
5229 WindowState focus = getFocusedWindow();
5230
5231 if (! checkInjectionPermissionTd(focus, injectorPid, injectorUid)) {
5232 return InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED;
5233 }
5234
5235 if (focus == null) {
5236 return InputManager.INPUT_EVENT_INJECTION_FAILED;
5237 }
5238
5239 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
5240
5241 addInputTargetTd(inputTargets, focus, InputTarget.FLAG_SYNC);
5242 return InputManager.INPUT_EVENT_INJECTION_SUCCEEDED;
5243 }
5244
5245 /* Set to true when a fat touch has been detected during the processing of a touch event.
5246 *
5247 * Only used by getMotionEventTargetsForTouchTd.
5248 * Set to true whenever a fat touch is detected and reset to false on ACTION_UP.
5249 */
5250 private boolean mFatTouch;
5251
5252 /* Set to true when we think the touch event.
5253 *
5254 * Only used by getMotionEventTargetsForTouchTd.
5255 * Set to true on ACTION_DOWN and set to false on ACTION_UP.
5256 */
5257 private boolean mTouchDown;
5258
5259 /* Current target of Motion events.
5260 *
5261 * Only used by getMotionEventTargetsForTouchTd.
5262 * Initialized on ACTION_DOWN and cleared on ACTION_UP.
5263 */
5264 private WindowState mTouchFocus;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005265
Jeff Brown7fbdc842010-06-17 20:52:56 -07005266 /* Windows above the target that would like to receive an "outside" touch event
5267 * for any down events outside of them.
5268 *
5269 * Only used by getMotionEventTargetsForTouchTd.
5270 * Initialized on ACTION_DOWN and cleared immediately afterwards.
5271 */
5272 private ArrayList<WindowState> mOutsideTouchTargets = new ArrayList<WindowState>();
5273
5274 /* Wallpaper windows that are currently receiving touch events.
5275 *
5276 * Only used by getMotionEventTargetsForTouchTd.
5277 * Initialized on ACTION_DOWN and cleared on ACTION_UP.
5278 */
5279 private ArrayList<WindowState> mWallpaperTouchTargets = new ArrayList<WindowState>();
5280
5281 /* Gets the input targets for a touch event.
5282 *
5283 * Called by the InputManager on the InputDispatcher thread.
5284 */
5285 private int getMotionEventTargetsForTouchTd(InputTargetList inputTargets,
5286 MotionEvent event, int policyFlags, int injectorPid, int injectorUid) {
5287 final int action = event.getAction();
5288
5289 if (action == MotionEvent.ACTION_DOWN) {
5290 updateTouchFocusBeforeDownTd(event, policyFlags);
5291 } else {
5292 updateTouchFocusBeforeNonDownTd(event, policyFlags);
5293 }
5294
5295 boolean skipDelivery = false;
5296 int touchTargetFlags = 0;
5297
5298 int injectionResult = InputManager.INPUT_EVENT_INJECTION_SUCCEEDED;
5299 WindowState focusedTouchTarget = mTouchFocus;
5300 if (focusedTouchTarget == null) {
5301 // In this case we are either dropping the event, or have received
5302 // a move or up without a down. It is common to receive move
5303 // events in such a way, since this means the user is moving the
5304 // pointer without actually pressing down. All other cases should
5305 // be atypical, so let's log them.
5306 if (action != MotionEvent.ACTION_MOVE) {
5307 Slog.w(TAG, "No window to dispatch pointer action " + action);
5308 injectionResult = InputManager.INPUT_EVENT_INJECTION_FAILED;
5309 }
5310 } else {
5311 // We have a valid focused touch target.
5312 if (! checkInjectionPermissionTd(focusedTouchTarget, injectorPid, injectorUid)) {
5313 return InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED;
5314 }
5315
5316 wakeupIfNeeded(focusedTouchTarget, eventType(event));
5317
5318 if ((focusedTouchTarget.mAttrs.flags &
5319 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
5320 // Target wants to ignore fat touch events
5321 boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(event);
5322
5323 if (cheekPress) {
5324 if ((action == MotionEvent.ACTION_DOWN)) {
5325 mFatTouch = true;
5326 skipDelivery = true;
5327 } else {
5328 if (! mFatTouch) {
5329 // cancel the earlier event
5330 touchTargetFlags |= InputTarget.FLAG_CANCEL;
5331 mFatTouch = true;
5332 } else {
5333 skipDelivery = true;
5334 }
5335 }
5336 }
5337 }
5338 }
5339
5340 if (! skipDelivery) {
5341 int outsideTargetCount = mOutsideTouchTargets.size();
5342 for (int i = 0; i < outsideTargetCount; i++) {
5343 WindowState outsideTouchTarget = mOutsideTouchTargets.get(i);
5344 addInputTargetTd(inputTargets, outsideTouchTarget,
5345 InputTarget.FLAG_OUTSIDE | touchTargetFlags);
5346 }
5347
5348 int wallpaperTargetCount = mWallpaperTouchTargets.size();
5349 for (int i = 0; i < wallpaperTargetCount; i++) {
5350 WindowState wallpaperTouchTarget = mWallpaperTouchTargets.get(i);
5351 addInputTargetTd(inputTargets, wallpaperTouchTarget,
5352 touchTargetFlags);
5353 }
5354
5355 if (focusedTouchTarget != null) {
5356 addInputTargetTd(inputTargets, focusedTouchTarget,
5357 InputTarget.FLAG_SYNC | touchTargetFlags);
5358 }
5359 }
5360
5361 if (action == MotionEvent.ACTION_UP) {
5362 updateTouchFocusAfterUpTd(event, policyFlags);
5363 }
5364
5365 return injectionResult;
5366 }
5367
5368 private void updateTouchFocusBeforeDownTd(MotionEvent event, int policyFlags) {
5369 if (mTouchDown) {
5370 // This is weird, we got a down, but we thought it was already down!
5371 // XXX: We should probably send an ACTION_UP to the current target.
5372 Slog.w(TAG, "Pointer down received while already down in: " + mTouchFocus);
5373 updateTouchFocusAfterUpTd(event, policyFlags);
5374 }
5375
5376 mTouchDown = true;
5377 mPowerManager.logPointerDownEvent();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005378
5379 final boolean screenWasOff = (policyFlags & WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
Jeff Brown7fbdc842010-06-17 20:52:56 -07005380 synchronized (mWindowMap) {
5381 final int x = (int) event.getX();
5382 final int y = (int) event.getY();
5383
5384 final ArrayList windows = mWindows;
5385 final int N = windows.size();
5386 WindowState topErrWindow = null;
5387 final Rect tmpRect = mTempRect;
5388 for (int i= N - 1; i >= 0; i--) {
5389 WindowState child = (WindowState) windows.get(i);
5390 //Slog.i(TAG, "Checking dispatch to: " + child);
5391
5392 final int flags = child.mAttrs.flags;
5393 if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
5394 if (topErrWindow == null) {
5395 topErrWindow = child;
5396 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005397 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07005398
5399 if (!child.isVisibleLw()) {
5400 //Slog.i(TAG, "Not visible!");
5401 continue;
5402 }
5403
5404 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) == 0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005405 tmpRect.set(child.mFrame);
5406 if (child.mTouchableInsets == ViewTreeObserver
5407 .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
5408 // The touch is inside of the window if it is
5409 // inside the frame, AND the content part of that
5410 // frame that was given by the application.
5411 tmpRect.left += child.mGivenContentInsets.left;
5412 tmpRect.top += child.mGivenContentInsets.top;
5413 tmpRect.right -= child.mGivenContentInsets.right;
5414 tmpRect.bottom -= child.mGivenContentInsets.bottom;
5415 } else if (child.mTouchableInsets == ViewTreeObserver
5416 .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
5417 // The touch is inside of the window if it is
5418 // inside the frame, AND the visible part of that
5419 // frame that was given by the application.
5420 tmpRect.left += child.mGivenVisibleInsets.left;
5421 tmpRect.top += child.mGivenVisibleInsets.top;
5422 tmpRect.right -= child.mGivenVisibleInsets.right;
5423 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
5424 }
5425 final int touchFlags = flags &
5426 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
5427 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
5428 if (tmpRect.contains(x, y) || touchFlags == 0) {
5429 //Slog.i(TAG, "Using this target!");
Jeff Brown7fbdc842010-06-17 20:52:56 -07005430 if (! screenWasOff || (flags &
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005431 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
5432 mTouchFocus = child;
5433 } else {
5434 //Slog.i(TAG, "Waking, skip!");
5435 mTouchFocus = null;
5436 }
5437 break;
5438 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005439 }
5440
Jeff Brown7fbdc842010-06-17 20:52:56 -07005441 if ((flags & WindowManager.LayoutParams
5442 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5443 //Slog.i(TAG, "Adding to outside target list: " + child);
5444 mOutsideTouchTargets.add(child);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005445 }
5446 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07005447
5448 // If there's an error window but it's not accepting focus (typically because
5449 // it is not yet visible) just wait for it -- any other focused window may in fact
5450 // be in ANR state.
5451 if (topErrWindow != null && mTouchFocus != topErrWindow) {
5452 mTouchFocus = null;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005453 }
5454
Jeff Brown7fbdc842010-06-17 20:52:56 -07005455 // Drop the touch focus if the window is not visible.
5456 if (mTouchFocus != null && ! mTouchFocus.isVisibleLw()) {
5457 mTouchFocus = null;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005458 }
5459
Jeff Brown7fbdc842010-06-17 20:52:56 -07005460 // Determine wallpaper targets.
5461 if (mTouchFocus != null
5462 && mTouchFocus == mWallpaperTarget
5463 && mTouchFocus.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005464 int curTokenIndex = mWallpaperTokens.size();
5465 while (curTokenIndex > 0) {
5466 curTokenIndex--;
5467 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Jeff Brown7fbdc842010-06-17 20:52:56 -07005468
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005469 int curWallpaperIndex = token.windows.size();
5470 while (curWallpaperIndex > 0) {
5471 curWallpaperIndex--;
5472 WindowState wallpaper = token.windows.get(curWallpaperIndex);
5473 if ((wallpaper.mAttrs.flags &
Jeff Brown7fbdc842010-06-17 20:52:56 -07005474 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) == 0) {
5475 mWallpaperTouchTargets.add(wallpaper);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005476 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005477 }
5478 }
5479 }
Jeff Brown7fbdc842010-06-17 20:52:56 -07005480 }
5481 }
5482
5483 private void updateTouchFocusBeforeNonDownTd(MotionEvent event, int policyFlags) {
5484 synchronized (mWindowMap) {
5485 // Drop the touch focus if the window is not visible.
5486 if (mTouchFocus != null && ! mTouchFocus.isVisibleLw()) {
5487 mTouchFocus = null;
5488 mWallpaperTouchTargets.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005489 }
5490 }
5491 }
5492
Jeff Brown7fbdc842010-06-17 20:52:56 -07005493 private void updateTouchFocusAfterUpTd(MotionEvent event, int policyFlags) {
5494 mFatTouch = false;
5495 mTouchDown = false;
5496 mTouchFocus = null;
5497 mOutsideTouchTargets.clear();
5498 mWallpaperTouchTargets.clear();
5499
5500 mPowerManager.logPointerUpEvent();
5501 }
5502
5503 /* Adds a window to a list of input targets.
5504 * Do NOT call this method while holding any locks because the call to
5505 * appToken.getKeyDispatchingTimeout() can potentially call into the ActivityManager
5506 * and create a deadlock hazard.
5507 */
5508 private void addInputTargetTd(InputTargetList inputTargets, WindowState window, int flags) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005509 if (window.mInputChannel == null) {
5510 return;
5511 }
5512
5513 long timeoutNanos = -1;
5514 IApplicationToken appToken = window.getAppToken();
5515
5516 if (appToken != null) {
5517 try {
5518 timeoutNanos = appToken.getKeyDispatchingTimeout() * 1000000;
5519 } catch (RemoteException ex) {
5520 Slog.w(TAG, "Could not get key dispatching timeout.", ex);
5521 }
5522 }
5523
5524 inputTargets.add(window.mInputChannel, flags, timeoutNanos,
5525 - window.mFrame.left, - window.mFrame.top);
5526 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527
5528 private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
Michael Chane96440f2009-05-06 10:27:36 -07005529 long curTime = SystemClock.uptimeMillis();
5530
Michael Chane10de972009-05-18 11:24:50 -07005531 if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
Michael Chane96440f2009-05-06 10:27:36 -07005532 if (mLastTouchEventType == eventType &&
5533 (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
5534 return;
5535 }
5536 mLastUserActivityCallTime = curTime;
5537 mLastTouchEventType = eventType;
5538 }
5539
5540 if (targetWin == null
5541 || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
5542 mPowerManager.userActivity(curTime, false, eventType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005543 }
5544 }
5545
5546 // tells if it's a cheek event or not -- this function is stateful
5547 private static final int EVENT_NONE = 0;
5548 private static final int EVENT_UNKNOWN = 0;
5549 private static final int EVENT_CHEEK = 0;
5550 private static final int EVENT_IGNORE_DURATION = 300; // ms
5551 private static final float CHEEK_THRESHOLD = 0.6f;
5552 private int mEventState = EVENT_NONE;
5553 private float mEventSize;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005554
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005555 private int eventType(MotionEvent ev) {
5556 float size = ev.getSize();
5557 switch (ev.getAction()) {
5558 case MotionEvent.ACTION_DOWN:
5559 mEventSize = size;
5560 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT;
5561 case MotionEvent.ACTION_UP:
5562 if (size > mEventSize) mEventSize = size;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005563 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005564 case MotionEvent.ACTION_MOVE:
5565 final int N = ev.getHistorySize();
5566 if (size > mEventSize) mEventSize = size;
5567 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5568 for (int i=0; i<N; i++) {
5569 size = ev.getHistoricalSize(i);
5570 if (size > mEventSize) mEventSize = size;
5571 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5572 }
5573 if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) {
5574 return TOUCH_EVENT;
5575 } else {
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005576 return LONG_TOUCH_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005577 }
5578 default:
5579 // not good
5580 return OTHER_EVENT;
5581 }
5582 }
5583
5584 /**
5585 * @return Returns true if event was dispatched, false if it was dropped for any reason
5586 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005587 private int dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005588 if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005589 "dispatchPointer " + ev);
5590
Michael Chan53071d62009-05-13 17:29:48 -07005591 if (MEASURE_LATENCY) {
5592 lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
5593 }
5594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005595 Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005596 ev, true, false, pid, uid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005597
Michael Chan53071d62009-05-13 17:29:48 -07005598 if (MEASURE_LATENCY) {
5599 lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
5600 }
5601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005602 int action = ev.getAction();
Romain Guy06882f82009-06-10 13:36:04 -07005603
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005604 if (action == MotionEvent.ACTION_UP) {
5605 // let go of our target
5606 mKeyWaiter.mMotionTarget = null;
5607 mPowerManager.logPointerUpEvent();
5608 } else if (action == MotionEvent.ACTION_DOWN) {
5609 mPowerManager.logPointerDownEvent();
5610 }
5611
5612 if (targetObj == null) {
5613 // In this case we are either dropping the event, or have received
5614 // a move or up without a down. It is common to receive move
5615 // events in such a way, since this means the user is moving the
5616 // pointer without actually pressing down. All other cases should
5617 // be atypical, so let's log them.
Michael Chane96440f2009-05-06 10:27:36 -07005618 if (action != MotionEvent.ACTION_MOVE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005619 Slog.w(TAG, "No window to dispatch pointer action " + ev.getAction());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005620 }
Dianne Hackborn6adba242009-11-10 11:10:09 -08005621 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005622 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005623 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005624 if (qev != null) {
5625 mQueue.recycleEvent(qev);
5626 }
5627 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005628 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629 }
5630 if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborn6adba242009-11-10 11:10:09 -08005631 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005632 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005634 if (qev != null) {
5635 mQueue.recycleEvent(qev);
5636 }
5637 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005638 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005639 }
Romain Guy06882f82009-06-10 13:36:04 -07005640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005641 WindowState target = (WindowState)targetObj;
Romain Guy06882f82009-06-10 13:36:04 -07005642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005643 final long eventTime = ev.getEventTime();
Michael Chan53071d62009-05-13 17:29:48 -07005644 final long eventTimeNano = ev.getEventTimeNano();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005645
Joe Onorato8a9b2202010-02-26 18:56:32 -08005646 //Slog.i(TAG, "Sending " + ev + " to " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005647
5648 if (uid != 0 && uid != target.mSession.mUid) {
5649 if (mContext.checkPermission(
5650 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5651 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005652 Slog.w(TAG, "Permission denied: injecting pointer event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005653 + pid + " uid " + uid + " to window " + target
5654 + " owned by uid " + target.mSession.mUid);
5655 if (qev != null) {
5656 mQueue.recycleEvent(qev);
5657 }
5658 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005659 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005660 }
5661 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005662
Michael Chan53071d62009-05-13 17:29:48 -07005663 if (MEASURE_LATENCY) {
5664 lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano);
5665 }
5666
Romain Guy06882f82009-06-10 13:36:04 -07005667 if ((target.mAttrs.flags &
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005668 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
5669 //target wants to ignore fat touch events
5670 boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev);
5671 //explicit flag to return without processing event further
5672 boolean returnFlag = false;
5673 if((action == MotionEvent.ACTION_DOWN)) {
5674 mFatTouch = false;
5675 if(cheekPress) {
5676 mFatTouch = true;
5677 returnFlag = true;
5678 }
5679 } else {
5680 if(action == MotionEvent.ACTION_UP) {
5681 if(mFatTouch) {
5682 //earlier even was invalid doesnt matter if current up is cheekpress or not
5683 mFatTouch = false;
5684 returnFlag = true;
5685 } else if(cheekPress) {
5686 //cancel the earlier event
5687 ev.setAction(MotionEvent.ACTION_CANCEL);
5688 action = MotionEvent.ACTION_CANCEL;
5689 }
5690 } else if(action == MotionEvent.ACTION_MOVE) {
5691 if(mFatTouch) {
5692 //two cases here
5693 //an invalid down followed by 0 or moves(valid or invalid)
Romain Guy06882f82009-06-10 13:36:04 -07005694 //a valid down, invalid move, more moves. want to ignore till up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005695 returnFlag = true;
5696 } else if(cheekPress) {
5697 //valid down followed by invalid moves
5698 //an invalid move have to cancel earlier action
5699 ev.setAction(MotionEvent.ACTION_CANCEL);
5700 action = MotionEvent.ACTION_CANCEL;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005701 if (DEBUG_INPUT) Slog.v(TAG, "Sending cancel for invalid ACTION_MOVE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005702 //note that the subsequent invalid moves will not get here
5703 mFatTouch = true;
5704 }
5705 }
5706 } //else if action
5707 if(returnFlag) {
5708 //recycle que, ev
5709 if (qev != null) {
5710 mQueue.recycleEvent(qev);
5711 }
5712 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005713 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005714 }
5715 } //end if target
Michael Chane96440f2009-05-06 10:27:36 -07005716
Michael Chan9f028e62009-08-04 17:37:46 -07005717 // Enable this for testing the "right" value
5718 if (false && action == MotionEvent.ACTION_DOWN) {
Michael Chane96440f2009-05-06 10:27:36 -07005719 int max_events_per_sec = 35;
5720 try {
5721 max_events_per_sec = Integer.parseInt(SystemProperties
5722 .get("windowsmgr.max_events_per_sec"));
5723 if (max_events_per_sec < 1) {
5724 max_events_per_sec = 35;
5725 }
5726 } catch (NumberFormatException e) {
5727 }
5728 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
5729 }
5730
5731 /*
5732 * Throttle events to minimize CPU usage when there's a flood of events
5733 * e.g. constant contact with the screen
5734 */
5735 if (action == MotionEvent.ACTION_MOVE) {
5736 long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents;
5737 long now = SystemClock.uptimeMillis();
5738 if (now < nextEventTime) {
5739 try {
5740 Thread.sleep(nextEventTime - now);
5741 } catch (InterruptedException e) {
5742 }
5743 mLastTouchEventTime = nextEventTime;
5744 } else {
5745 mLastTouchEventTime = now;
5746 }
5747 }
5748
Michael Chan53071d62009-05-13 17:29:48 -07005749 if (MEASURE_LATENCY) {
5750 lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano);
5751 }
5752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005753 synchronized(mWindowMap) {
Dianne Hackborn6adba242009-11-10 11:10:09 -08005754 if (!target.isVisibleLw()) {
5755 // During this motion dispatch, the target window has become
5756 // invisible.
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005757 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), false);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005758 if (qev != null) {
5759 mQueue.recycleEvent(qev);
5760 }
5761 ev.recycle();
5762 return INJECT_SUCCEEDED;
5763 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 if (qev != null && action == MotionEvent.ACTION_MOVE) {
5766 mKeyWaiter.bindTargetWindowLocked(target,
5767 KeyWaiter.RETURN_PENDING_POINTER, qev);
5768 ev = null;
5769 } else {
5770 if (action == MotionEvent.ACTION_DOWN) {
5771 WindowState out = mKeyWaiter.mOutsideTouchTargets;
5772 if (out != null) {
5773 MotionEvent oev = MotionEvent.obtain(ev);
Adam Powell47482962010-05-27 15:19:58 -07005774 try {
5775 oev.setAction(MotionEvent.ACTION_OUTSIDE);
5776 do {
5777 final Rect frame = out.mFrame;
5778 oev.offsetLocation(-(float)frame.left, -(float)frame.top);
5779 try {
5780 out.mClient.dispatchPointer(oev, eventTime, false);
5781 } catch (android.os.RemoteException e) {
5782 Slog.i(TAG,
5783 "WINDOW DIED during outside motion dispatch: " + out);
5784 }
5785 oev.offsetLocation((float)frame.left, (float)frame.top);
5786 out = out.mNextOutsideTouch;
5787 } while (out != null);
5788 mKeyWaiter.mOutsideTouchTargets = null;
5789 } finally {
5790 oev.recycle();
5791 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005792 }
5793 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005794
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005795 dispatchPointerElsewhereLocked(target, null, ev, ev.getEventTime(), false);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005796
Dianne Hackborn6adba242009-11-10 11:10:09 -08005797 final Rect frame = target.mFrame;
5798 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
5799 mKeyWaiter.bindTargetWindowLocked(target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005800 }
5801 }
Romain Guy06882f82009-06-10 13:36:04 -07005802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005803 // finally offset the event to the target's coordinate system and
5804 // dispatch the event.
5805 try {
5806 if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005807 Slog.v(TAG, "Delivering pointer " + qev + " to " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005808 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005809
Michael Chan53071d62009-05-13 17:29:48 -07005810 if (MEASURE_LATENCY) {
5811 lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
5812 }
5813
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005814 target.mClient.dispatchPointer(ev, eventTime, true);
Michael Chan53071d62009-05-13 17:29:48 -07005815
5816 if (MEASURE_LATENCY) {
5817 lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
5818 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07005819 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005820 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005821 Slog.i(TAG, "WINDOW DIED during motion dispatch: " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005822 mKeyWaiter.mMotionTarget = null;
5823 try {
5824 removeWindow(target.mSession, target.mClient);
5825 } catch (java.util.NoSuchElementException ex) {
5826 // This will happen if the window has already been
5827 // removed.
5828 }
5829 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07005830 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005831 }
Romain Guy06882f82009-06-10 13:36:04 -07005832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005833 /**
5834 * @return Returns true if event was dispatched, false if it was dropped for any reason
5835 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005836 private int dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005837 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005838 TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">");
Romain Guy06882f82009-06-10 13:36:04 -07005839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005841 ev, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005842 if (focusObj == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005843 Slog.w(TAG, "No focus window, dropping trackball: " + ev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005844 if (qev != null) {
5845 mQueue.recycleEvent(qev);
5846 }
5847 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005848 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005849 }
5850 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5851 if (qev != null) {
5852 mQueue.recycleEvent(qev);
5853 }
5854 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005855 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005856 }
Romain Guy06882f82009-06-10 13:36:04 -07005857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07005859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 if (uid != 0 && uid != focus.mSession.mUid) {
5861 if (mContext.checkPermission(
5862 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5863 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005864 Slog.w(TAG, "Permission denied: injecting key event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 + pid + " uid " + uid + " to window " + focus
5866 + " owned by uid " + focus.mSession.mUid);
5867 if (qev != null) {
5868 mQueue.recycleEvent(qev);
5869 }
5870 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005871 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005872 }
5873 }
Romain Guy06882f82009-06-10 13:36:04 -07005874
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005875 final long eventTime = ev.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07005876
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005877 synchronized(mWindowMap) {
5878 if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) {
5879 mKeyWaiter.bindTargetWindowLocked(focus,
5880 KeyWaiter.RETURN_PENDING_TRACKBALL, qev);
5881 // We don't deliver movement events to the client, we hold
5882 // them and wait for them to call back.
5883 ev = null;
5884 } else {
5885 mKeyWaiter.bindTargetWindowLocked(focus);
5886 }
5887 }
Romain Guy06882f82009-06-10 13:36:04 -07005888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005889 try {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005890 focus.mClient.dispatchTrackball(ev, eventTime, true);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005891 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005892 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005893 Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005894 try {
5895 removeWindow(focus.mSession, focus.mClient);
5896 } catch (java.util.NoSuchElementException ex) {
5897 // This will happen if the window has already been
5898 // removed.
5899 }
5900 }
Romain Guy06882f82009-06-10 13:36:04 -07005901
Dianne Hackborncfaef692009-06-15 14:24:44 -07005902 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005903 }
Romain Guy06882f82009-06-10 13:36:04 -07005904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005905 /**
5906 * @return Returns true if event was dispatched, false if it was dropped for any reason
5907 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005908 private int dispatchKey(KeyEvent event, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005909 if (DEBUG_INPUT) Slog.v(TAG, "Dispatch key: " + event);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005910
5911 Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005912 null, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005913 if (focusObj == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005914 Slog.w(TAG, "No focus window, dropping: " + event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005915 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005916 }
5917 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005918 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005919 }
Romain Guy06882f82009-06-10 13:36:04 -07005920
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07005921 // Okay we have finished waiting for the last event to be processed.
5922 // First off, if this is a repeat event, check to see if there is
5923 // a corresponding up event in the queue. If there is, we will
5924 // just drop the repeat, because it makes no sense to repeat after
5925 // the user has released a key. (This is especially important for
5926 // long presses.)
5927 if (event.getRepeatCount() > 0 && mQueue.hasKeyUpEvent(event)) {
5928 return INJECT_SUCCEEDED;
5929 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07005932
Joe Onorato8a9b2202010-02-26 18:56:32 -08005933 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005934 TAG, "Dispatching to " + focus + ": " + event);
5935
5936 if (uid != 0 && uid != focus.mSession.mUid) {
5937 if (mContext.checkPermission(
5938 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5939 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005940 Slog.w(TAG, "Permission denied: injecting key event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 + pid + " uid " + uid + " to window " + focus
5942 + " owned by uid " + focus.mSession.mUid);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005943 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005944 }
5945 }
Romain Guy06882f82009-06-10 13:36:04 -07005946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 synchronized(mWindowMap) {
5948 mKeyWaiter.bindTargetWindowLocked(focus);
5949 }
5950
5951 // NOSHIP extra state logging
5952 mKeyWaiter.recordDispatchState(event, focus);
5953 // END NOSHIP
Romain Guy06882f82009-06-10 13:36:04 -07005954
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005955 try {
5956 if (DEBUG_INPUT || DEBUG_FOCUS) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005957 Slog.v(TAG, "Delivering key " + event.getKeyCode()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005958 + " to " + focus);
5959 }
5960 focus.mClient.dispatchKey(event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005961 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005962 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005963 Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 try {
5965 removeWindow(focus.mSession, focus.mClient);
5966 } catch (java.util.NoSuchElementException ex) {
5967 // This will happen if the window has already been
5968 // removed.
5969 }
5970 }
Romain Guy06882f82009-06-10 13:36:04 -07005971
Dianne Hackborncfaef692009-06-15 14:24:44 -07005972 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005973 }
Romain Guy06882f82009-06-10 13:36:04 -07005974
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005975 public void pauseKeyDispatching(IBinder _token) {
5976 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5977 "pauseKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005978 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005979 }
5980
5981 synchronized (mWindowMap) {
5982 WindowToken token = mTokenMap.get(_token);
5983 if (token != null) {
5984 mKeyWaiter.pauseDispatchingLocked(token);
5985 }
5986 }
5987 }
5988
5989 public void resumeKeyDispatching(IBinder _token) {
5990 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5991 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005992 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005993 }
5994
5995 synchronized (mWindowMap) {
5996 WindowToken token = mTokenMap.get(_token);
5997 if (token != null) {
5998 mKeyWaiter.resumeDispatchingLocked(token);
5999 }
6000 }
6001 }
6002
6003 public void setEventDispatching(boolean enabled) {
6004 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
6005 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07006006 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006007 }
6008
6009 synchronized (mWindowMap) {
6010 mKeyWaiter.setEventDispatchingLocked(enabled);
6011 }
6012 }
Romain Guy06882f82009-06-10 13:36:04 -07006013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006014 /**
6015 * Injects a keystroke event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07006016 *
6017 * @param ev A motion event describing the keystroke action. (Be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006018 * {@link SystemClock#uptimeMillis()} as the timebase.)
6019 * @param sync If true, wait for the event to be completed before returning to the caller.
6020 * @return Returns true if event was dispatched, false if it was dropped for any reason
6021 */
6022 public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
6023 long downTime = ev.getDownTime();
6024 long eventTime = ev.getEventTime();
6025
6026 int action = ev.getAction();
6027 int code = ev.getKeyCode();
6028 int repeatCount = ev.getRepeatCount();
6029 int metaState = ev.getMetaState();
6030 int deviceId = ev.getDeviceId();
6031 int scancode = ev.getScanCode();
6032
6033 if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
6034 if (downTime == 0) downTime = eventTime;
6035
6036 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
The Android Open Source Project10592532009-03-18 17:39:46 -07006037 deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006038
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006039 final int pid = Binder.getCallingPid();
6040 final int uid = Binder.getCallingUid();
6041 final long ident = Binder.clearCallingIdentity();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006042
6043 final int result;
6044 if (ENABLE_NATIVE_INPUT_DISPATCH) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07006045 result = mInputManager.injectKeyEvent(newEvent, InputQueue.INPUT_EVENT_NATURE_KEY,
6046 pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006047 } else {
6048 result = dispatchKey(newEvent, pid, uid);
6049 if (sync) {
6050 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
6051 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006052 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006053
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006054 Binder.restoreCallingIdentity(ident);
Jeff Brown7fbdc842010-06-17 20:52:56 -07006055 return reportInjectionResult(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006056 }
6057
6058 /**
6059 * Inject a pointer (touch) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07006060 *
6061 * @param ev A motion event describing the pointer (touch) action. (As noted in
6062 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006063 * {@link SystemClock#uptimeMillis()} as the timebase.)
6064 * @param sync If true, wait for the event to be completed before returning to the caller.
6065 * @return Returns true if event was dispatched, false if it was dropped for any reason
6066 */
6067 public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006068 final int pid = Binder.getCallingPid();
6069 final int uid = Binder.getCallingUid();
6070 final long ident = Binder.clearCallingIdentity();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006071
6072 final int result;
6073 if (ENABLE_NATIVE_INPUT_DISPATCH) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07006074 result = mInputManager.injectMotionEvent(ev, InputQueue.INPUT_EVENT_NATURE_TOUCH,
6075 pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006076 } else {
6077 result = dispatchPointer(null, ev, pid, uid);
6078 if (sync) {
6079 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
6080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006081 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006082
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006083 Binder.restoreCallingIdentity(ident);
Jeff Brown7fbdc842010-06-17 20:52:56 -07006084 return reportInjectionResult(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006085 }
Romain Guy06882f82009-06-10 13:36:04 -07006086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006087 /**
6088 * Inject a trackball (navigation device) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07006089 *
6090 * @param ev A motion event describing the trackball action. (As noted in
6091 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006092 * {@link SystemClock#uptimeMillis()} as the timebase.)
6093 * @param sync If true, wait for the event to be completed before returning to the caller.
6094 * @return Returns true if event was dispatched, false if it was dropped for any reason
6095 */
6096 public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006097 final int pid = Binder.getCallingPid();
6098 final int uid = Binder.getCallingUid();
6099 final long ident = Binder.clearCallingIdentity();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006100
6101 final int result;
6102 if (ENABLE_NATIVE_INPUT_DISPATCH) {
Jeff Brown7fbdc842010-06-17 20:52:56 -07006103 result = mInputManager.injectMotionEvent(ev, InputQueue.INPUT_EVENT_NATURE_TRACKBALL,
6104 pid, uid, sync, INJECTION_TIMEOUT_MILLIS);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006105 } else {
6106 result = dispatchTrackball(null, ev, pid, uid);
6107 if (sync) {
6108 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
6109 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006110 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07006111
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006112 Binder.restoreCallingIdentity(ident);
Jeff Brown7fbdc842010-06-17 20:52:56 -07006113 return reportInjectionResult(result);
6114 }
6115
6116 private boolean reportInjectionResult(int result) {
6117 if (ENABLE_NATIVE_INPUT_DISPATCH) {
6118 switch (result) {
6119 case InputManager.INPUT_EVENT_INJECTION_PERMISSION_DENIED:
6120 Slog.w(TAG, "Input event injection permission denied.");
6121 throw new SecurityException(
6122 "Injecting to another application requires INJECT_EVENTS permission");
6123 case InputManager.INPUT_EVENT_INJECTION_SUCCEEDED:
6124 Slog.v(TAG, "Input event injection succeeded.");
6125 return true;
6126 case InputManager.INPUT_EVENT_INJECTION_TIMED_OUT:
6127 Slog.w(TAG, "Input event injection timed out.");
6128 return false;
6129 case InputManager.INPUT_EVENT_INJECTION_FAILED:
6130 default:
6131 Slog.w(TAG, "Input event injection failed.");
6132 return false;
6133 }
6134 } else {
6135 switch (result) {
6136 case INJECT_NO_PERMISSION:
6137 throw new SecurityException(
6138 "Injecting to another application requires INJECT_EVENTS permission");
6139 case INJECT_SUCCEEDED:
6140 return true;
6141 }
6142 return false;
Dianne Hackborncfaef692009-06-15 14:24:44 -07006143 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006144 }
Romain Guy06882f82009-06-10 13:36:04 -07006145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006146 private WindowState getFocusedWindow() {
6147 synchronized (mWindowMap) {
6148 return getFocusedWindowLocked();
6149 }
6150 }
6151
6152 private WindowState getFocusedWindowLocked() {
6153 return mCurrentFocus;
6154 }
Romain Guy06882f82009-06-10 13:36:04 -07006155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006156 /**
6157 * This class holds the state for dispatching key events. This state
6158 * is protected by the KeyWaiter instance, NOT by the window lock. You
6159 * can be holding the main window lock while acquire the KeyWaiter lock,
6160 * but not the other way around.
6161 */
6162 final class KeyWaiter {
6163 // NOSHIP debugging
6164 public class DispatchState {
6165 private KeyEvent event;
6166 private WindowState focus;
6167 private long time;
6168 private WindowState lastWin;
6169 private IBinder lastBinder;
6170 private boolean finished;
6171 private boolean gotFirstWindow;
6172 private boolean eventDispatching;
6173 private long timeToSwitch;
6174 private boolean wasFrozen;
6175 private boolean focusPaused;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006176 private WindowState curFocus;
Romain Guy06882f82009-06-10 13:36:04 -07006177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006178 DispatchState(KeyEvent theEvent, WindowState theFocus) {
6179 focus = theFocus;
6180 event = theEvent;
6181 time = System.currentTimeMillis();
6182 // snapshot KeyWaiter state
6183 lastWin = mLastWin;
6184 lastBinder = mLastBinder;
6185 finished = mFinished;
6186 gotFirstWindow = mGotFirstWindow;
6187 eventDispatching = mEventDispatching;
6188 timeToSwitch = mTimeToSwitch;
6189 wasFrozen = mWasFrozen;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006190 curFocus = mCurrentFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006191 // cache the paused state at ctor time as well
6192 if (theFocus == null || theFocus.mToken == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006193 focusPaused = false;
6194 } else {
6195 focusPaused = theFocus.mToken.paused;
6196 }
6197 }
Romain Guy06882f82009-06-10 13:36:04 -07006198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006199 public String toString() {
6200 return "{{" + event + " to " + focus + " @ " + time
6201 + " lw=" + lastWin + " lb=" + lastBinder
6202 + " fin=" + finished + " gfw=" + gotFirstWindow
6203 + " ed=" + eventDispatching + " tts=" + timeToSwitch
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006204 + " wf=" + wasFrozen + " fp=" + focusPaused
Christopher Tate46d45252010-02-09 15:48:57 -08006205 + " mcf=" + curFocus + "}}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006206 }
6207 };
6208 private DispatchState mDispatchState = null;
6209 public void recordDispatchState(KeyEvent theEvent, WindowState theFocus) {
6210 mDispatchState = new DispatchState(theEvent, theFocus);
6211 }
6212 // END NOSHIP
6213
6214 public static final int RETURN_NOTHING = 0;
6215 public static final int RETURN_PENDING_POINTER = 1;
6216 public static final int RETURN_PENDING_TRACKBALL = 2;
Romain Guy06882f82009-06-10 13:36:04 -07006217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006218 final Object SKIP_TARGET_TOKEN = new Object();
6219 final Object CONSUMED_EVENT_TOKEN = new Object();
Romain Guy06882f82009-06-10 13:36:04 -07006220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006221 private WindowState mLastWin = null;
6222 private IBinder mLastBinder = null;
6223 private boolean mFinished = true;
6224 private boolean mGotFirstWindow = false;
6225 private boolean mEventDispatching = true;
6226 private long mTimeToSwitch = 0;
6227 /* package */ boolean mWasFrozen = false;
Romain Guy06882f82009-06-10 13:36:04 -07006228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006229 // Target of Motion events
6230 WindowState mMotionTarget;
Romain Guy06882f82009-06-10 13:36:04 -07006231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006232 // Windows above the target who would like to receive an "outside"
6233 // touch event for any down events outside of them.
6234 WindowState mOutsideTouchTargets;
6235
6236 /**
6237 * Wait for the last event dispatch to complete, then find the next
6238 * target that should receive the given event and wait for that one
6239 * to be ready to receive it.
6240 */
6241 Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev,
6242 MotionEvent nextMotion, boolean isPointerEvent,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006243 boolean failIfTimeout, int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006244 long startTime = SystemClock.uptimeMillis();
6245 long keyDispatchingTimeout = 5 * 1000;
6246 long waitedFor = 0;
6247
6248 while (true) {
6249 // Figure out which window we care about. It is either the
6250 // last window we are waiting to have process the event or,
6251 // if none, then the next window we think the event should go
6252 // to. Note: we retrieve mLastWin outside of the lock, so
6253 // it may change before we lock. Thus we must check it again.
6254 WindowState targetWin = mLastWin;
6255 boolean targetIsNew = targetWin == null;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006256 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006257 TAG, "waitForLastKey: mFinished=" + mFinished +
6258 ", mLastWin=" + mLastWin);
6259 if (targetIsNew) {
6260 Object target = findTargetWindow(nextKey, qev, nextMotion,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006261 isPointerEvent, callingPid, callingUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006262 if (target == SKIP_TARGET_TOKEN) {
6263 // The user has pressed a special key, and we are
6264 // dropping all pending events before it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006265 if (DEBUG_INPUT) Slog.v(TAG, "Skipping: " + nextKey
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006266 + " " + nextMotion);
6267 return null;
6268 }
6269 if (target == CONSUMED_EVENT_TOKEN) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006270 if (DEBUG_INPUT) Slog.v(TAG, "Consumed: " + nextKey
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006271 + " " + nextMotion);
6272 return target;
6273 }
6274 targetWin = (WindowState)target;
6275 }
Romain Guy06882f82009-06-10 13:36:04 -07006276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006277 AppWindowToken targetApp = null;
Romain Guy06882f82009-06-10 13:36:04 -07006278
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006279 // Now: is it okay to send the next event to this window?
6280 synchronized (this) {
6281 // First: did we come here based on the last window not
6282 // being null, but it changed by the time we got here?
6283 // If so, try again.
6284 if (!targetIsNew && mLastWin == null) {
6285 continue;
6286 }
Romain Guy06882f82009-06-10 13:36:04 -07006287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006288 // We never dispatch events if not finished with the
6289 // last one, or the display is frozen.
6290 if (mFinished && !mDisplayFrozen) {
6291 // If event dispatching is disabled, then we
6292 // just consume the events.
6293 if (!mEventDispatching) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006294 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006295 "Skipping event; dispatching disabled: "
6296 + nextKey + " " + nextMotion);
6297 return null;
6298 }
6299 if (targetWin != null) {
6300 // If this is a new target, and that target is not
6301 // paused or unresponsive, then all looks good to
6302 // handle the event.
6303 if (targetIsNew && !targetWin.mToken.paused) {
6304 return targetWin;
6305 }
Romain Guy06882f82009-06-10 13:36:04 -07006306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006307 // If we didn't find a target window, and there is no
6308 // focused app window, then just eat the events.
6309 } else if (mFocusedApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006310 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006311 "Skipping event; no focused app: "
6312 + nextKey + " " + nextMotion);
6313 return null;
6314 }
6315 }
Romain Guy06882f82009-06-10 13:36:04 -07006316
Joe Onorato8a9b2202010-02-26 18:56:32 -08006317 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006318 TAG, "Waiting for last key in " + mLastBinder
6319 + " target=" + targetWin
6320 + " mFinished=" + mFinished
6321 + " mDisplayFrozen=" + mDisplayFrozen
6322 + " targetIsNew=" + targetIsNew
6323 + " paused="
6324 + (targetWin != null ? targetWin.mToken.paused : false)
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006325 + " mFocusedApp=" + mFocusedApp
6326 + " mCurrentFocus=" + mCurrentFocus);
Romain Guy06882f82009-06-10 13:36:04 -07006327
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006328 targetApp = targetWin != null
6329 ? targetWin.mAppToken : mFocusedApp;
Romain Guy06882f82009-06-10 13:36:04 -07006330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 long curTimeout = keyDispatchingTimeout;
6332 if (mTimeToSwitch != 0) {
6333 long now = SystemClock.uptimeMillis();
6334 if (mTimeToSwitch <= now) {
6335 // If an app switch key has been pressed, and we have
6336 // waited too long for the current app to finish
6337 // processing keys, then wait no more!
Christopher Tate136b1f92010-02-11 17:51:24 -08006338 doFinishedKeyLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006339 continue;
6340 }
6341 long switchTimeout = mTimeToSwitch - now;
6342 if (curTimeout > switchTimeout) {
6343 curTimeout = switchTimeout;
6344 }
6345 }
Romain Guy06882f82009-06-10 13:36:04 -07006346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006347 try {
6348 // after that continue
6349 // processing keys, so we don't get stuck.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006350 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 TAG, "Waiting for key dispatch: " + curTimeout);
6352 wait(curTimeout);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006353 if (DEBUG_INPUT) Slog.v(TAG, "Finished waiting @"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006354 + SystemClock.uptimeMillis() + " startTime="
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006355 + startTime + " switchTime=" + mTimeToSwitch
6356 + " target=" + targetWin + " mLW=" + mLastWin
6357 + " mLB=" + mLastBinder + " fin=" + mFinished
6358 + " mCurrentFocus=" + mCurrentFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006359 } catch (InterruptedException e) {
6360 }
6361 }
6362
6363 // If we were frozen during configuration change, restart the
6364 // timeout checks from now; otherwise look at whether we timed
6365 // out before awakening.
6366 if (mWasFrozen) {
6367 waitedFor = 0;
6368 mWasFrozen = false;
6369 } else {
6370 waitedFor = SystemClock.uptimeMillis() - startTime;
6371 }
6372
6373 if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) {
6374 IApplicationToken at = null;
6375 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006376 Slog.w(TAG, "Key dispatching timed out sending to " +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006377 (targetWin != null ? targetWin.mAttrs.getTitle()
Ken Shirriff8200b202010-02-04 13:34:37 -08006378 : "<null>: no window ready for key dispatch"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006379 // NOSHIP debugging
Joe Onorato8a9b2202010-02-26 18:56:32 -08006380 Slog.w(TAG, "Previous dispatch state: " + mDispatchState);
6381 Slog.w(TAG, "Current dispatch state: " +
Ken Shirriff8200b202010-02-04 13:34:37 -08006382 new DispatchState(nextKey, targetWin));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006383 // END NOSHIP
6384 //dump();
6385 if (targetWin != null) {
6386 at = targetWin.getAppToken();
6387 } else if (targetApp != null) {
6388 at = targetApp.appToken;
6389 }
6390 }
6391
6392 boolean abort = true;
6393 if (at != null) {
6394 try {
6395 long timeout = at.getKeyDispatchingTimeout();
6396 if (timeout > waitedFor) {
6397 // we did not wait the proper amount of time for this application.
6398 // set the timeout to be the real timeout and wait again.
6399 keyDispatchingTimeout = timeout - waitedFor;
6400 continue;
6401 } else {
6402 abort = at.keyDispatchingTimedOut();
6403 }
6404 } catch (RemoteException ex) {
6405 }
6406 }
6407
6408 synchronized (this) {
6409 if (abort && (mLastWin == targetWin || targetWin == null)) {
6410 mFinished = true;
Romain Guy06882f82009-06-10 13:36:04 -07006411 if (mLastWin != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006412 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006413 "Window " + mLastWin +
6414 " timed out on key input");
6415 if (mLastWin.mToken.paused) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006416 Slog.w(TAG, "Un-pausing dispatching to this window");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006417 mLastWin.mToken.paused = false;
6418 }
6419 }
6420 if (mMotionTarget == targetWin) {
6421 mMotionTarget = null;
6422 }
6423 mLastWin = null;
6424 mLastBinder = null;
6425 if (failIfTimeout || targetWin == null) {
6426 return null;
6427 }
6428 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006429 Slog.w(TAG, "Continuing to wait for key to be dispatched");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006430 startTime = SystemClock.uptimeMillis();
6431 }
6432 }
6433 }
6434 }
6435 }
Romain Guy06882f82009-06-10 13:36:04 -07006436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006437 Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006438 MotionEvent nextMotion, boolean isPointerEvent,
6439 int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 mOutsideTouchTargets = null;
Romain Guy06882f82009-06-10 13:36:04 -07006441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006442 if (nextKey != null) {
6443 // Find the target window for a normal key event.
6444 final int keycode = nextKey.getKeyCode();
6445 final int repeatCount = nextKey.getRepeatCount();
6446 final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP;
6447 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006448
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006449 if (!dispatch) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006450 if (callingUid == 0 ||
6451 mContext.checkPermission(
6452 android.Manifest.permission.INJECT_EVENTS,
6453 callingPid, callingUid)
6454 == PackageManager.PERMISSION_GRANTED) {
6455 mPolicy.interceptKeyTi(null, keycode,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07006456 nextKey.getMetaState(), down, repeatCount,
6457 nextKey.getFlags());
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006458 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08006459 Slog.w(TAG, "Event timeout during app switch: dropping "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006460 + nextKey);
6461 return SKIP_TARGET_TOKEN;
6462 }
Romain Guy06882f82009-06-10 13:36:04 -07006463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006464 // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")");
Romain Guy06882f82009-06-10 13:36:04 -07006465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006466 WindowState focus = null;
6467 synchronized(mWindowMap) {
6468 focus = getFocusedWindowLocked();
6469 }
Romain Guy06882f82009-06-10 13:36:04 -07006470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006471 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
Romain Guy06882f82009-06-10 13:36:04 -07006472
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006473 if (callingUid == 0 ||
6474 (focus != null && callingUid == focus.mSession.mUid) ||
6475 mContext.checkPermission(
6476 android.Manifest.permission.INJECT_EVENTS,
6477 callingPid, callingUid)
6478 == PackageManager.PERMISSION_GRANTED) {
6479 if (mPolicy.interceptKeyTi(focus,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006480 keycode, nextKey.getMetaState(), down, repeatCount,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07006481 nextKey.getFlags())) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07006482 return CONSUMED_EVENT_TOKEN;
6483 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006484 }
Romain Guy06882f82009-06-10 13:36:04 -07006485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006486 return focus;
Romain Guy06882f82009-06-10 13:36:04 -07006487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006488 } else if (!isPointerEvent) {
6489 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1);
6490 if (!dispatch) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006491 Slog.w(TAG, "Event timeout during app switch: dropping trackball "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006492 + nextMotion);
6493 return SKIP_TARGET_TOKEN;
6494 }
Romain Guy06882f82009-06-10 13:36:04 -07006495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496 WindowState focus = null;
6497 synchronized(mWindowMap) {
6498 focus = getFocusedWindowLocked();
6499 }
Romain Guy06882f82009-06-10 13:36:04 -07006500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006501 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
6502 return focus;
6503 }
Romain Guy06882f82009-06-10 13:36:04 -07006504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006505 if (nextMotion == null) {
6506 return SKIP_TARGET_TOKEN;
6507 }
Romain Guy06882f82009-06-10 13:36:04 -07006508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006509 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(
6510 KeyEvent.KEYCODE_UNKNOWN);
6511 if (!dispatch) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006512 Slog.w(TAG, "Event timeout during app switch: dropping pointer "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006513 + nextMotion);
6514 return SKIP_TARGET_TOKEN;
6515 }
Romain Guy06882f82009-06-10 13:36:04 -07006516
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006517 // Find the target window for a pointer event.
6518 int action = nextMotion.getAction();
6519 final float xf = nextMotion.getX();
6520 final float yf = nextMotion.getY();
6521 final long eventTime = nextMotion.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07006522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 final boolean screenWasOff = qev != null
6524 && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07006525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006526 WindowState target = null;
Romain Guy06882f82009-06-10 13:36:04 -07006527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006528 synchronized(mWindowMap) {
6529 synchronized (this) {
6530 if (action == MotionEvent.ACTION_DOWN) {
6531 if (mMotionTarget != null) {
6532 // this is weird, we got a pen down, but we thought it was
6533 // already down!
6534 // XXX: We should probably send an ACTION_UP to the current
6535 // target.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006536 Slog.w(TAG, "Pointer down received while already down in: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006537 + mMotionTarget);
6538 mMotionTarget = null;
6539 }
Romain Guy06882f82009-06-10 13:36:04 -07006540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006541 // ACTION_DOWN is special, because we need to lock next events to
6542 // the window we'll land onto.
6543 final int x = (int)xf;
6544 final int y = (int)yf;
Romain Guy06882f82009-06-10 13:36:04 -07006545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006546 final ArrayList windows = mWindows;
6547 final int N = windows.size();
6548 WindowState topErrWindow = null;
6549 final Rect tmpRect = mTempRect;
6550 for (int i=N-1; i>=0; i--) {
6551 WindowState child = (WindowState)windows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006552 //Slog.i(TAG, "Checking dispatch to: " + child);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006553 final int flags = child.mAttrs.flags;
6554 if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
6555 if (topErrWindow == null) {
6556 topErrWindow = child;
6557 }
6558 }
6559 if (!child.isVisibleLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006560 //Slog.i(TAG, "Not visible!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006561 continue;
6562 }
6563 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006564 //Slog.i(TAG, "Not touchable!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006565 if ((flags & WindowManager.LayoutParams
6566 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
6567 child.mNextOutsideTouch = mOutsideTouchTargets;
6568 mOutsideTouchTargets = child;
6569 }
6570 continue;
6571 }
6572 tmpRect.set(child.mFrame);
6573 if (child.mTouchableInsets == ViewTreeObserver
6574 .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
6575 // The touch is inside of the window if it is
6576 // inside the frame, AND the content part of that
6577 // frame that was given by the application.
6578 tmpRect.left += child.mGivenContentInsets.left;
6579 tmpRect.top += child.mGivenContentInsets.top;
6580 tmpRect.right -= child.mGivenContentInsets.right;
6581 tmpRect.bottom -= child.mGivenContentInsets.bottom;
6582 } else if (child.mTouchableInsets == ViewTreeObserver
6583 .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
6584 // The touch is inside of the window if it is
6585 // inside the frame, AND the visible part of that
6586 // frame that was given by the application.
6587 tmpRect.left += child.mGivenVisibleInsets.left;
6588 tmpRect.top += child.mGivenVisibleInsets.top;
6589 tmpRect.right -= child.mGivenVisibleInsets.right;
6590 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
6591 }
6592 final int touchFlags = flags &
6593 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6594 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
6595 if (tmpRect.contains(x, y) || touchFlags == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006596 //Slog.i(TAG, "Using this target!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006597 if (!screenWasOff || (flags &
6598 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
6599 mMotionTarget = child;
6600 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006601 //Slog.i(TAG, "Waking, skip!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006602 mMotionTarget = null;
6603 }
6604 break;
6605 }
Romain Guy06882f82009-06-10 13:36:04 -07006606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006607 if ((flags & WindowManager.LayoutParams
6608 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
6609 child.mNextOutsideTouch = mOutsideTouchTargets;
6610 mOutsideTouchTargets = child;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006611 //Slog.i(TAG, "Adding to outside target list: " + child);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006612 }
6613 }
6614
6615 // if there's an error window but it's not accepting
6616 // focus (typically because it is not yet visible) just
6617 // wait for it -- any other focused window may in fact
6618 // be in ANR state.
6619 if (topErrWindow != null && mMotionTarget != topErrWindow) {
6620 mMotionTarget = null;
6621 }
6622 }
Romain Guy06882f82009-06-10 13:36:04 -07006623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006624 target = mMotionTarget;
6625 }
6626 }
Romain Guy06882f82009-06-10 13:36:04 -07006627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006628 wakeupIfNeeded(target, eventType(nextMotion));
Romain Guy06882f82009-06-10 13:36:04 -07006629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006630 // Pointer events are a little different -- if there isn't a
6631 // target found for any event, then just drop it.
6632 return target != null ? target : SKIP_TARGET_TOKEN;
6633 }
Romain Guy06882f82009-06-10 13:36:04 -07006634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006635 boolean checkShouldDispatchKey(int keycode) {
6636 synchronized (this) {
6637 if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) {
6638 mTimeToSwitch = 0;
6639 return true;
6640 }
6641 if (mTimeToSwitch != 0
6642 && mTimeToSwitch < SystemClock.uptimeMillis()) {
6643 return false;
6644 }
6645 return true;
6646 }
6647 }
Romain Guy06882f82009-06-10 13:36:04 -07006648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006649 void bindTargetWindowLocked(WindowState win,
6650 int pendingWhat, QueuedEvent pendingMotion) {
6651 synchronized (this) {
6652 bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion);
6653 }
6654 }
Romain Guy06882f82009-06-10 13:36:04 -07006655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006656 void bindTargetWindowLocked(WindowState win) {
6657 synchronized (this) {
6658 bindTargetWindowLockedLocked(win, RETURN_NOTHING, null);
6659 }
6660 }
6661
6662 void bindTargetWindowLockedLocked(WindowState win,
6663 int pendingWhat, QueuedEvent pendingMotion) {
6664 mLastWin = win;
6665 mLastBinder = win.mClient.asBinder();
6666 mFinished = false;
6667 if (pendingMotion != null) {
6668 final Session s = win.mSession;
6669 if (pendingWhat == RETURN_PENDING_POINTER) {
6670 releasePendingPointerLocked(s);
6671 s.mPendingPointerMove = pendingMotion;
6672 s.mPendingPointerWindow = win;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006673 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006674 "bindTargetToWindow " + s.mPendingPointerMove);
6675 } else if (pendingWhat == RETURN_PENDING_TRACKBALL) {
6676 releasePendingTrackballLocked(s);
6677 s.mPendingTrackballMove = pendingMotion;
6678 s.mPendingTrackballWindow = win;
6679 }
6680 }
6681 }
Romain Guy06882f82009-06-10 13:36:04 -07006682
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006683 void releasePendingPointerLocked(Session s) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006684 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006685 "releasePendingPointer " + s.mPendingPointerMove);
6686 if (s.mPendingPointerMove != null) {
6687 mQueue.recycleEvent(s.mPendingPointerMove);
6688 s.mPendingPointerMove = null;
6689 }
6690 }
Romain Guy06882f82009-06-10 13:36:04 -07006691
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006692 void releasePendingTrackballLocked(Session s) {
6693 if (s.mPendingTrackballMove != null) {
6694 mQueue.recycleEvent(s.mPendingTrackballMove);
6695 s.mPendingTrackballMove = null;
6696 }
6697 }
Romain Guy06882f82009-06-10 13:36:04 -07006698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006699 MotionEvent finishedKey(Session session, IWindow client, boolean force,
6700 int returnWhat) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006701 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006702 TAG, "finishedKey: client=" + client + ", force=" + force);
6703
6704 if (client == null) {
6705 return null;
6706 }
6707
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006708 MotionEvent res = null;
6709 QueuedEvent qev = null;
6710 WindowState win = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006712 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006713 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006714 TAG, "finishedKey: client=" + client.asBinder()
6715 + ", force=" + force + ", last=" + mLastBinder
6716 + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
6717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006718 if (returnWhat == RETURN_PENDING_POINTER) {
6719 qev = session.mPendingPointerMove;
6720 win = session.mPendingPointerWindow;
6721 session.mPendingPointerMove = null;
6722 session.mPendingPointerWindow = null;
6723 } else if (returnWhat == RETURN_PENDING_TRACKBALL) {
6724 qev = session.mPendingTrackballMove;
6725 win = session.mPendingTrackballWindow;
6726 session.mPendingTrackballMove = null;
6727 session.mPendingTrackballWindow = null;
6728 }
Romain Guy06882f82009-06-10 13:36:04 -07006729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006730 if (mLastBinder == client.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006731 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 TAG, "finishedKey: last paused="
6733 + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
6734 if (mLastWin != null && (!mLastWin.mToken.paused || force
6735 || !mEventDispatching)) {
Christopher Tate136b1f92010-02-11 17:51:24 -08006736 doFinishedKeyLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006737 } else {
6738 // Make sure to wake up anyone currently waiting to
6739 // dispatch a key, so they can re-evaluate their
6740 // current situation.
6741 mFinished = true;
6742 notifyAll();
6743 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006744 }
Romain Guy06882f82009-06-10 13:36:04 -07006745
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006746 if (qev != null) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006747 res = (MotionEvent)qev.event;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006748 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006749 "Returning pending motion: " + res);
6750 mQueue.recycleEvent(qev);
6751 if (win != null && returnWhat == RETURN_PENDING_POINTER) {
6752 res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
6753 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006754 }
Christopher Tate2624fbc2009-12-11 12:11:31 -08006755 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006756
Christopher Tate2624fbc2009-12-11 12:11:31 -08006757 if (res != null && returnWhat == RETURN_PENDING_POINTER) {
6758 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08006759 dispatchPointerElsewhereLocked(win, win, res, res.getEventTime(), false);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006760 }
6761 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006762
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006763 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006764 }
6765
6766 void tickle() {
6767 synchronized (this) {
6768 notifyAll();
6769 }
6770 }
Romain Guy06882f82009-06-10 13:36:04 -07006771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 void handleNewWindowLocked(WindowState newWindow) {
6773 if (!newWindow.canReceiveKeys()) {
6774 return;
6775 }
6776 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006777 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006778 TAG, "New key dispatch window: win="
6779 + newWindow.mClient.asBinder()
6780 + ", last=" + mLastBinder
6781 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6782 + "), finished=" + mFinished + ", paused="
6783 + newWindow.mToken.paused);
6784
6785 // Displaying a window implicitly causes dispatching to
6786 // be unpaused. (This is to protect against bugs if someone
6787 // pauses dispatching but forgets to resume.)
6788 newWindow.mToken.paused = false;
6789
6790 mGotFirstWindow = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006791
6792 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006793 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006794 "New SYSTEM_ERROR window; resetting state");
6795 mLastWin = null;
6796 mLastBinder = null;
6797 mMotionTarget = null;
6798 mFinished = true;
6799 } else if (mLastWin != null) {
6800 // If the new window is above the window we are
6801 // waiting on, then stop waiting and let key dispatching
6802 // start on the new guy.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006803 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006804 TAG, "Last win layer=" + mLastWin.mLayer
6805 + ", new win layer=" + newWindow.mLayer);
6806 if (newWindow.mLayer >= mLastWin.mLayer) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006807 // The new window is above the old; finish pending input to the last
6808 // window and start directing it to the new one.
6809 mLastWin.mToken.paused = false;
Christopher Tate136b1f92010-02-11 17:51:24 -08006810 doFinishedKeyLocked(false); // does a notifyAll()
6811 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006812 }
6813 }
6814
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006815 // Now that we've put a new window state in place, make the event waiter
6816 // take notice and retarget its attentions.
6817 notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006818 }
6819 }
6820
6821 void pauseDispatchingLocked(WindowToken token) {
6822 synchronized (this)
6823 {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006824 if (DEBUG_INPUT) Slog.v(TAG, "Pausing WindowToken " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006825 token.paused = true;
6826
6827 /*
6828 if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) {
6829 mPaused = true;
6830 } else {
6831 if (mLastWin == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006832 Slog.i(TAG, "Key dispatching not paused: no last window.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006833 } else if (mFinished) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006834 Slog.i(TAG, "Key dispatching not paused: finished last key.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006835 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006836 Slog.i(TAG, "Key dispatching not paused: window in higher layer.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006837 }
6838 }
6839 */
6840 }
6841 }
6842
6843 void resumeDispatchingLocked(WindowToken token) {
6844 synchronized (this) {
6845 if (token.paused) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006846 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006847 TAG, "Resuming WindowToken " + token
6848 + ", last=" + mLastBinder
6849 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6850 + "), finished=" + mFinished + ", paused="
6851 + token.paused);
6852 token.paused = false;
6853 if (mLastWin != null && mLastWin.mToken == token && mFinished) {
Christopher Tate136b1f92010-02-11 17:51:24 -08006854 doFinishedKeyLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006855 } else {
6856 notifyAll();
6857 }
6858 }
6859 }
6860 }
6861
6862 void setEventDispatchingLocked(boolean enabled) {
6863 synchronized (this) {
6864 mEventDispatching = enabled;
6865 notifyAll();
6866 }
6867 }
Romain Guy06882f82009-06-10 13:36:04 -07006868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006869 void appSwitchComing() {
6870 synchronized (this) {
6871 // Don't wait for more than .5 seconds for app to finish
6872 // processing the pending events.
6873 long now = SystemClock.uptimeMillis() + 500;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006874 if (DEBUG_INPUT) Slog.v(TAG, "appSwitchComing: " + now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006875 if (mTimeToSwitch == 0 || now < mTimeToSwitch) {
6876 mTimeToSwitch = now;
6877 }
6878 notifyAll();
6879 }
6880 }
Romain Guy06882f82009-06-10 13:36:04 -07006881
Christopher Tate136b1f92010-02-11 17:51:24 -08006882 private final void doFinishedKeyLocked(boolean force) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006883 if (mLastWin != null) {
6884 releasePendingPointerLocked(mLastWin.mSession);
6885 releasePendingTrackballLocked(mLastWin.mSession);
6886 }
Romain Guy06882f82009-06-10 13:36:04 -07006887
Christopher Tate136b1f92010-02-11 17:51:24 -08006888 if (force || mLastWin == null || !mLastWin.mToken.paused
6889 || !mLastWin.isVisibleLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006890 // If the current window has been paused, we aren't -really-
6891 // finished... so let the waiters still wait.
6892 mLastWin = null;
6893 mLastBinder = null;
6894 }
6895 mFinished = true;
6896 notifyAll();
6897 }
6898 }
6899
6900 private class KeyQ extends KeyInputQueue
6901 implements KeyInputQueue.FilterCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006902 KeyQ() {
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07006903 super(mContext, WindowManagerService.this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006904 }
6905
6906 @Override
6907 boolean preprocessEvent(InputDevice device, RawInputEvent event) {
6908 if (mPolicy.preprocessInputEventTq(event)) {
6909 return true;
6910 }
Romain Guy06882f82009-06-10 13:36:04 -07006911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006912 switch (event.type) {
6913 case RawInputEvent.EV_KEY: {
6914 // XXX begin hack
6915 if (DEBUG) {
6916 if (event.keycode == KeyEvent.KEYCODE_G) {
6917 if (event.value != 0) {
6918 // G down
6919 mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
6920 }
6921 return false;
6922 }
6923 if (event.keycode == KeyEvent.KEYCODE_D) {
6924 if (event.value != 0) {
6925 //dump();
6926 }
6927 return false;
6928 }
6929 }
6930 // XXX end hack
Romain Guy06882f82009-06-10 13:36:04 -07006931
Charles Mendis322591c2009-10-29 11:06:59 -07006932 boolean screenIsOff = !mPowerManager.isScreenOn();
6933 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006934 int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
Romain Guy06882f82009-06-10 13:36:04 -07006935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006936 if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) {
6937 mPowerManager.goToSleep(event.when);
6938 }
6939
6940 if (screenIsOff) {
6941 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6942 }
6943 if (screenIsDim) {
6944 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6945 }
6946 if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
6947 mPowerManager.userActivity(event.when, false,
Michael Chane96440f2009-05-06 10:27:36 -07006948 LocalPowerManager.BUTTON_EVENT, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006949 }
Romain Guy06882f82009-06-10 13:36:04 -07006950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006951 if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
6952 if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) {
6953 filterQueue(this);
6954 mKeyWaiter.appSwitchComing();
6955 }
6956 return true;
6957 } else {
6958 return false;
6959 }
6960 }
Romain Guy06882f82009-06-10 13:36:04 -07006961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006962 case RawInputEvent.EV_REL: {
Charles Mendis322591c2009-10-29 11:06:59 -07006963 boolean screenIsOff = !mPowerManager.isScreenOn();
6964 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 if (screenIsOff) {
6966 if (!mPolicy.isWakeRelMovementTq(event.deviceId,
6967 device.classes, event)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006968 //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006969 return false;
6970 }
6971 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6972 }
6973 if (screenIsDim) {
6974 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6975 }
6976 return true;
6977 }
Romain Guy06882f82009-06-10 13:36:04 -07006978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006979 case RawInputEvent.EV_ABS: {
Charles Mendis322591c2009-10-29 11:06:59 -07006980 boolean screenIsOff = !mPowerManager.isScreenOn();
6981 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006982 if (screenIsOff) {
6983 if (!mPolicy.isWakeAbsMovementTq(event.deviceId,
6984 device.classes, event)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006985 //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006986 return false;
6987 }
6988 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6989 }
6990 if (screenIsDim) {
6991 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6992 }
6993 return true;
6994 }
Romain Guy06882f82009-06-10 13:36:04 -07006995
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006996 default:
6997 return true;
6998 }
6999 }
7000
7001 public int filterEvent(QueuedEvent ev) {
7002 switch (ev.classType) {
7003 case RawInputEvent.CLASS_KEYBOARD:
7004 KeyEvent ke = (KeyEvent)ev.event;
7005 if (mPolicy.isMovementKeyTi(ke.getKeyCode())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007006 Slog.w(TAG, "Dropping movement key during app switch: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007007 + ke.getKeyCode() + ", action=" + ke.getAction());
7008 return FILTER_REMOVE;
7009 }
7010 return FILTER_ABORT;
7011 default:
7012 return FILTER_KEEP;
7013 }
7014 }
Michael Chan53071d62009-05-13 17:29:48 -07007015 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007016
7017 public boolean detectSafeMode() {
7018 mSafeMode = mPolicy.detectSafeMode();
7019 return mSafeMode;
7020 }
Romain Guy06882f82009-06-10 13:36:04 -07007021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007022 public void systemReady() {
7023 mPolicy.systemReady();
7024 }
Romain Guy06882f82009-06-10 13:36:04 -07007025
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007026 private final class InputDispatcherThread extends Thread {
7027 // Time to wait when there is nothing to do: 9999 seconds.
7028 static final int LONG_WAIT=9999*1000;
7029
7030 public InputDispatcherThread() {
7031 super("InputDispatcher");
7032 }
Romain Guy06882f82009-06-10 13:36:04 -07007033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007034 @Override
7035 public void run() {
7036 while (true) {
7037 try {
7038 process();
7039 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007040 Slog.e(TAG, "Exception in input dispatcher", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007041 }
7042 }
7043 }
Romain Guy06882f82009-06-10 13:36:04 -07007044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007045 private void process() {
7046 android.os.Process.setThreadPriority(
7047 android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -07007048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007049 // The last key event we saw
7050 KeyEvent lastKey = null;
7051
7052 // Last keydown time for auto-repeating keys
7053 long lastKeyTime = SystemClock.uptimeMillis();
7054 long nextKeyTime = lastKeyTime+LONG_WAIT;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007055 long downTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007056
Romain Guy06882f82009-06-10 13:36:04 -07007057 // How many successive repeats we generated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007058 int keyRepeatCount = 0;
7059
7060 // Need to report that configuration has changed?
7061 boolean configChanged = false;
Romain Guy06882f82009-06-10 13:36:04 -07007062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007063 while (true) {
7064 long curTime = SystemClock.uptimeMillis();
7065
Joe Onorato8a9b2202010-02-26 18:56:32 -08007066 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007067 TAG, "Waiting for next key: now=" + curTime
7068 + ", repeat @ " + nextKeyTime);
7069
7070 // Retrieve next event, waiting only as long as the next
7071 // repeat timeout. If the configuration has changed, then
7072 // don't wait at all -- we'll report the change as soon as
7073 // we have processed all events.
7074 QueuedEvent ev = mQueue.getEvent(
7075 (int)((!configChanged && curTime < nextKeyTime)
7076 ? (nextKeyTime-curTime) : 0));
7077
Joe Onorato8a9b2202010-02-26 18:56:32 -08007078 if (DEBUG_INPUT && ev != null) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007079 TAG, "Event: type=" + ev.classType + " data=" + ev.event);
7080
Michael Chan53071d62009-05-13 17:29:48 -07007081 if (MEASURE_LATENCY) {
7082 lt.sample("2 got event ", System.nanoTime() - ev.whenNano);
7083 }
7084
Mike Lockwood3d0ea722009-10-21 22:58:29 -04007085 if (lastKey != null && !mPolicy.allowKeyRepeat()) {
7086 // cancel key repeat at the request of the policy.
7087 lastKey = null;
7088 downTime = 0;
7089 lastKeyTime = curTime;
7090 nextKeyTime = curTime + LONG_WAIT;
7091 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007092 try {
7093 if (ev != null) {
Michael Chan53071d62009-05-13 17:29:48 -07007094 curTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007095 int eventType;
7096 if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
7097 eventType = eventType((MotionEvent)ev.event);
7098 } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
7099 ev.classType == RawInputEvent.CLASS_TRACKBALL) {
7100 eventType = LocalPowerManager.BUTTON_EVENT;
7101 } else {
7102 eventType = LocalPowerManager.OTHER_EVENT;
7103 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07007104 try {
Michael Chan53071d62009-05-13 17:29:48 -07007105 if ((curTime - mLastBatteryStatsCallTime)
Michael Chane96440f2009-05-06 10:27:36 -07007106 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
Michael Chan53071d62009-05-13 17:29:48 -07007107 mLastBatteryStatsCallTime = curTime;
Michael Chane96440f2009-05-06 10:27:36 -07007108 mBatteryStats.noteInputEvent();
7109 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07007110 } catch (RemoteException e) {
7111 // Ignore
7112 }
Michael Chane10de972009-05-18 11:24:50 -07007113
Mike Lockwood5db42402009-11-30 14:51:51 -05007114 if (ev.classType == RawInputEvent.CLASS_CONFIGURATION_CHANGED) {
7115 // do not wake screen in this case
7116 } else if (eventType != TOUCH_EVENT
Michael Chane10de972009-05-18 11:24:50 -07007117 && eventType != LONG_TOUCH_EVENT
7118 && eventType != CHEEK_EVENT) {
7119 mPowerManager.userActivity(curTime, false,
7120 eventType, false);
7121 } else if (mLastTouchEventType != eventType
7122 || (curTime - mLastUserActivityCallTime)
7123 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
7124 mLastUserActivityCallTime = curTime;
7125 mLastTouchEventType = eventType;
7126 mPowerManager.userActivity(curTime, false,
7127 eventType, false);
7128 }
7129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007130 switch (ev.classType) {
7131 case RawInputEvent.CLASS_KEYBOARD:
7132 KeyEvent ke = (KeyEvent)ev.event;
7133 if (ke.isDown()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007134 lastKeyTime = curTime;
Kristian Dreher133bfdf2010-02-23 08:50:58 +01007135 if (lastKey != null &&
7136 ke.getKeyCode() == lastKey.getKeyCode()) {
7137 keyRepeatCount++;
7138 // Arbitrary long timeout to block
7139 // repeating here since we know that
7140 // the device driver takes care of it.
7141 nextKeyTime = lastKeyTime + LONG_WAIT;
The Android Open Source Project2a9ae012010-05-12 12:33:35 -07007142 if (DEBUG_INPUT) Slog.v(
Kristian Dreher133bfdf2010-02-23 08:50:58 +01007143 TAG, "Received repeated key down");
7144 } else {
7145 downTime = curTime;
7146 keyRepeatCount = 0;
7147 nextKeyTime = lastKeyTime
7148 + ViewConfiguration.getLongPressTimeout();
The Android Open Source Project2a9ae012010-05-12 12:33:35 -07007149 if (DEBUG_INPUT) Slog.v(
Kristian Dreher133bfdf2010-02-23 08:50:58 +01007150 TAG, "Received key down: first repeat @ "
7151 + nextKeyTime);
7152 }
7153 lastKey = ke;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007154 } else {
7155 lastKey = null;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007156 downTime = 0;
Kristian Dreher133bfdf2010-02-23 08:50:58 +01007157 keyRepeatCount = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007158 // Arbitrary long timeout.
7159 lastKeyTime = curTime;
7160 nextKeyTime = curTime + LONG_WAIT;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007161 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007162 TAG, "Received key up: ignore repeat @ "
7163 + nextKeyTime);
7164 }
Kristian Dreher133bfdf2010-02-23 08:50:58 +01007165 if (keyRepeatCount > 0) {
7166 dispatchKey(KeyEvent.changeTimeRepeat(ke,
7167 ke.getEventTime(), keyRepeatCount), 0, 0);
7168 } else {
7169 dispatchKey(ke, 0, 0);
7170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007171 mQueue.recycleEvent(ev);
7172 break;
7173 case RawInputEvent.CLASS_TOUCHSCREEN:
Joe Onorato8a9b2202010-02-26 18:56:32 -08007174 //Slog.i(TAG, "Read next event " + ev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007175 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
7176 break;
7177 case RawInputEvent.CLASS_TRACKBALL:
7178 dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
7179 break;
7180 case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
7181 configChanged = true;
7182 break;
7183 default:
7184 mQueue.recycleEvent(ev);
7185 break;
7186 }
Romain Guy06882f82009-06-10 13:36:04 -07007187
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007188 } else if (configChanged) {
7189 configChanged = false;
7190 sendNewConfiguration();
Romain Guy06882f82009-06-10 13:36:04 -07007191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007192 } else if (lastKey != null) {
7193 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07007194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007195 // Timeout occurred while key was down. If it is at or
7196 // past the key repeat time, dispatch the repeat.
Joe Onorato8a9b2202010-02-26 18:56:32 -08007197 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007198 TAG, "Key timeout: repeat=" + nextKeyTime
7199 + ", now=" + curTime);
7200 if (curTime < nextKeyTime) {
7201 continue;
7202 }
Romain Guy06882f82009-06-10 13:36:04 -07007203
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007204 lastKeyTime = nextKeyTime;
7205 nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY;
7206 keyRepeatCount++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007207 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007208 TAG, "Key repeat: count=" + keyRepeatCount
7209 + ", next @ " + nextKeyTime);
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007210 KeyEvent newEvent;
7211 if (downTime != 0 && (downTime
7212 + ViewConfiguration.getLongPressTimeout())
7213 <= curTime) {
7214 newEvent = KeyEvent.changeTimeRepeat(lastKey,
7215 curTime, keyRepeatCount,
7216 lastKey.getFlags() | KeyEvent.FLAG_LONG_PRESS);
7217 downTime = 0;
7218 } else {
7219 newEvent = KeyEvent.changeTimeRepeat(lastKey,
7220 curTime, keyRepeatCount);
7221 }
7222 dispatchKey(newEvent, 0, 0);
Romain Guy06882f82009-06-10 13:36:04 -07007223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007224 } else {
7225 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07007226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007227 lastKeyTime = curTime;
7228 nextKeyTime = curTime + LONG_WAIT;
7229 }
Romain Guy06882f82009-06-10 13:36:04 -07007230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007231 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007232 Slog.e(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007233 "Input thread received uncaught exception: " + e, e);
7234 }
7235 }
7236 }
7237 }
7238
7239 // -------------------------------------------------------------
7240 // Client Session State
7241 // -------------------------------------------------------------
7242
7243 private final class Session extends IWindowSession.Stub
7244 implements IBinder.DeathRecipient {
7245 final IInputMethodClient mClient;
7246 final IInputContext mInputContext;
7247 final int mUid;
7248 final int mPid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007249 final String mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007250 SurfaceSession mSurfaceSession;
7251 int mNumWindow = 0;
7252 boolean mClientDead = false;
Romain Guy06882f82009-06-10 13:36:04 -07007253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007254 /**
7255 * Current pointer move event being dispatched to client window... must
7256 * hold key lock to access.
7257 */
7258 QueuedEvent mPendingPointerMove;
7259 WindowState mPendingPointerWindow;
Romain Guy06882f82009-06-10 13:36:04 -07007260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007261 /**
7262 * Current trackball move event being dispatched to client window... must
7263 * hold key lock to access.
7264 */
7265 QueuedEvent mPendingTrackballMove;
7266 WindowState mPendingTrackballWindow;
7267
7268 public Session(IInputMethodClient client, IInputContext inputContext) {
7269 mClient = client;
7270 mInputContext = inputContext;
7271 mUid = Binder.getCallingUid();
7272 mPid = Binder.getCallingPid();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007273 StringBuilder sb = new StringBuilder();
7274 sb.append("Session{");
7275 sb.append(Integer.toHexString(System.identityHashCode(this)));
7276 sb.append(" uid ");
7277 sb.append(mUid);
7278 sb.append("}");
7279 mStringName = sb.toString();
Romain Guy06882f82009-06-10 13:36:04 -07007280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007281 synchronized (mWindowMap) {
7282 if (mInputMethodManager == null && mHaveInputMethods) {
7283 IBinder b = ServiceManager.getService(
7284 Context.INPUT_METHOD_SERVICE);
7285 mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
7286 }
7287 }
7288 long ident = Binder.clearCallingIdentity();
7289 try {
7290 // Note: it is safe to call in to the input method manager
7291 // here because we are not holding our lock.
7292 if (mInputMethodManager != null) {
7293 mInputMethodManager.addClient(client, inputContext,
7294 mUid, mPid);
7295 } else {
7296 client.setUsingInputMethod(false);
7297 }
7298 client.asBinder().linkToDeath(this, 0);
7299 } catch (RemoteException e) {
7300 // The caller has died, so we can just forget about this.
7301 try {
7302 if (mInputMethodManager != null) {
7303 mInputMethodManager.removeClient(client);
7304 }
7305 } catch (RemoteException ee) {
7306 }
7307 } finally {
7308 Binder.restoreCallingIdentity(ident);
7309 }
7310 }
Romain Guy06882f82009-06-10 13:36:04 -07007311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007312 @Override
7313 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
7314 throws RemoteException {
7315 try {
7316 return super.onTransact(code, data, reply, flags);
7317 } catch (RuntimeException e) {
7318 // Log all 'real' exceptions thrown to the caller
7319 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007320 Slog.e(TAG, "Window Session Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007321 }
7322 throw e;
7323 }
7324 }
7325
7326 public void binderDied() {
7327 // Note: it is safe to call in to the input method manager
7328 // here because we are not holding our lock.
7329 try {
7330 if (mInputMethodManager != null) {
7331 mInputMethodManager.removeClient(mClient);
7332 }
7333 } catch (RemoteException e) {
7334 }
7335 synchronized(mWindowMap) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07007336 mClient.asBinder().unlinkToDeath(this, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007337 mClientDead = true;
7338 killSessionLocked();
7339 }
7340 }
7341
7342 public int add(IWindow window, WindowManager.LayoutParams attrs,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07007343 int viewVisibility, Rect outContentInsets, InputChannel outInputChannel) {
7344 return addWindow(this, window, attrs, viewVisibility, outContentInsets,
7345 outInputChannel);
7346 }
7347
7348 public int addWithoutInputChannel(IWindow window, WindowManager.LayoutParams attrs,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007349 int viewVisibility, Rect outContentInsets) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07007350 return addWindow(this, window, attrs, viewVisibility, outContentInsets, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007351 }
Romain Guy06882f82009-06-10 13:36:04 -07007352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007353 public void remove(IWindow window) {
7354 removeWindow(this, window);
7355 }
Romain Guy06882f82009-06-10 13:36:04 -07007356
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007357 public int relayout(IWindow window, WindowManager.LayoutParams attrs,
7358 int requestedWidth, int requestedHeight, int viewFlags,
7359 boolean insetsPending, Rect outFrame, Rect outContentInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07007360 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007361 return relayoutWindow(this, window, attrs,
7362 requestedWidth, requestedHeight, viewFlags, insetsPending,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07007363 outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007364 }
Romain Guy06882f82009-06-10 13:36:04 -07007365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007366 public void setTransparentRegion(IWindow window, Region region) {
7367 setTransparentRegionWindow(this, window, region);
7368 }
Romain Guy06882f82009-06-10 13:36:04 -07007369
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007370 public void setInsets(IWindow window, int touchableInsets,
7371 Rect contentInsets, Rect visibleInsets) {
7372 setInsetsWindow(this, window, touchableInsets, contentInsets,
7373 visibleInsets);
7374 }
Romain Guy06882f82009-06-10 13:36:04 -07007375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
7377 getWindowDisplayFrame(this, window, outDisplayFrame);
7378 }
Romain Guy06882f82009-06-10 13:36:04 -07007379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380 public void finishDrawing(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007381 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007382 TAG, "IWindow finishDrawing called for " + window);
7383 finishDrawingWindow(this, window);
7384 }
7385
7386 public void finishKey(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007387 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 TAG, "IWindow finishKey called for " + window);
7389 mKeyWaiter.finishedKey(this, window, false,
7390 KeyWaiter.RETURN_NOTHING);
7391 }
7392
7393 public MotionEvent getPendingPointerMove(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007394 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007395 TAG, "IWindow getPendingMotionEvent called for " + window);
7396 return mKeyWaiter.finishedKey(this, window, false,
7397 KeyWaiter.RETURN_PENDING_POINTER);
7398 }
Romain Guy06882f82009-06-10 13:36:04 -07007399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007400 public MotionEvent getPendingTrackballMove(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007401 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007402 TAG, "IWindow getPendingMotionEvent called for " + window);
7403 return mKeyWaiter.finishedKey(this, window, false,
7404 KeyWaiter.RETURN_PENDING_TRACKBALL);
7405 }
7406
7407 public void setInTouchMode(boolean mode) {
7408 synchronized(mWindowMap) {
7409 mInTouchMode = mode;
7410 }
7411 }
7412
7413 public boolean getInTouchMode() {
7414 synchronized(mWindowMap) {
7415 return mInTouchMode;
7416 }
7417 }
7418
7419 public boolean performHapticFeedback(IWindow window, int effectId,
7420 boolean always) {
7421 synchronized(mWindowMap) {
7422 long ident = Binder.clearCallingIdentity();
7423 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07007424 return mPolicy.performHapticFeedbackLw(
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007425 windowForClientLocked(this, window, true),
7426 effectId, always);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 } finally {
7428 Binder.restoreCallingIdentity(ident);
7429 }
7430 }
7431 }
Romain Guy06882f82009-06-10 13:36:04 -07007432
Marco Nelissenbf6956b2009-11-09 15:21:13 -08007433 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007434 synchronized(mWindowMap) {
7435 long ident = Binder.clearCallingIdentity();
7436 try {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007437 setWindowWallpaperPositionLocked(
7438 windowForClientLocked(this, window, true),
Marco Nelissenbf6956b2009-11-09 15:21:13 -08007439 x, y, xStep, yStep);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007440 } finally {
7441 Binder.restoreCallingIdentity(ident);
7442 }
7443 }
7444 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007445
Dianne Hackborn19382ac2009-09-11 21:13:37 -07007446 public void wallpaperOffsetsComplete(IBinder window) {
7447 WindowManagerService.this.wallpaperOffsetsComplete(window);
7448 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007449
Dianne Hackborn75804932009-10-20 20:15:20 -07007450 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
7451 int z, Bundle extras, boolean sync) {
7452 synchronized(mWindowMap) {
7453 long ident = Binder.clearCallingIdentity();
7454 try {
7455 return sendWindowWallpaperCommandLocked(
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007456 windowForClientLocked(this, window, true),
Dianne Hackborn75804932009-10-20 20:15:20 -07007457 action, x, y, z, extras, sync);
7458 } finally {
7459 Binder.restoreCallingIdentity(ident);
7460 }
7461 }
7462 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007463
Dianne Hackborn75804932009-10-20 20:15:20 -07007464 public void wallpaperCommandComplete(IBinder window, Bundle result) {
7465 WindowManagerService.this.wallpaperCommandComplete(window, result);
7466 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007467
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 void windowAddedLocked() {
7469 if (mSurfaceSession == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007470 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007471 TAG, "First window added to " + this + ", creating SurfaceSession");
7472 mSurfaceSession = new SurfaceSession();
Joe Onorato8a9b2202010-02-26 18:56:32 -08007473 if (SHOW_TRANSACTIONS) Slog.i(
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007474 TAG, " NEW SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475 mSessions.add(this);
7476 }
7477 mNumWindow++;
7478 }
7479
7480 void windowRemovedLocked() {
7481 mNumWindow--;
7482 killSessionLocked();
7483 }
Romain Guy06882f82009-06-10 13:36:04 -07007484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007485 void killSessionLocked() {
7486 if (mNumWindow <= 0 && mClientDead) {
7487 mSessions.remove(this);
7488 if (mSurfaceSession != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007489 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007490 TAG, "Last window removed from " + this
7491 + ", destroying " + mSurfaceSession);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007492 if (SHOW_TRANSACTIONS) Slog.i(
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007493 TAG, " KILL SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 try {
7495 mSurfaceSession.kill();
7496 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007497 Slog.w(TAG, "Exception thrown when killing surface session "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007498 + mSurfaceSession + " in session " + this
7499 + ": " + e.toString());
7500 }
7501 mSurfaceSession = null;
7502 }
7503 }
7504 }
Romain Guy06882f82009-06-10 13:36:04 -07007505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007506 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007507 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
7508 pw.print(" mClientDead="); pw.print(mClientDead);
7509 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
7510 if (mPendingPointerWindow != null || mPendingPointerMove != null) {
7511 pw.print(prefix);
7512 pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
7513 pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
7514 }
7515 if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
7516 pw.print(prefix);
7517 pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
7518 pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
7519 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007520 }
7521
7522 @Override
7523 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07007524 return mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007525 }
7526 }
7527
7528 // -------------------------------------------------------------
7529 // Client Window State
7530 // -------------------------------------------------------------
7531
7532 private final class WindowState implements WindowManagerPolicy.WindowState {
7533 final Session mSession;
7534 final IWindow mClient;
7535 WindowToken mToken;
The Android Open Source Project10592532009-03-18 17:39:46 -07007536 WindowToken mRootToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007537 AppWindowToken mAppToken;
7538 AppWindowToken mTargetAppToken;
7539 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
7540 final DeathRecipient mDeathRecipient;
7541 final WindowState mAttachedWindow;
7542 final ArrayList mChildWindows = new ArrayList();
7543 final int mBaseLayer;
7544 final int mSubLayer;
7545 final boolean mLayoutAttached;
7546 final boolean mIsImWindow;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007547 final boolean mIsWallpaper;
7548 final boolean mIsFloatingLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007549 int mViewVisibility;
7550 boolean mPolicyVisibility = true;
7551 boolean mPolicyVisibilityAfterAnim = true;
7552 boolean mAppFreezing;
7553 Surface mSurface;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007554 boolean mReportDestroySurface;
7555 boolean mSurfacePendingDestroy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007556 boolean mAttachedHidden; // is our parent window hidden?
7557 boolean mLastHidden; // was this window last hidden?
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007558 boolean mWallpaperVisible; // for wallpaper, what was last vis report?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559 int mRequestedWidth;
7560 int mRequestedHeight;
7561 int mLastRequestedWidth;
7562 int mLastRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007563 int mLayer;
7564 int mAnimLayer;
7565 int mLastLayer;
7566 boolean mHaveFrame;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007567 boolean mObscured;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07007568 boolean mTurnOnScreen;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569
7570 WindowState mNextOutsideTouch;
Romain Guy06882f82009-06-10 13:36:04 -07007571
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007572 int mLayoutSeq = -1;
7573
7574 Configuration mConfiguration = null;
7575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576 // Actual frame shown on-screen (may be modified by animation)
7577 final Rect mShownFrame = new Rect();
7578 final Rect mLastShownFrame = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 /**
Dianne Hackbornac3587d2010-03-11 11:12:11 -08007581 * Set when we have changed the size of the surface, to know that
7582 * we must tell them application to resize (and thus redraw itself).
7583 */
7584 boolean mSurfaceResized;
7585
7586 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007587 * Insets that determine the actually visible area
7588 */
7589 final Rect mVisibleInsets = new Rect();
7590 final Rect mLastVisibleInsets = new Rect();
7591 boolean mVisibleInsetsChanged;
7592
7593 /**
7594 * Insets that are covered by system windows
7595 */
7596 final Rect mContentInsets = new Rect();
7597 final Rect mLastContentInsets = new Rect();
7598 boolean mContentInsetsChanged;
7599
7600 /**
7601 * Set to true if we are waiting for this window to receive its
7602 * given internal insets before laying out other windows based on it.
7603 */
7604 boolean mGivenInsetsPending;
Romain Guy06882f82009-06-10 13:36:04 -07007605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007606 /**
7607 * These are the content insets that were given during layout for
7608 * this window, to be applied to windows behind it.
7609 */
7610 final Rect mGivenContentInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007612 /**
7613 * These are the visible insets that were given during layout for
7614 * this window, to be applied to windows behind it.
7615 */
7616 final Rect mGivenVisibleInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007618 /**
7619 * Flag indicating whether the touchable region should be adjusted by
7620 * the visible insets; if false the area outside the visible insets is
7621 * NOT touchable, so we must use those to adjust the frame during hit
7622 * tests.
7623 */
7624 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
Romain Guy06882f82009-06-10 13:36:04 -07007625
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007626 // Current transformation being applied.
7627 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
7628 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
7629 float mHScale=1, mVScale=1;
7630 float mLastHScale=1, mLastVScale=1;
7631 final Matrix mTmpMatrix = new Matrix();
7632
7633 // "Real" frame that the application sees.
7634 final Rect mFrame = new Rect();
7635 final Rect mLastFrame = new Rect();
7636
7637 final Rect mContainingFrame = new Rect();
7638 final Rect mDisplayFrame = new Rect();
7639 final Rect mContentFrame = new Rect();
7640 final Rect mVisibleFrame = new Rect();
7641
7642 float mShownAlpha = 1;
7643 float mAlpha = 1;
7644 float mLastAlpha = 1;
7645
7646 // Set to true if, when the window gets displayed, it should perform
7647 // an enter animation.
7648 boolean mEnterAnimationPending;
7649
7650 // Currently running animation.
7651 boolean mAnimating;
7652 boolean mLocalAnimating;
7653 Animation mAnimation;
7654 boolean mAnimationIsEntrance;
7655 boolean mHasTransformation;
7656 boolean mHasLocalTransformation;
7657 final Transformation mTransformation = new Transformation();
7658
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007659 // If a window showing a wallpaper: the requested offset for the
7660 // wallpaper; if a wallpaper window: the currently applied offset.
7661 float mWallpaperX = -1;
7662 float mWallpaperY = -1;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08007663
7664 // If a window showing a wallpaper: what fraction of the offset
7665 // range corresponds to a full virtual screen.
7666 float mWallpaperXStep = -1;
7667 float mWallpaperYStep = -1;
7668
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007669 // Wallpaper windows: pixels offset based on above variables.
7670 int mXOffset;
7671 int mYOffset;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007673 // This is set after IWindowSession.relayout() has been called at
7674 // least once for the window. It allows us to detect the situation
7675 // where we don't yet have a surface, but should have one soon, so
7676 // we can give the window focus before waiting for the relayout.
7677 boolean mRelayoutCalled;
Romain Guy06882f82009-06-10 13:36:04 -07007678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007679 // This is set after the Surface has been created but before the
7680 // window has been drawn. During this time the surface is hidden.
7681 boolean mDrawPending;
7682
7683 // This is set after the window has finished drawing for the first
7684 // time but before its surface is shown. The surface will be
7685 // displayed when the next layout is run.
7686 boolean mCommitDrawPending;
7687
7688 // This is set during the time after the window's drawing has been
7689 // committed, and before its surface is actually shown. It is used
7690 // to delay showing the surface until all windows in a token are ready
7691 // to be shown.
7692 boolean mReadyToShow;
Romain Guy06882f82009-06-10 13:36:04 -07007693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007694 // Set when the window has been shown in the screen the first time.
7695 boolean mHasDrawn;
7696
7697 // Currently running an exit animation?
7698 boolean mExiting;
7699
7700 // Currently on the mDestroySurface list?
7701 boolean mDestroying;
Romain Guy06882f82009-06-10 13:36:04 -07007702
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007703 // Completely remove from window manager after exit animation?
7704 boolean mRemoveOnExit;
7705
7706 // Set when the orientation is changing and this window has not yet
7707 // been updated for the new orientation.
7708 boolean mOrientationChanging;
Romain Guy06882f82009-06-10 13:36:04 -07007709
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007710 // Is this window now (or just being) removed?
7711 boolean mRemoved;
Romain Guy06882f82009-06-10 13:36:04 -07007712
Dianne Hackborn16064f92010-03-25 00:47:24 -07007713 // For debugging, this is the last information given to the surface flinger.
7714 boolean mSurfaceShown;
7715 int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
7716 int mSurfaceLayer;
7717 float mSurfaceAlpha;
7718
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07007719 // Input channel
7720 InputChannel mInputChannel;
7721
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007722 WindowState(Session s, IWindow c, WindowToken token,
7723 WindowState attachedWindow, WindowManager.LayoutParams a,
7724 int viewVisibility) {
7725 mSession = s;
7726 mClient = c;
7727 mToken = token;
7728 mAttrs.copyFrom(a);
7729 mViewVisibility = viewVisibility;
7730 DeathRecipient deathRecipient = new DeathRecipient();
7731 mAlpha = a.alpha;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007732 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007733 TAG, "Window " + this + " client=" + c.asBinder()
7734 + " token=" + token + " (" + mAttrs.token + ")");
7735 try {
7736 c.asBinder().linkToDeath(deathRecipient, 0);
7737 } catch (RemoteException e) {
7738 mDeathRecipient = null;
7739 mAttachedWindow = null;
7740 mLayoutAttached = false;
7741 mIsImWindow = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007742 mIsWallpaper = false;
7743 mIsFloatingLayer = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007744 mBaseLayer = 0;
7745 mSubLayer = 0;
7746 return;
7747 }
7748 mDeathRecipient = deathRecipient;
Romain Guy06882f82009-06-10 13:36:04 -07007749
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007750 if ((mAttrs.type >= FIRST_SUB_WINDOW &&
7751 mAttrs.type <= LAST_SUB_WINDOW)) {
7752 // The multiplier here is to reserve space for multiple
7753 // windows in the same type layer.
7754 mBaseLayer = mPolicy.windowTypeToLayerLw(
7755 attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
7756 + TYPE_LAYER_OFFSET;
7757 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
7758 mAttachedWindow = attachedWindow;
7759 mAttachedWindow.mChildWindows.add(this);
7760 mLayoutAttached = mAttrs.type !=
7761 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
7762 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
7763 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007764 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
7765 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007766 } else {
7767 // The multiplier here is to reserve space for multiple
7768 // windows in the same type layer.
7769 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
7770 * TYPE_LAYER_MULTIPLIER
7771 + TYPE_LAYER_OFFSET;
7772 mSubLayer = 0;
7773 mAttachedWindow = null;
7774 mLayoutAttached = false;
7775 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
7776 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007777 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
7778 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007779 }
7780
7781 WindowState appWin = this;
7782 while (appWin.mAttachedWindow != null) {
7783 appWin = mAttachedWindow;
7784 }
7785 WindowToken appToken = appWin.mToken;
7786 while (appToken.appWindowToken == null) {
7787 WindowToken parent = mTokenMap.get(appToken.token);
7788 if (parent == null || appToken == parent) {
7789 break;
7790 }
7791 appToken = parent;
7792 }
The Android Open Source Project10592532009-03-18 17:39:46 -07007793 mRootToken = appToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007794 mAppToken = appToken.appWindowToken;
7795
7796 mSurface = null;
7797 mRequestedWidth = 0;
7798 mRequestedHeight = 0;
7799 mLastRequestedWidth = 0;
7800 mLastRequestedHeight = 0;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007801 mXOffset = 0;
7802 mYOffset = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007803 mLayer = 0;
7804 mAnimLayer = 0;
7805 mLastLayer = 0;
7806 }
7807
7808 void attach() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007809 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 TAG, "Attaching " + this + " token=" + mToken
7811 + ", list=" + mToken.windows);
7812 mSession.windowAddedLocked();
7813 }
7814
7815 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
7816 mHaveFrame = true;
7817
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007818 final Rect container = mContainingFrame;
7819 container.set(pf);
7820
7821 final Rect display = mDisplayFrame;
7822 display.set(df);
7823
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07007824 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007825 container.intersect(mCompatibleScreenFrame);
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007826 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
7827 display.intersect(mCompatibleScreenFrame);
7828 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007829 }
7830
7831 final int pw = container.right - container.left;
7832 final int ph = container.bottom - container.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007833
7834 int w,h;
7835 if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
7836 w = mAttrs.width < 0 ? pw : mAttrs.width;
7837 h = mAttrs.height< 0 ? ph : mAttrs.height;
7838 } else {
Romain Guy980a9382010-01-08 15:06:28 -08007839 w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
7840 h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007841 }
Romain Guy06882f82009-06-10 13:36:04 -07007842
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007843 final Rect content = mContentFrame;
7844 content.set(cf);
Romain Guy06882f82009-06-10 13:36:04 -07007845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007846 final Rect visible = mVisibleFrame;
7847 visible.set(vf);
Romain Guy06882f82009-06-10 13:36:04 -07007848
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007849 final Rect frame = mFrame;
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07007850 final int fw = frame.width();
7851 final int fh = frame.height();
Romain Guy06882f82009-06-10 13:36:04 -07007852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007853 //System.out.println("In: w=" + w + " h=" + h + " container=" +
7854 // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
7855
7856 Gravity.apply(mAttrs.gravity, w, h, container,
7857 (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
7858 (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
7859
7860 //System.out.println("Out: " + mFrame);
7861
7862 // Now make sure the window fits in the overall display.
7863 Gravity.applyDisplay(mAttrs.gravity, df, frame);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007865 // Make sure the content and visible frames are inside of the
7866 // final window frame.
7867 if (content.left < frame.left) content.left = frame.left;
7868 if (content.top < frame.top) content.top = frame.top;
7869 if (content.right > frame.right) content.right = frame.right;
7870 if (content.bottom > frame.bottom) content.bottom = frame.bottom;
7871 if (visible.left < frame.left) visible.left = frame.left;
7872 if (visible.top < frame.top) visible.top = frame.top;
7873 if (visible.right > frame.right) visible.right = frame.right;
7874 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007876 final Rect contentInsets = mContentInsets;
7877 contentInsets.left = content.left-frame.left;
7878 contentInsets.top = content.top-frame.top;
7879 contentInsets.right = frame.right-content.right;
7880 contentInsets.bottom = frame.bottom-content.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007881
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007882 final Rect visibleInsets = mVisibleInsets;
7883 visibleInsets.left = visible.left-frame.left;
7884 visibleInsets.top = visible.top-frame.top;
7885 visibleInsets.right = frame.right-visible.right;
7886 visibleInsets.bottom = frame.bottom-visible.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007887
Dianne Hackborn284ac932009-08-28 10:34:25 -07007888 if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
7889 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07007890 mDisplay.getHeight(), false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07007891 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007893 if (localLOGV) {
7894 //if ("com.google.android.youtube".equals(mAttrs.packageName)
7895 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007896 Slog.v(TAG, "Resolving (mRequestedWidth="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007897 + mRequestedWidth + ", mRequestedheight="
7898 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
7899 + "): frame=" + mFrame.toShortString()
7900 + " ci=" + contentInsets.toShortString()
7901 + " vi=" + visibleInsets.toShortString());
7902 //}
7903 }
7904 }
Romain Guy06882f82009-06-10 13:36:04 -07007905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007906 public Rect getFrameLw() {
7907 return mFrame;
7908 }
7909
7910 public Rect getShownFrameLw() {
7911 return mShownFrame;
7912 }
7913
7914 public Rect getDisplayFrameLw() {
7915 return mDisplayFrame;
7916 }
7917
7918 public Rect getContentFrameLw() {
7919 return mContentFrame;
7920 }
7921
7922 public Rect getVisibleFrameLw() {
7923 return mVisibleFrame;
7924 }
7925
7926 public boolean getGivenInsetsPendingLw() {
7927 return mGivenInsetsPending;
7928 }
7929
7930 public Rect getGivenContentInsetsLw() {
7931 return mGivenContentInsets;
7932 }
Romain Guy06882f82009-06-10 13:36:04 -07007933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007934 public Rect getGivenVisibleInsetsLw() {
7935 return mGivenVisibleInsets;
7936 }
Romain Guy06882f82009-06-10 13:36:04 -07007937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007938 public WindowManager.LayoutParams getAttrs() {
7939 return mAttrs;
7940 }
7941
7942 public int getSurfaceLayer() {
7943 return mLayer;
7944 }
Romain Guy06882f82009-06-10 13:36:04 -07007945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946 public IApplicationToken getAppToken() {
7947 return mAppToken != null ? mAppToken.appToken : null;
7948 }
7949
7950 public boolean hasAppShownWindows() {
7951 return mAppToken != null ? mAppToken.firstWindowDrawn : false;
7952 }
7953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007954 public void setAnimation(Animation anim) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007955 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007956 TAG, "Setting animation in " + this + ": " + anim);
7957 mAnimating = false;
7958 mLocalAnimating = false;
7959 mAnimation = anim;
7960 mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
7961 mAnimation.scaleCurrentDuration(mWindowAnimationScale);
7962 }
7963
7964 public void clearAnimation() {
7965 if (mAnimation != null) {
7966 mAnimating = true;
7967 mLocalAnimating = false;
7968 mAnimation = null;
7969 }
7970 }
Romain Guy06882f82009-06-10 13:36:04 -07007971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007972 Surface createSurfaceLocked() {
7973 if (mSurface == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007974 mReportDestroySurface = false;
7975 mSurfacePendingDestroy = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007976 mDrawPending = true;
7977 mCommitDrawPending = false;
7978 mReadyToShow = false;
7979 if (mAppToken != null) {
7980 mAppToken.allDrawn = false;
7981 }
7982
7983 int flags = 0;
Mathias Agopian317a6282009-08-13 17:29:02 -07007984 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007985 flags |= Surface.PUSH_BUFFERS;
7986 }
7987
7988 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
7989 flags |= Surface.SECURE;
7990 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007991 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007992 TAG, "Creating surface in session "
7993 + mSession.mSurfaceSession + " window " + this
7994 + " w=" + mFrame.width()
7995 + " h=" + mFrame.height() + " format="
7996 + mAttrs.format + " flags=" + flags);
7997
7998 int w = mFrame.width();
7999 int h = mFrame.height();
8000 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
8001 // for a scaled surface, we always want the requested
8002 // size.
8003 w = mRequestedWidth;
8004 h = mRequestedHeight;
8005 }
8006
Romain Guy9825ec62009-10-01 00:58:09 -07008007 // Something is wrong and SurfaceFlinger will not like this,
8008 // try to revert to sane values
8009 if (w <= 0) w = 1;
8010 if (h <= 0) h = 1;
8011
Dianne Hackborn16064f92010-03-25 00:47:24 -07008012 mSurfaceShown = false;
8013 mSurfaceLayer = 0;
8014 mSurfaceAlpha = 1;
8015 mSurfaceX = 0;
8016 mSurfaceY = 0;
8017 mSurfaceW = w;
8018 mSurfaceH = h;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008019 try {
8020 mSurface = new Surface(
Romain Guy06882f82009-06-10 13:36:04 -07008021 mSession.mSurfaceSession, mSession.mPid,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -08008022 mAttrs.getTitle().toString(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008023 0, w, h, mAttrs.format, flags);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008024 if (SHOW_TRANSACTIONS) Slog.i(TAG, " CREATE SURFACE "
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07008025 + mSurface + " IN SESSION "
8026 + mSession.mSurfaceSession
8027 + ": pid=" + mSession.mPid + " format="
8028 + mAttrs.format + " flags=0x"
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008029 + Integer.toHexString(flags)
8030 + " / " + this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008031 } catch (Surface.OutOfResourcesException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008032 Slog.w(TAG, "OutOfResourcesException creating surface");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008033 reclaimSomeSurfaceMemoryLocked(this, "create");
8034 return null;
8035 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008036 Slog.e(TAG, "Exception creating surface", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 return null;
8038 }
Romain Guy06882f82009-06-10 13:36:04 -07008039
Joe Onorato8a9b2202010-02-26 18:56:32 -08008040 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 TAG, "Got surface: " + mSurface
8042 + ", set left=" + mFrame.left + " top=" + mFrame.top
8043 + ", animLayer=" + mAnimLayer);
8044 if (SHOW_TRANSACTIONS) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008045 Slog.i(TAG, ">>> OPEN TRANSACTION");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008046 if (SHOW_TRANSACTIONS) logSurface(this,
8047 "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
8048 mFrame.width() + "x" + mFrame.height() + "), layer=" +
8049 mAnimLayer + " HIDE", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008050 }
8051 Surface.openTransaction();
8052 try {
8053 try {
Dianne Hackborn16064f92010-03-25 00:47:24 -07008054 mSurfaceX = mFrame.left + mXOffset;
Dianne Hackborn529bef62010-03-25 11:48:43 -07008055 mSurfaceY = mFrame.top + mYOffset;
Dianne Hackborn16064f92010-03-25 00:47:24 -07008056 mSurface.setPosition(mSurfaceX, mSurfaceY);
8057 mSurfaceLayer = mAnimLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008058 mSurface.setLayer(mAnimLayer);
Dianne Hackborn16064f92010-03-25 00:47:24 -07008059 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008060 mSurface.hide();
8061 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008062 if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008063 mSurface.setFlags(Surface.SURFACE_DITHER,
8064 Surface.SURFACE_DITHER);
8065 }
8066 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008067 Slog.w(TAG, "Error creating surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008068 reclaimSomeSurfaceMemoryLocked(this, "create-init");
8069 }
8070 mLastHidden = true;
8071 } finally {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008072 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008073 Surface.closeTransaction();
8074 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008075 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008076 TAG, "Created surface " + this);
8077 }
8078 return mSurface;
8079 }
Romain Guy06882f82009-06-10 13:36:04 -07008080
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008081 void destroySurfaceLocked() {
8082 // Window is no longer on-screen, so can no longer receive
8083 // key events... if we were waiting for it to finish
8084 // handling a key event, the wait is over!
8085 mKeyWaiter.finishedKey(mSession, mClient, true,
8086 KeyWaiter.RETURN_NOTHING);
8087 mKeyWaiter.releasePendingPointerLocked(mSession);
8088 mKeyWaiter.releasePendingTrackballLocked(mSession);
8089
8090 if (mAppToken != null && this == mAppToken.startingWindow) {
8091 mAppToken.startingDisplayed = false;
8092 }
Romain Guy06882f82009-06-10 13:36:04 -07008093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008094 if (mSurface != null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008095 mDrawPending = false;
8096 mCommitDrawPending = false;
8097 mReadyToShow = false;
8098
8099 int i = mChildWindows.size();
8100 while (i > 0) {
8101 i--;
8102 WindowState c = (WindowState)mChildWindows.get(i);
8103 c.mAttachedHidden = true;
8104 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008105
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008106 if (mReportDestroySurface) {
8107 mReportDestroySurface = false;
8108 mSurfacePendingDestroy = true;
8109 try {
8110 mClient.dispatchGetNewSurface();
8111 // We'll really destroy on the next time around.
8112 return;
8113 } catch (RemoteException e) {
8114 }
8115 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008118 if (DEBUG_VISIBILITY) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008119 RuntimeException e = null;
8120 if (!HIDE_STACK_CRAWLS) {
8121 e = new RuntimeException();
8122 e.fillInStackTrace();
8123 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008124 Slog.w(TAG, "Window " + this + " destroying surface "
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008125 + mSurface + ", session " + mSession, e);
8126 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008127 if (SHOW_TRANSACTIONS) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008128 RuntimeException e = null;
8129 if (!HIDE_STACK_CRAWLS) {
8130 e = new RuntimeException();
8131 e.fillInStackTrace();
8132 }
8133 if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008134 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07008135 mSurface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008136 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008137 Slog.w(TAG, "Exception thrown when destroying Window " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008138 + " surface " + mSurface + " session " + mSession
8139 + ": " + e.toString());
8140 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008141
Dianne Hackborn16064f92010-03-25 00:47:24 -07008142 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008143 mSurface = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008144 }
8145 }
8146
8147 boolean finishDrawingLocked() {
8148 if (mDrawPending) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008149 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008150 TAG, "finishDrawingLocked: " + mSurface);
8151 mCommitDrawPending = true;
8152 mDrawPending = false;
8153 return true;
8154 }
8155 return false;
8156 }
8157
8158 // This must be called while inside a transaction.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07008159 boolean commitFinishDrawingLocked(long currentTime) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008160 //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008161 if (!mCommitDrawPending) {
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07008162 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008163 }
8164 mCommitDrawPending = false;
8165 mReadyToShow = true;
8166 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
8167 final AppWindowToken atoken = mAppToken;
8168 if (atoken == null || atoken.allDrawn || starting) {
8169 performShowLocked();
8170 }
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07008171 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008172 }
8173
8174 // This must be called while inside a transaction.
8175 boolean performShowLocked() {
8176 if (DEBUG_VISIBILITY) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008177 RuntimeException e = null;
8178 if (!HIDE_STACK_CRAWLS) {
8179 e = new RuntimeException();
8180 e.fillInStackTrace();
8181 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008182 Slog.v(TAG, "performShow on " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008183 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
8184 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
8185 }
8186 if (mReadyToShow && isReadyForDisplay()) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008187 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this,
8188 "SHOW (performShowLocked)", null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008189 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008190 + " during animation: policyVis=" + mPolicyVisibility
8191 + " attHidden=" + mAttachedHidden
8192 + " tok.hiddenRequested="
8193 + (mAppToken != null ? mAppToken.hiddenRequested : false)
Dianne Hackborn248b1882009-09-16 16:46:44 -07008194 + " tok.hidden="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008195 + (mAppToken != null ? mAppToken.hidden : false)
8196 + " animating=" + mAnimating
8197 + " tok animating="
8198 + (mAppToken != null ? mAppToken.animating : false));
8199 if (!showSurfaceRobustlyLocked(this)) {
8200 return false;
8201 }
8202 mLastAlpha = -1;
8203 mHasDrawn = true;
8204 mLastHidden = false;
8205 mReadyToShow = false;
8206 enableScreenIfNeededLocked();
8207
8208 applyEnterAnimationLocked(this);
Romain Guy06882f82009-06-10 13:36:04 -07008209
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008210 int i = mChildWindows.size();
8211 while (i > 0) {
8212 i--;
8213 WindowState c = (WindowState)mChildWindows.get(i);
Dianne Hackbornf09c1a22010-04-22 15:59:21 -07008214 if (c.mAttachedHidden) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008215 c.mAttachedHidden = false;
Dianne Hackbornf09c1a22010-04-22 15:59:21 -07008216 if (c.mSurface != null) {
8217 c.performShowLocked();
8218 // It hadn't been shown, which means layout not
8219 // performed on it, so now we want to make sure to
8220 // do a layout. If called from within the transaction
8221 // loop, this will cause it to restart with a new
8222 // layout.
8223 mLayoutNeeded = true;
8224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008225 }
8226 }
Romain Guy06882f82009-06-10 13:36:04 -07008227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008228 if (mAttrs.type != TYPE_APPLICATION_STARTING
8229 && mAppToken != null) {
8230 mAppToken.firstWindowDrawn = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008231
Dianne Hackborn248b1882009-09-16 16:46:44 -07008232 if (mAppToken.startingData != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008233 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG,
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07008234 "Finish starting " + mToken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008235 + ": first real window is shown, no animation");
Dianne Hackborn248b1882009-09-16 16:46:44 -07008236 // If this initial window is animating, stop it -- we
8237 // will do an animation to reveal it from behind the
8238 // starting window, so there is no need for it to also
8239 // be doing its own stuff.
8240 if (mAnimation != null) {
8241 mAnimation = null;
8242 // Make sure we clean up the animation.
8243 mAnimating = true;
8244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008245 mFinishedStarting.add(mAppToken);
8246 mH.sendEmptyMessage(H.FINISHED_STARTING);
8247 }
8248 mAppToken.updateReportedVisibilityLocked();
8249 }
8250 }
8251 return true;
8252 }
Romain Guy06882f82009-06-10 13:36:04 -07008253
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008254 // This must be called while inside a transaction. Returns true if
8255 // there is more animation to run.
8256 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -08008257 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008258 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07008259
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008260 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
8261 mHasTransformation = true;
8262 mHasLocalTransformation = true;
8263 if (!mLocalAnimating) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008264 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008265 TAG, "Starting animation in " + this +
8266 " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
8267 " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
8268 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
8269 mAnimation.setStartTime(currentTime);
8270 mLocalAnimating = true;
8271 mAnimating = true;
8272 }
8273 mTransformation.clear();
8274 final boolean more = mAnimation.getTransformation(
8275 currentTime, mTransformation);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008276 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008277 TAG, "Stepped animation in " + this +
8278 ": more=" + more + ", xform=" + mTransformation);
8279 if (more) {
8280 // we're not done!
8281 return true;
8282 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008283 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008284 TAG, "Finished animation in " + this +
8285 " @ " + currentTime);
8286 mAnimation = null;
8287 //WindowManagerService.this.dump();
8288 }
8289 mHasLocalTransformation = false;
8290 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008291 && mAppToken.animation != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008292 // When our app token is animating, we kind-of pretend like
8293 // we are as well. Note the mLocalAnimating mAnimationIsEntrance
8294 // part of this check means that we will only do this if
8295 // our window is not currently exiting, or it is not
8296 // locally animating itself. The idea being that one that
8297 // is exiting and doing a local animation should be removed
8298 // once that animation is done.
8299 mAnimating = true;
8300 mHasTransformation = true;
8301 mTransformation.clear();
8302 return false;
8303 } else if (mHasTransformation) {
8304 // Little trick to get through the path below to act like
8305 // we have finished an animation.
8306 mAnimating = true;
8307 } else if (isAnimating()) {
8308 mAnimating = true;
8309 }
8310 } else if (mAnimation != null) {
8311 // If the display is frozen, and there is a pending animation,
8312 // clear it and make sure we run the cleanup code.
8313 mAnimating = true;
8314 mLocalAnimating = true;
8315 mAnimation = null;
8316 }
Romain Guy06882f82009-06-10 13:36:04 -07008317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008318 if (!mAnimating && !mLocalAnimating) {
8319 return false;
8320 }
8321
Joe Onorato8a9b2202010-02-26 18:56:32 -08008322 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008323 TAG, "Animation done in " + this + ": exiting=" + mExiting
8324 + ", reportedVisible="
8325 + (mAppToken != null ? mAppToken.reportedVisible : false));
Romain Guy06882f82009-06-10 13:36:04 -07008326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008327 mAnimating = false;
8328 mLocalAnimating = false;
8329 mAnimation = null;
8330 mAnimLayer = mLayer;
8331 if (mIsImWindow) {
8332 mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008333 } else if (mIsWallpaper) {
8334 mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008335 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008336 if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008337 + " anim layer: " + mAnimLayer);
8338 mHasTransformation = false;
8339 mHasLocalTransformation = false;
Dianne Hackbornb601ce12010-03-01 23:36:02 -08008340 if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
8341 if (DEBUG_VISIBILITY) {
8342 Slog.v(TAG, "Policy visibility changing after anim in " + this + ": "
8343 + mPolicyVisibilityAfterAnim);
8344 }
8345 mPolicyVisibility = mPolicyVisibilityAfterAnim;
8346 if (!mPolicyVisibility) {
8347 if (mCurrentFocus == this) {
8348 mFocusMayChange = true;
8349 }
8350 // Window is no longer visible -- make sure if we were waiting
8351 // for it to be displayed before enabling the display, that
8352 // we allow the display to be enabled now.
8353 enableScreenIfNeededLocked();
8354 }
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -08008355 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008356 mTransformation.clear();
8357 if (mHasDrawn
8358 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
8359 && mAppToken != null
8360 && mAppToken.firstWindowDrawn
8361 && mAppToken.startingData != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008362 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008363 + mToken + ": first real window done animating");
8364 mFinishedStarting.add(mAppToken);
8365 mH.sendEmptyMessage(H.FINISHED_STARTING);
8366 }
Romain Guy06882f82009-06-10 13:36:04 -07008367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008368 finishExit();
8369
8370 if (mAppToken != null) {
8371 mAppToken.updateReportedVisibilityLocked();
8372 }
8373
8374 return false;
8375 }
8376
8377 void finishExit() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008378 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008379 TAG, "finishExit in " + this
8380 + ": exiting=" + mExiting
8381 + " remove=" + mRemoveOnExit
8382 + " windowAnimating=" + isWindowAnimating());
Romain Guy06882f82009-06-10 13:36:04 -07008383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008384 final int N = mChildWindows.size();
8385 for (int i=0; i<N; i++) {
8386 ((WindowState)mChildWindows.get(i)).finishExit();
8387 }
Romain Guy06882f82009-06-10 13:36:04 -07008388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008389 if (!mExiting) {
8390 return;
8391 }
Romain Guy06882f82009-06-10 13:36:04 -07008392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008393 if (isWindowAnimating()) {
8394 return;
8395 }
8396
Joe Onorato8a9b2202010-02-26 18:56:32 -08008397 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008398 TAG, "Exit animation finished in " + this
8399 + ": remove=" + mRemoveOnExit);
8400 if (mSurface != null) {
8401 mDestroySurface.add(this);
8402 mDestroying = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008403 if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null);
Dianne Hackborn16064f92010-03-25 00:47:24 -07008404 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008405 try {
8406 mSurface.hide();
8407 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008408 Slog.w(TAG, "Error hiding surface in " + this, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008409 }
8410 mLastHidden = true;
8411 mKeyWaiter.releasePendingPointerLocked(mSession);
8412 }
8413 mExiting = false;
8414 if (mRemoveOnExit) {
8415 mPendingRemove.add(this);
8416 mRemoveOnExit = false;
8417 }
8418 }
Romain Guy06882f82009-06-10 13:36:04 -07008419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008420 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
8421 if (dsdx < .99999f || dsdx > 1.00001f) return false;
8422 if (dtdy < .99999f || dtdy > 1.00001f) return false;
8423 if (dtdx < -.000001f || dtdx > .000001f) return false;
8424 if (dsdy < -.000001f || dsdy > .000001f) return false;
8425 return true;
8426 }
Romain Guy06882f82009-06-10 13:36:04 -07008427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008428 void computeShownFrameLocked() {
8429 final boolean selfTransformation = mHasLocalTransformation;
8430 Transformation attachedTransformation =
8431 (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
8432 ? mAttachedWindow.mTransformation : null;
8433 Transformation appTransformation =
8434 (mAppToken != null && mAppToken.hasTransformation)
8435 ? mAppToken.transformation : null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008436
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008437 // Wallpapers are animated based on the "real" window they
8438 // are currently targeting.
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008439 if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07008440 && mWallpaperTarget != null) {
Dianne Hackborn5baba162009-09-23 17:01:12 -07008441 if (mWallpaperTarget.mHasLocalTransformation &&
8442 mWallpaperTarget.mAnimation != null &&
8443 !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008444 attachedTransformation = mWallpaperTarget.mTransformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07008445 if (DEBUG_WALLPAPER && attachedTransformation != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008446 Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
Dianne Hackborn5baba162009-09-23 17:01:12 -07008447 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008448 }
8449 if (mWallpaperTarget.mAppToken != null &&
Dianne Hackborn5baba162009-09-23 17:01:12 -07008450 mWallpaperTarget.mAppToken.hasTransformation &&
8451 mWallpaperTarget.mAppToken.animation != null &&
8452 !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008453 appTransformation = mWallpaperTarget.mAppToken.transformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07008454 if (DEBUG_WALLPAPER && appTransformation != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008455 Slog.v(TAG, "WP target app xform: " + appTransformation);
Dianne Hackborn5baba162009-09-23 17:01:12 -07008456 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008457 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008458 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008460 if (selfTransformation || attachedTransformation != null
8461 || appTransformation != null) {
Romain Guy06882f82009-06-10 13:36:04 -07008462 // cache often used attributes locally
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 final Rect frame = mFrame;
8464 final float tmpFloats[] = mTmpFloats;
8465 final Matrix tmpMatrix = mTmpMatrix;
8466
8467 // Compute the desired transformation.
Dianne Hackborn65c23872009-09-18 17:47:02 -07008468 tmpMatrix.setTranslate(0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008469 if (selfTransformation) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07008470 tmpMatrix.postConcat(mTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008471 }
Dianne Hackborn65c23872009-09-18 17:47:02 -07008472 tmpMatrix.postTranslate(frame.left, frame.top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008473 if (attachedTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07008474 tmpMatrix.postConcat(attachedTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008475 }
8476 if (appTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07008477 tmpMatrix.postConcat(appTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008478 }
8479
8480 // "convert" it into SurfaceFlinger's format
8481 // (a 2x2 matrix + an offset)
8482 // Here we must not transform the position of the surface
8483 // since it is already included in the transformation.
Joe Onorato8a9b2202010-02-26 18:56:32 -08008484 //Slog.i(TAG, "Transform: " + matrix);
Romain Guy06882f82009-06-10 13:36:04 -07008485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 tmpMatrix.getValues(tmpFloats);
8487 mDsDx = tmpFloats[Matrix.MSCALE_X];
8488 mDtDx = tmpFloats[Matrix.MSKEW_X];
8489 mDsDy = tmpFloats[Matrix.MSKEW_Y];
8490 mDtDy = tmpFloats[Matrix.MSCALE_Y];
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008491 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
8492 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 int w = frame.width();
8494 int h = frame.height();
8495 mShownFrame.set(x, y, x+w, y+h);
8496
8497 // Now set the alpha... but because our current hardware
8498 // can't do alpha transformation on a non-opaque surface,
8499 // turn it off if we are running an animation that is also
8500 // transforming since it is more important to have that
8501 // animation be smooth.
8502 mShownAlpha = mAlpha;
8503 if (!mLimitedAlphaCompositing
8504 || (!PixelFormat.formatHasAlpha(mAttrs.format)
8505 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
8506 && x == frame.left && y == frame.top))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008507 //Slog.i(TAG, "Applying alpha transform");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008508 if (selfTransformation) {
8509 mShownAlpha *= mTransformation.getAlpha();
8510 }
8511 if (attachedTransformation != null) {
8512 mShownAlpha *= attachedTransformation.getAlpha();
8513 }
8514 if (appTransformation != null) {
8515 mShownAlpha *= appTransformation.getAlpha();
8516 }
8517 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008518 //Slog.i(TAG, "Not applying alpha transform");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008519 }
Romain Guy06882f82009-06-10 13:36:04 -07008520
Joe Onorato8a9b2202010-02-26 18:56:32 -08008521 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 TAG, "Continuing animation in " + this +
8523 ": " + mShownFrame +
8524 ", alpha=" + mTransformation.getAlpha());
8525 return;
8526 }
Romain Guy06882f82009-06-10 13:36:04 -07008527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 mShownFrame.set(mFrame);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008529 if (mXOffset != 0 || mYOffset != 0) {
8530 mShownFrame.offset(mXOffset, mYOffset);
8531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008532 mShownAlpha = mAlpha;
8533 mDsDx = 1;
8534 mDtDx = 0;
8535 mDsDy = 0;
8536 mDtDy = 1;
8537 }
Romain Guy06882f82009-06-10 13:36:04 -07008538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008539 /**
8540 * Is this window visible? It is not visible if there is no
8541 * surface, or we are in the process of running an exit animation
8542 * that will remove the surface, or its app token has been hidden.
8543 */
8544 public boolean isVisibleLw() {
8545 final AppWindowToken atoken = mAppToken;
8546 return mSurface != null && mPolicyVisibility && !mAttachedHidden
8547 && (atoken == null || !atoken.hiddenRequested)
8548 && !mExiting && !mDestroying;
8549 }
8550
8551 /**
Dianne Hackborn3d163f072009-10-07 21:26:57 -07008552 * Like {@link #isVisibleLw}, but also counts a window that is currently
8553 * "hidden" behind the keyguard as visible. This allows us to apply
8554 * things like window flags that impact the keyguard.
8555 * XXX I am starting to think we need to have ANOTHER visibility flag
8556 * for this "hidden behind keyguard" state rather than overloading
8557 * mPolicyVisibility. Ungh.
8558 */
8559 public boolean isVisibleOrBehindKeyguardLw() {
8560 final AppWindowToken atoken = mAppToken;
8561 return mSurface != null && !mAttachedHidden
8562 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008563 && !mDrawPending && !mCommitDrawPending
Dianne Hackborn3d163f072009-10-07 21:26:57 -07008564 && !mExiting && !mDestroying;
8565 }
8566
8567 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008568 * Is this window visible, ignoring its app token? It is not visible
8569 * if there is no surface, or we are in the process of running an exit animation
8570 * that will remove the surface.
8571 */
8572 public boolean isWinVisibleLw() {
8573 final AppWindowToken atoken = mAppToken;
8574 return mSurface != null && mPolicyVisibility && !mAttachedHidden
8575 && (atoken == null || !atoken.hiddenRequested || atoken.animating)
8576 && !mExiting && !mDestroying;
8577 }
8578
8579 /**
8580 * The same as isVisible(), but follows the current hidden state of
8581 * the associated app token, not the pending requested hidden state.
8582 */
8583 boolean isVisibleNow() {
8584 return mSurface != null && mPolicyVisibility && !mAttachedHidden
The Android Open Source Project10592532009-03-18 17:39:46 -07008585 && !mRootToken.hidden && !mExiting && !mDestroying;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008586 }
8587
8588 /**
8589 * Same as isVisible(), but we also count it as visible between the
8590 * call to IWindowSession.add() and the first relayout().
8591 */
8592 boolean isVisibleOrAdding() {
8593 final AppWindowToken atoken = mAppToken;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008594 return ((mSurface != null && !mReportDestroySurface)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008595 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
8596 && mPolicyVisibility && !mAttachedHidden
8597 && (atoken == null || !atoken.hiddenRequested)
8598 && !mExiting && !mDestroying;
8599 }
8600
8601 /**
8602 * Is this window currently on-screen? It is on-screen either if it
8603 * is visible or it is currently running an animation before no longer
8604 * being visible.
8605 */
8606 boolean isOnScreen() {
8607 final AppWindowToken atoken = mAppToken;
8608 if (atoken != null) {
8609 return mSurface != null && mPolicyVisibility && !mDestroying
8610 && ((!mAttachedHidden && !atoken.hiddenRequested)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008611 || mAnimation != null || atoken.animation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008612 } else {
8613 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008614 && (!mAttachedHidden || mAnimation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008615 }
8616 }
Romain Guy06882f82009-06-10 13:36:04 -07008617
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008618 /**
8619 * Like isOnScreen(), but we don't return true if the window is part
8620 * of a transition that has not yet been started.
8621 */
8622 boolean isReadyForDisplay() {
Dianne Hackborna8f60182009-09-01 19:01:50 -07008623 if (mRootToken.waitingToShow &&
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07008624 mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07008625 return false;
8626 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008627 final AppWindowToken atoken = mAppToken;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008628 final boolean animating = atoken != null
8629 ? (atoken.animation != null) : false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008630 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008631 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
8632 && !mRootToken.hidden)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008633 || mAnimation != null || animating);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008634 }
8635
8636 /** Is the window or its container currently animating? */
8637 boolean isAnimating() {
8638 final WindowState attached = mAttachedWindow;
8639 final AppWindowToken atoken = mAppToken;
8640 return mAnimation != null
8641 || (attached != null && attached.mAnimation != null)
Romain Guy06882f82009-06-10 13:36:04 -07008642 || (atoken != null &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008643 (atoken.animation != null
8644 || atoken.inPendingTransaction));
8645 }
8646
8647 /** Is this window currently animating? */
8648 boolean isWindowAnimating() {
8649 return mAnimation != null;
8650 }
8651
8652 /**
8653 * Like isOnScreen, but returns false if the surface hasn't yet
8654 * been drawn.
8655 */
8656 public boolean isDisplayedLw() {
8657 final AppWindowToken atoken = mAppToken;
8658 return mSurface != null && mPolicyVisibility && !mDestroying
8659 && !mDrawPending && !mCommitDrawPending
8660 && ((!mAttachedHidden &&
8661 (atoken == null || !atoken.hiddenRequested))
8662 || mAnimating);
8663 }
8664
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008665 /**
8666 * Returns true if the window has a surface that it has drawn a
8667 * complete UI in to.
8668 */
8669 public boolean isDrawnLw() {
8670 final AppWindowToken atoken = mAppToken;
8671 return mSurface != null && !mDestroying
8672 && !mDrawPending && !mCommitDrawPending;
8673 }
8674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008675 public boolean fillsScreenLw(int screenWidth, int screenHeight,
8676 boolean shownFrame, boolean onlyOpaque) {
8677 if (mSurface == null) {
8678 return false;
8679 }
8680 if (mAppToken != null && !mAppToken.appFullscreen) {
8681 return false;
8682 }
8683 if (onlyOpaque && mAttrs.format != PixelFormat.OPAQUE) {
8684 return false;
8685 }
8686 final Rect frame = shownFrame ? mShownFrame : mFrame;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008687
8688 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
8689 return frame.left <= mCompatibleScreenFrame.left &&
8690 frame.top <= mCompatibleScreenFrame.top &&
8691 frame.right >= mCompatibleScreenFrame.right &&
8692 frame.bottom >= mCompatibleScreenFrame.bottom;
8693 } else {
8694 return frame.left <= 0 && frame.top <= 0
8695 && frame.right >= screenWidth
8696 && frame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008697 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008698 }
Romain Guy06882f82009-06-10 13:36:04 -07008699
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008700 /**
Dianne Hackborn25994b42009-09-04 14:21:19 -07008701 * Return true if the window is opaque and fully drawn. This indicates
8702 * it may obscure windows behind it.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008703 */
8704 boolean isOpaqueDrawn() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07008705 return (mAttrs.format == PixelFormat.OPAQUE
8706 || mAttrs.type == TYPE_WALLPAPER)
8707 && mSurface != null && mAnimation == null
8708 && (mAppToken == null || mAppToken.animation == null)
8709 && !mDrawPending && !mCommitDrawPending;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008710 }
8711
8712 boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
8713 return
8714 // only if the application is requesting compatible window
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008715 (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
8716 // only if it's visible
8717 mHasDrawn && mViewVisibility == View.VISIBLE &&
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008718 // and only if the application fills the compatible screen
8719 mFrame.left <= mCompatibleScreenFrame.left &&
8720 mFrame.top <= mCompatibleScreenFrame.top &&
8721 mFrame.right >= mCompatibleScreenFrame.right &&
8722 mFrame.bottom >= mCompatibleScreenFrame.bottom &&
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008723 // and starting window do not need background filler
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008724 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008725 }
8726
8727 boolean isFullscreen(int screenWidth, int screenHeight) {
8728 return mFrame.left <= 0 && mFrame.top <= 0 &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07008729 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008730 }
8731
8732 void removeLocked() {
8733 if (mAttachedWindow != null) {
8734 mAttachedWindow.mChildWindows.remove(this);
8735 }
8736 destroySurfaceLocked();
8737 mSession.windowRemovedLocked();
8738 try {
8739 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
8740 } catch (RuntimeException e) {
8741 // Ignore if it has already been removed (usually because
8742 // we are doing this as part of processing a death note.)
8743 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07008744
8745 if (ENABLE_NATIVE_INPUT_DISPATCH) {
8746 if (mInputChannel != null) {
8747 mInputManager.unregisterInputChannel(mInputChannel);
8748
8749 mInputChannel.dispose();
8750 mInputChannel = null;
8751 }
8752 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008753 }
8754
8755 private class DeathRecipient implements IBinder.DeathRecipient {
8756 public void binderDied() {
8757 try {
8758 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008759 WindowState win = windowForClientLocked(mSession, mClient, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008760 Slog.i(TAG, "WIN DEATH: " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008761 if (win != null) {
8762 removeWindowLocked(mSession, win);
8763 }
8764 }
8765 } catch (IllegalArgumentException ex) {
8766 // This will happen if the window has already been
8767 // removed.
8768 }
8769 }
8770 }
8771
8772 /** Returns true if this window desires key events. */
8773 public final boolean canReceiveKeys() {
8774 return isVisibleOrAdding()
8775 && (mViewVisibility == View.VISIBLE)
8776 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
8777 }
8778
8779 public boolean hasDrawnLw() {
8780 return mHasDrawn;
8781 }
8782
8783 public boolean showLw(boolean doAnimation) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008784 return showLw(doAnimation, true);
8785 }
8786
8787 boolean showLw(boolean doAnimation, boolean requestAnim) {
8788 if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
8789 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008790 }
Dianne Hackbornb601ce12010-03-01 23:36:02 -08008791 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008792 if (doAnimation) {
8793 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
8794 + mPolicyVisibility + " mAnimation=" + mAnimation);
8795 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8796 doAnimation = false;
8797 } else if (mPolicyVisibility && mAnimation == null) {
8798 // Check for the case where we are currently visible and
8799 // not animating; we do not want to do animation at such a
8800 // point to become visible when we already are.
8801 doAnimation = false;
8802 }
8803 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008804 mPolicyVisibility = true;
8805 mPolicyVisibilityAfterAnim = true;
8806 if (doAnimation) {
8807 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
8808 }
8809 if (requestAnim) {
8810 requestAnimationLocked(0);
8811 }
8812 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008813 }
8814
8815 public boolean hideLw(boolean doAnimation) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008816 return hideLw(doAnimation, true);
8817 }
8818
8819 boolean hideLw(boolean doAnimation, boolean requestAnim) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008820 if (doAnimation) {
8821 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8822 doAnimation = false;
8823 }
8824 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008825 boolean current = doAnimation ? mPolicyVisibilityAfterAnim
8826 : mPolicyVisibility;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008827 if (!current) {
8828 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008829 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008830 if (doAnimation) {
8831 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
8832 if (mAnimation == null) {
8833 doAnimation = false;
8834 }
8835 }
8836 if (doAnimation) {
8837 mPolicyVisibilityAfterAnim = false;
8838 } else {
Dianne Hackbornb601ce12010-03-01 23:36:02 -08008839 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008840 mPolicyVisibilityAfterAnim = false;
8841 mPolicyVisibility = false;
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -08008842 // Window is no longer visible -- make sure if we were waiting
8843 // for it to be displayed before enabling the display, that
8844 // we allow the display to be enabled now.
8845 enableScreenIfNeededLocked();
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008846 if (mCurrentFocus == this) {
8847 mFocusMayChange = true;
8848 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008849 }
8850 if (requestAnim) {
8851 requestAnimationLocked(0);
8852 }
8853 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008854 }
8855
8856 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008857 pw.print(prefix); pw.print("mSession="); pw.print(mSession);
8858 pw.print(" mClient="); pw.println(mClient.asBinder());
8859 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
8860 if (mAttachedWindow != null || mLayoutAttached) {
8861 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
8862 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
8863 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07008864 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
8865 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
8866 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008867 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
8868 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008869 }
8870 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
8871 pw.print(" mSubLayer="); pw.print(mSubLayer);
8872 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
8873 pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
8874 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
8875 pw.print("="); pw.print(mAnimLayer);
8876 pw.print(" mLastLayer="); pw.println(mLastLayer);
8877 if (mSurface != null) {
8878 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
Dianne Hackborn16064f92010-03-25 00:47:24 -07008879 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
8880 pw.print(" layer="); pw.print(mSurfaceLayer);
8881 pw.print(" alpha="); pw.print(mSurfaceAlpha);
8882 pw.print(" rect=("); pw.print(mSurfaceX);
8883 pw.print(","); pw.print(mSurfaceY);
8884 pw.print(") "); pw.print(mSurfaceW);
8885 pw.print(" x "); pw.println(mSurfaceH);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008886 }
8887 pw.print(prefix); pw.print("mToken="); pw.println(mToken);
8888 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
8889 if (mAppToken != null) {
8890 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
8891 }
8892 if (mTargetAppToken != null) {
8893 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
8894 }
8895 pw.print(prefix); pw.print("mViewVisibility=0x");
8896 pw.print(Integer.toHexString(mViewVisibility));
8897 pw.print(" mLastHidden="); pw.print(mLastHidden);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008898 pw.print(" mHaveFrame="); pw.print(mHaveFrame);
8899 pw.print(" mObscured="); pw.println(mObscured);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008900 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
8901 pw.print(prefix); pw.print("mPolicyVisibility=");
8902 pw.print(mPolicyVisibility);
8903 pw.print(" mPolicyVisibilityAfterAnim=");
8904 pw.print(mPolicyVisibilityAfterAnim);
8905 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
8906 }
Dianne Hackborn9b52a212009-12-11 14:51:35 -08008907 if (!mRelayoutCalled) {
8908 pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
8909 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008910 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008911 pw.print(" h="); pw.print(mRequestedHeight);
8912 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008913 if (mXOffset != 0 || mYOffset != 0) {
8914 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
8915 pw.print(" y="); pw.println(mYOffset);
8916 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008917 pw.print(prefix); pw.print("mGivenContentInsets=");
8918 mGivenContentInsets.printShortString(pw);
8919 pw.print(" mGivenVisibleInsets=");
8920 mGivenVisibleInsets.printShortString(pw);
8921 pw.println();
8922 if (mTouchableInsets != 0 || mGivenInsetsPending) {
8923 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
8924 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
8925 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008926 pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008927 pw.print(prefix); pw.print("mShownFrame=");
8928 mShownFrame.printShortString(pw);
8929 pw.print(" last="); mLastShownFrame.printShortString(pw);
8930 pw.println();
8931 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
8932 pw.print(" last="); mLastFrame.printShortString(pw);
8933 pw.println();
8934 pw.print(prefix); pw.print("mContainingFrame=");
8935 mContainingFrame.printShortString(pw);
8936 pw.print(" mDisplayFrame=");
8937 mDisplayFrame.printShortString(pw);
8938 pw.println();
8939 pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
8940 pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
8941 pw.println();
8942 pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
8943 pw.print(" last="); mLastContentInsets.printShortString(pw);
8944 pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
8945 pw.print(" last="); mLastVisibleInsets.printShortString(pw);
8946 pw.println();
8947 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
8948 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
8949 pw.print(" mAlpha="); pw.print(mAlpha);
8950 pw.print(" mLastAlpha="); pw.println(mLastAlpha);
8951 }
8952 if (mAnimating || mLocalAnimating || mAnimationIsEntrance
8953 || mAnimation != null) {
8954 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
8955 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
8956 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
8957 pw.print(" mAnimation="); pw.println(mAnimation);
8958 }
8959 if (mHasTransformation || mHasLocalTransformation) {
8960 pw.print(prefix); pw.print("XForm: has=");
8961 pw.print(mHasTransformation);
8962 pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
8963 pw.print(" "); mTransformation.printShortString(pw);
8964 pw.println();
8965 }
8966 pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
8967 pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
8968 pw.print(" mReadyToShow="); pw.print(mReadyToShow);
8969 pw.print(" mHasDrawn="); pw.println(mHasDrawn);
8970 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
8971 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
8972 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
8973 pw.print(" mDestroying="); pw.print(mDestroying);
8974 pw.print(" mRemoved="); pw.println(mRemoved);
8975 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07008976 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008977 pw.print(prefix); pw.print("mOrientationChanging=");
8978 pw.print(mOrientationChanging);
Dianne Hackborn93e462b2009-09-15 22:50:40 -07008979 pw.print(" mAppFreezing="); pw.print(mAppFreezing);
8980 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008981 }
Mitsuru Oshima589cebe2009-07-22 20:38:58 -07008982 if (mHScale != 1 || mVScale != 1) {
8983 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
8984 pw.print(" mVScale="); pw.println(mVScale);
8985 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07008986 if (mWallpaperX != -1 || mWallpaperY != -1) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008987 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
8988 pw.print(" mWallpaperY="); pw.println(mWallpaperY);
8989 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08008990 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
8991 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
8992 pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
8993 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008994 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07008995
8996 String makeInputChannelName() {
8997 return Integer.toHexString(System.identityHashCode(this))
8998 + " " + mAttrs.getTitle();
8999 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009000
9001 @Override
9002 public String toString() {
9003 return "Window{"
9004 + Integer.toHexString(System.identityHashCode(this))
9005 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
9006 }
9007 }
Romain Guy06882f82009-06-10 13:36:04 -07009008
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009009 // -------------------------------------------------------------
9010 // Window Token State
9011 // -------------------------------------------------------------
9012
9013 class WindowToken {
9014 // The actual token.
9015 final IBinder token;
9016
9017 // The type of window this token is for, as per WindowManager.LayoutParams.
9018 final int windowType;
Romain Guy06882f82009-06-10 13:36:04 -07009019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009020 // Set if this token was explicitly added by a client, so should
9021 // not be removed when all windows are removed.
9022 final boolean explicit;
Romain Guy06882f82009-06-10 13:36:04 -07009023
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009024 // For printing.
9025 String stringName;
Romain Guy06882f82009-06-10 13:36:04 -07009026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009027 // If this is an AppWindowToken, this is non-null.
9028 AppWindowToken appWindowToken;
Romain Guy06882f82009-06-10 13:36:04 -07009029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009030 // All of the windows associated with this token.
9031 final ArrayList<WindowState> windows = new ArrayList<WindowState>();
9032
9033 // Is key dispatching paused for this token?
9034 boolean paused = false;
9035
9036 // Should this token's windows be hidden?
9037 boolean hidden;
9038
9039 // Temporary for finding which tokens no longer have visible windows.
9040 boolean hasVisible;
9041
Dianne Hackborna8f60182009-09-01 19:01:50 -07009042 // Set to true when this token is in a pending transaction where it
9043 // will be shown.
9044 boolean waitingToShow;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009045
Dianne Hackborna8f60182009-09-01 19:01:50 -07009046 // Set to true when this token is in a pending transaction where it
9047 // will be hidden.
9048 boolean waitingToHide;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009049
Dianne Hackborna8f60182009-09-01 19:01:50 -07009050 // Set to true when this token is in a pending transaction where its
9051 // windows will be put to the bottom of the list.
9052 boolean sendingToBottom;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009053
Dianne Hackborna8f60182009-09-01 19:01:50 -07009054 // Set to true when this token is in a pending transaction where its
9055 // windows will be put to the top of the list.
9056 boolean sendingToTop;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009058 WindowToken(IBinder _token, int type, boolean _explicit) {
9059 token = _token;
9060 windowType = type;
9061 explicit = _explicit;
9062 }
9063
9064 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009065 pw.print(prefix); pw.print("token="); pw.println(token);
9066 pw.print(prefix); pw.print("windows="); pw.println(windows);
9067 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
9068 pw.print(" hidden="); pw.print(hidden);
9069 pw.print(" hasVisible="); pw.println(hasVisible);
Dianne Hackborna8f60182009-09-01 19:01:50 -07009070 if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
9071 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
9072 pw.print(" waitingToHide="); pw.print(waitingToHide);
9073 pw.print(" sendingToBottom="); pw.print(sendingToBottom);
9074 pw.print(" sendingToTop="); pw.println(sendingToTop);
9075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009076 }
9077
9078 @Override
9079 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009080 if (stringName == null) {
9081 StringBuilder sb = new StringBuilder();
9082 sb.append("WindowToken{");
9083 sb.append(Integer.toHexString(System.identityHashCode(this)));
9084 sb.append(" token="); sb.append(token); sb.append('}');
9085 stringName = sb.toString();
9086 }
9087 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009088 }
9089 };
9090
9091 class AppWindowToken extends WindowToken {
9092 // Non-null only for application tokens.
9093 final IApplicationToken appToken;
9094
9095 // All of the windows and child windows that are included in this
9096 // application token. Note this list is NOT sorted!
9097 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
9098
9099 int groupId = -1;
9100 boolean appFullscreen;
9101 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Romain Guy06882f82009-06-10 13:36:04 -07009102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009103 // These are used for determining when all windows associated with
9104 // an activity have been drawn, so they can be made visible together
9105 // at the same time.
9106 int lastTransactionSequence = mTransactionSequence-1;
9107 int numInterestingWindows;
9108 int numDrawnWindows;
9109 boolean inPendingTransaction;
9110 boolean allDrawn;
Romain Guy06882f82009-06-10 13:36:04 -07009111
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009112 // Is this token going to be hidden in a little while? If so, it
9113 // won't be taken into account for setting the screen orientation.
9114 boolean willBeHidden;
Romain Guy06882f82009-06-10 13:36:04 -07009115
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009116 // Is this window's surface needed? This is almost like hidden, except
9117 // it will sometimes be true a little earlier: when the token has
9118 // been shown, but is still waiting for its app transition to execute
9119 // before making its windows shown.
9120 boolean hiddenRequested;
Romain Guy06882f82009-06-10 13:36:04 -07009121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009122 // Have we told the window clients to hide themselves?
9123 boolean clientHidden;
Romain Guy06882f82009-06-10 13:36:04 -07009124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009125 // Last visibility state we reported to the app token.
9126 boolean reportedVisible;
9127
9128 // Set to true when the token has been removed from the window mgr.
9129 boolean removed;
9130
9131 // Have we been asked to have this token keep the screen frozen?
9132 boolean freezingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07009133
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009134 boolean animating;
9135 Animation animation;
9136 boolean hasTransformation;
9137 final Transformation transformation = new Transformation();
Romain Guy06882f82009-06-10 13:36:04 -07009138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009139 // Offset to the window of all layers in the token, for use by
9140 // AppWindowToken animations.
9141 int animLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -07009142
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009143 // Information about an application starting window if displayed.
9144 StartingData startingData;
9145 WindowState startingWindow;
9146 View startingView;
9147 boolean startingDisplayed;
9148 boolean startingMoved;
9149 boolean firstWindowDrawn;
9150
9151 AppWindowToken(IApplicationToken _token) {
9152 super(_token.asBinder(),
9153 WindowManager.LayoutParams.TYPE_APPLICATION, true);
9154 appWindowToken = this;
9155 appToken = _token;
9156 }
Romain Guy06882f82009-06-10 13:36:04 -07009157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 public void setAnimation(Animation anim) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009159 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009160 TAG, "Setting animation in " + this + ": " + anim);
9161 animation = anim;
9162 animating = false;
9163 anim.restrictDuration(MAX_ANIMATION_DURATION);
9164 anim.scaleCurrentDuration(mTransitionAnimationScale);
9165 int zorder = anim.getZAdjustment();
9166 int adj = 0;
9167 if (zorder == Animation.ZORDER_TOP) {
9168 adj = TYPE_LAYER_OFFSET;
9169 } else if (zorder == Animation.ZORDER_BOTTOM) {
9170 adj = -TYPE_LAYER_OFFSET;
9171 }
Romain Guy06882f82009-06-10 13:36:04 -07009172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009173 if (animLayerAdjustment != adj) {
9174 animLayerAdjustment = adj;
9175 updateLayers();
9176 }
9177 }
Romain Guy06882f82009-06-10 13:36:04 -07009178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009179 public void setDummyAnimation() {
9180 if (animation == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009181 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009182 TAG, "Setting dummy animation in " + this);
9183 animation = sDummyAnimation;
9184 }
9185 }
9186
9187 public void clearAnimation() {
9188 if (animation != null) {
9189 animation = null;
9190 animating = true;
9191 }
9192 }
Romain Guy06882f82009-06-10 13:36:04 -07009193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009194 void updateLayers() {
9195 final int N = allAppWindows.size();
9196 final int adj = animLayerAdjustment;
9197 for (int i=0; i<N; i++) {
9198 WindowState w = allAppWindows.get(i);
9199 w.mAnimLayer = w.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009200 if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009201 + w.mAnimLayer);
9202 if (w == mInputMethodTarget) {
9203 setInputMethodAnimLayerAdjustment(adj);
9204 }
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009205 if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07009206 setWallpaperAnimLayerAdjustmentLocked(adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07009207 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009208 }
9209 }
Romain Guy06882f82009-06-10 13:36:04 -07009210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009211 void sendAppVisibilityToClients() {
9212 final int N = allAppWindows.size();
9213 for (int i=0; i<N; i++) {
9214 WindowState win = allAppWindows.get(i);
9215 if (win == startingWindow && clientHidden) {
9216 // Don't hide the starting window.
9217 continue;
9218 }
9219 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009220 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009221 "Setting visibility of " + win + ": " + (!clientHidden));
9222 win.mClient.dispatchAppVisibility(!clientHidden);
9223 } catch (RemoteException e) {
9224 }
9225 }
9226 }
Romain Guy06882f82009-06-10 13:36:04 -07009227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009228 void showAllWindowsLocked() {
9229 final int NW = allAppWindows.size();
9230 for (int i=0; i<NW; i++) {
9231 WindowState w = allAppWindows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009232 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009233 "performing show on: " + w);
9234 w.performShowLocked();
9235 }
9236 }
Romain Guy06882f82009-06-10 13:36:04 -07009237
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009238 // This must be called while inside a transaction.
9239 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -08009240 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009241 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07009242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009243 if (animation == sDummyAnimation) {
9244 // This guy is going to animate, but not yet. For now count
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009245 // it as not animating for purposes of scheduling transactions;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009246 // when it is really time to animate, this will be set to
9247 // a real animation and the next call will execute normally.
9248 return false;
9249 }
Romain Guy06882f82009-06-10 13:36:04 -07009250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009251 if ((allDrawn || animating || startingDisplayed) && animation != null) {
9252 if (!animating) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009253 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009254 TAG, "Starting animation in " + this +
9255 " @ " + currentTime + ": dw=" + dw + " dh=" + dh
9256 + " scale=" + mTransitionAnimationScale
9257 + " allDrawn=" + allDrawn + " animating=" + animating);
9258 animation.initialize(dw, dh, dw, dh);
9259 animation.setStartTime(currentTime);
9260 animating = true;
9261 }
9262 transformation.clear();
9263 final boolean more = animation.getTransformation(
9264 currentTime, transformation);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009265 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009266 TAG, "Stepped animation in " + this +
9267 ": more=" + more + ", xform=" + transformation);
9268 if (more) {
9269 // we're done!
9270 hasTransformation = true;
9271 return true;
9272 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009273 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009274 TAG, "Finished animation in " + this +
9275 " @ " + currentTime);
9276 animation = null;
9277 }
9278 } else if (animation != null) {
9279 // If the display is frozen, and there is a pending animation,
9280 // clear it and make sure we run the cleanup code.
9281 animating = true;
9282 animation = null;
9283 }
9284
9285 hasTransformation = false;
Romain Guy06882f82009-06-10 13:36:04 -07009286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009287 if (!animating) {
9288 return false;
9289 }
9290
9291 clearAnimation();
9292 animating = false;
9293 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
9294 moveInputMethodWindowsIfNeededLocked(true);
9295 }
Romain Guy06882f82009-06-10 13:36:04 -07009296
Joe Onorato8a9b2202010-02-26 18:56:32 -08009297 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009298 TAG, "Animation done in " + this
9299 + ": reportedVisible=" + reportedVisible);
9300
9301 transformation.clear();
9302 if (animLayerAdjustment != 0) {
9303 animLayerAdjustment = 0;
9304 updateLayers();
9305 }
Romain Guy06882f82009-06-10 13:36:04 -07009306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009307 final int N = windows.size();
9308 for (int i=0; i<N; i++) {
9309 ((WindowState)windows.get(i)).finishExit();
9310 }
9311 updateReportedVisibilityLocked();
Romain Guy06882f82009-06-10 13:36:04 -07009312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009313 return false;
9314 }
9315
9316 void updateReportedVisibilityLocked() {
9317 if (appToken == null) {
9318 return;
9319 }
Romain Guy06882f82009-06-10 13:36:04 -07009320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009321 int numInteresting = 0;
9322 int numVisible = 0;
9323 boolean nowGone = true;
Romain Guy06882f82009-06-10 13:36:04 -07009324
Joe Onorato8a9b2202010-02-26 18:56:32 -08009325 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 final int N = allAppWindows.size();
9327 for (int i=0; i<N; i++) {
9328 WindowState win = allAppWindows.get(i);
Dianne Hackborn6cf67fa2009-12-21 16:46:34 -08009329 if (win == startingWindow || win.mAppFreezing
The Android Open Source Project727cec02010-04-08 11:35:37 -07009330 || win.mViewVisibility != View.VISIBLE
9331 || win.mAttrs.type == TYPE_APPLICATION_STARTING) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009332 continue;
9333 }
9334 if (DEBUG_VISIBILITY) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009335 Slog.v(TAG, "Win " + win + ": isDrawn="
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009336 + win.isDrawnLw()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009337 + ", isAnimating=" + win.isAnimating());
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009338 if (!win.isDrawnLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009339 Slog.v(TAG, "Not displayed: s=" + win.mSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009340 + " pv=" + win.mPolicyVisibility
9341 + " dp=" + win.mDrawPending
9342 + " cdp=" + win.mCommitDrawPending
9343 + " ah=" + win.mAttachedHidden
9344 + " th="
9345 + (win.mAppToken != null
9346 ? win.mAppToken.hiddenRequested : false)
9347 + " a=" + win.mAnimating);
9348 }
9349 }
9350 numInteresting++;
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009351 if (win.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009352 if (!win.isAnimating()) {
9353 numVisible++;
9354 }
9355 nowGone = false;
9356 } else if (win.isAnimating()) {
9357 nowGone = false;
9358 }
9359 }
Romain Guy06882f82009-06-10 13:36:04 -07009360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009361 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009362 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009363 + numInteresting + " visible=" + numVisible);
9364 if (nowVisible != reportedVisible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009365 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009366 TAG, "Visibility changed in " + this
9367 + ": vis=" + nowVisible);
9368 reportedVisible = nowVisible;
9369 Message m = mH.obtainMessage(
9370 H.REPORT_APPLICATION_TOKEN_WINDOWS,
9371 nowVisible ? 1 : 0,
9372 nowGone ? 1 : 0,
9373 this);
9374 mH.sendMessage(m);
9375 }
9376 }
Romain Guy06882f82009-06-10 13:36:04 -07009377
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009378 WindowState findMainWindow() {
9379 int j = windows.size();
9380 while (j > 0) {
9381 j--;
9382 WindowState win = windows.get(j);
9383 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
9384 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
9385 return win;
9386 }
9387 }
9388 return null;
9389 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009391 void dump(PrintWriter pw, String prefix) {
9392 super.dump(pw, prefix);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009393 if (appToken != null) {
9394 pw.print(prefix); pw.println("app=true");
9395 }
9396 if (allAppWindows.size() > 0) {
9397 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
9398 }
9399 pw.print(prefix); pw.print("groupId="); pw.print(groupId);
Dianne Hackborna8f60182009-09-01 19:01:50 -07009400 pw.print(" appFullscreen="); pw.print(appFullscreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009401 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
9402 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
9403 pw.print(" clientHidden="); pw.print(clientHidden);
9404 pw.print(" willBeHidden="); pw.print(willBeHidden);
9405 pw.print(" reportedVisible="); pw.println(reportedVisible);
9406 if (paused || freezingScreen) {
9407 pw.print(prefix); pw.print("paused="); pw.print(paused);
9408 pw.print(" freezingScreen="); pw.println(freezingScreen);
9409 }
9410 if (numInterestingWindows != 0 || numDrawnWindows != 0
9411 || inPendingTransaction || allDrawn) {
9412 pw.print(prefix); pw.print("numInterestingWindows=");
9413 pw.print(numInterestingWindows);
9414 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
9415 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
9416 pw.print(" allDrawn="); pw.println(allDrawn);
9417 }
9418 if (animating || animation != null) {
9419 pw.print(prefix); pw.print("animating="); pw.print(animating);
9420 pw.print(" animation="); pw.println(animation);
9421 }
9422 if (animLayerAdjustment != 0) {
9423 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
9424 }
9425 if (hasTransformation) {
9426 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
9427 pw.print(" transformation="); transformation.printShortString(pw);
9428 pw.println();
9429 }
9430 if (startingData != null || removed || firstWindowDrawn) {
9431 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
9432 pw.print(" removed="); pw.print(removed);
9433 pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
9434 }
9435 if (startingWindow != null || startingView != null
9436 || startingDisplayed || startingMoved) {
9437 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
9438 pw.print(" startingView="); pw.print(startingView);
9439 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
9440 pw.print(" startingMoved"); pw.println(startingMoved);
9441 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009442 }
9443
9444 @Override
9445 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07009446 if (stringName == null) {
9447 StringBuilder sb = new StringBuilder();
9448 sb.append("AppWindowToken{");
9449 sb.append(Integer.toHexString(System.identityHashCode(this)));
9450 sb.append(" token="); sb.append(token); sb.append('}');
9451 stringName = sb.toString();
9452 }
9453 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009454 }
9455 }
Romain Guy06882f82009-06-10 13:36:04 -07009456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009457 // -------------------------------------------------------------
9458 // DummyAnimation
9459 // -------------------------------------------------------------
9460
9461 // This is an animation that does nothing: it just immediately finishes
9462 // itself every time it is called. It is used as a stub animation in cases
9463 // where we want to synchronize multiple things that may be animating.
9464 static final class DummyAnimation extends Animation {
9465 public boolean getTransformation(long currentTime, Transformation outTransformation) {
9466 return false;
9467 }
9468 }
9469 static final Animation sDummyAnimation = new DummyAnimation();
Romain Guy06882f82009-06-10 13:36:04 -07009470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009471 // -------------------------------------------------------------
9472 // Async Handler
9473 // -------------------------------------------------------------
9474
9475 static final class StartingData {
9476 final String pkg;
9477 final int theme;
9478 final CharSequence nonLocalizedLabel;
9479 final int labelRes;
9480 final int icon;
Romain Guy06882f82009-06-10 13:36:04 -07009481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009482 StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
9483 int _labelRes, int _icon) {
9484 pkg = _pkg;
9485 theme = _theme;
9486 nonLocalizedLabel = _nonLocalizedLabel;
9487 labelRes = _labelRes;
9488 icon = _icon;
9489 }
9490 }
9491
9492 private final class H extends Handler {
9493 public static final int REPORT_FOCUS_CHANGE = 2;
9494 public static final int REPORT_LOSING_FOCUS = 3;
9495 public static final int ANIMATE = 4;
9496 public static final int ADD_STARTING = 5;
9497 public static final int REMOVE_STARTING = 6;
9498 public static final int FINISHED_STARTING = 7;
9499 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009500 public static final int WINDOW_FREEZE_TIMEOUT = 11;
9501 public static final int HOLD_SCREEN_CHANGED = 12;
9502 public static final int APP_TRANSITION_TIMEOUT = 13;
9503 public static final int PERSIST_ANIMATION_SCALE = 14;
9504 public static final int FORCE_GC = 15;
9505 public static final int ENABLE_SCREEN = 16;
9506 public static final int APP_FREEZE_TIMEOUT = 17;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009507 public static final int SEND_NEW_CONFIGURATION = 18;
Romain Guy06882f82009-06-10 13:36:04 -07009508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009509 private Session mLastReportedHold;
Romain Guy06882f82009-06-10 13:36:04 -07009510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009511 public H() {
9512 }
Romain Guy06882f82009-06-10 13:36:04 -07009513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009514 @Override
9515 public void handleMessage(Message msg) {
9516 switch (msg.what) {
9517 case REPORT_FOCUS_CHANGE: {
9518 WindowState lastFocus;
9519 WindowState newFocus;
Romain Guy06882f82009-06-10 13:36:04 -07009520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009521 synchronized(mWindowMap) {
9522 lastFocus = mLastFocus;
9523 newFocus = mCurrentFocus;
9524 if (lastFocus == newFocus) {
9525 // Focus is not changing, so nothing to do.
9526 return;
9527 }
9528 mLastFocus = newFocus;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009529 //Slog.i(TAG, "Focus moving from " + lastFocus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009530 // + " to " + newFocus);
9531 if (newFocus != null && lastFocus != null
9532 && !newFocus.isDisplayedLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009533 //Slog.i(TAG, "Delaying loss of focus...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009534 mLosingFocus.add(lastFocus);
9535 lastFocus = null;
9536 }
9537 }
9538
9539 if (lastFocus != newFocus) {
9540 //System.out.println("Changing focus from " + lastFocus
9541 // + " to " + newFocus);
9542 if (newFocus != null) {
9543 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009544 //Slog.i(TAG, "Gaining focus: " + newFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009545 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
9546 } catch (RemoteException e) {
9547 // Ignore if process has died.
9548 }
9549 }
9550
9551 if (lastFocus != null) {
9552 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009553 //Slog.i(TAG, "Losing focus: " + lastFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009554 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
9555 } catch (RemoteException e) {
9556 // Ignore if process has died.
9557 }
9558 }
9559 }
9560 } break;
9561
9562 case REPORT_LOSING_FOCUS: {
9563 ArrayList<WindowState> losers;
Romain Guy06882f82009-06-10 13:36:04 -07009564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009565 synchronized(mWindowMap) {
9566 losers = mLosingFocus;
9567 mLosingFocus = new ArrayList<WindowState>();
9568 }
9569
9570 final int N = losers.size();
9571 for (int i=0; i<N; i++) {
9572 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009573 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009574 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
9575 } catch (RemoteException e) {
9576 // Ignore if process has died.
9577 }
9578 }
9579 } break;
9580
9581 case ANIMATE: {
9582 synchronized(mWindowMap) {
9583 mAnimationPending = false;
9584 performLayoutAndPlaceSurfacesLocked();
9585 }
9586 } break;
9587
9588 case ADD_STARTING: {
9589 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9590 final StartingData sd = wtoken.startingData;
9591
9592 if (sd == null) {
9593 // Animation has been canceled... do nothing.
9594 return;
9595 }
Romain Guy06882f82009-06-10 13:36:04 -07009596
Joe Onorato8a9b2202010-02-26 18:56:32 -08009597 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009598 + wtoken + ": pkg=" + sd.pkg);
Romain Guy06882f82009-06-10 13:36:04 -07009599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009600 View view = null;
9601 try {
9602 view = mPolicy.addStartingWindow(
9603 wtoken.token, sd.pkg,
9604 sd.theme, sd.nonLocalizedLabel, sd.labelRes,
9605 sd.icon);
9606 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009607 Slog.w(TAG, "Exception when adding starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009608 }
9609
9610 if (view != null) {
9611 boolean abort = false;
9612
9613 synchronized(mWindowMap) {
9614 if (wtoken.removed || wtoken.startingData == null) {
9615 // If the window was successfully added, then
9616 // we need to remove it.
9617 if (wtoken.startingWindow != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009618 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009619 "Aborted starting " + wtoken
9620 + ": removed=" + wtoken.removed
9621 + " startingData=" + wtoken.startingData);
9622 wtoken.startingWindow = null;
9623 wtoken.startingData = null;
9624 abort = true;
9625 }
9626 } else {
9627 wtoken.startingView = view;
9628 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009629 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009630 "Added starting " + wtoken
9631 + ": startingWindow="
9632 + wtoken.startingWindow + " startingView="
9633 + wtoken.startingView);
9634 }
9635
9636 if (abort) {
9637 try {
9638 mPolicy.removeStartingWindow(wtoken.token, view);
9639 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009640 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009641 }
9642 }
9643 }
9644 } break;
9645
9646 case REMOVE_STARTING: {
9647 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9648 IBinder token = null;
9649 View view = null;
9650 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009651 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 + wtoken + ": startingWindow="
9653 + wtoken.startingWindow + " startingView="
9654 + wtoken.startingView);
9655 if (wtoken.startingWindow != null) {
9656 view = wtoken.startingView;
9657 token = wtoken.token;
9658 wtoken.startingData = null;
9659 wtoken.startingView = null;
9660 wtoken.startingWindow = null;
9661 }
9662 }
9663 if (view != null) {
9664 try {
9665 mPolicy.removeStartingWindow(token, view);
9666 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009667 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009668 }
9669 }
9670 } break;
9671
9672 case FINISHED_STARTING: {
9673 IBinder token = null;
9674 View view = null;
9675 while (true) {
9676 synchronized (mWindowMap) {
9677 final int N = mFinishedStarting.size();
9678 if (N <= 0) {
9679 break;
9680 }
9681 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
9682
Joe Onorato8a9b2202010-02-26 18:56:32 -08009683 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009684 "Finished starting " + wtoken
9685 + ": startingWindow=" + wtoken.startingWindow
9686 + " startingView=" + wtoken.startingView);
9687
9688 if (wtoken.startingWindow == null) {
9689 continue;
9690 }
9691
9692 view = wtoken.startingView;
9693 token = wtoken.token;
9694 wtoken.startingData = null;
9695 wtoken.startingView = null;
9696 wtoken.startingWindow = null;
9697 }
9698
9699 try {
9700 mPolicy.removeStartingWindow(token, view);
9701 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009702 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009703 }
9704 }
9705 } break;
9706
9707 case REPORT_APPLICATION_TOKEN_WINDOWS: {
9708 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9709
9710 boolean nowVisible = msg.arg1 != 0;
9711 boolean nowGone = msg.arg2 != 0;
9712
9713 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009714 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009715 TAG, "Reporting visible in " + wtoken
9716 + " visible=" + nowVisible
9717 + " gone=" + nowGone);
9718 if (nowVisible) {
9719 wtoken.appToken.windowsVisible();
9720 } else {
9721 wtoken.appToken.windowsGone();
9722 }
9723 } catch (RemoteException ex) {
9724 }
9725 } break;
Romain Guy06882f82009-06-10 13:36:04 -07009726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009727 case WINDOW_FREEZE_TIMEOUT: {
9728 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009729 Slog.w(TAG, "Window freeze timeout expired.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009730 int i = mWindows.size();
9731 while (i > 0) {
9732 i--;
9733 WindowState w = (WindowState)mWindows.get(i);
9734 if (w.mOrientationChanging) {
9735 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009736 Slog.w(TAG, "Force clearing orientation change: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009737 }
9738 }
9739 performLayoutAndPlaceSurfacesLocked();
9740 }
9741 break;
9742 }
Romain Guy06882f82009-06-10 13:36:04 -07009743
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009744 case HOLD_SCREEN_CHANGED: {
9745 Session oldHold;
9746 Session newHold;
9747 synchronized (mWindowMap) {
9748 oldHold = mLastReportedHold;
9749 newHold = (Session)msg.obj;
9750 mLastReportedHold = newHold;
9751 }
Romain Guy06882f82009-06-10 13:36:04 -07009752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009753 if (oldHold != newHold) {
9754 try {
9755 if (oldHold != null) {
9756 mBatteryStats.noteStopWakelock(oldHold.mUid,
9757 "window",
9758 BatteryStats.WAKE_TYPE_WINDOW);
9759 }
9760 if (newHold != null) {
9761 mBatteryStats.noteStartWakelock(newHold.mUid,
9762 "window",
9763 BatteryStats.WAKE_TYPE_WINDOW);
9764 }
9765 } catch (RemoteException e) {
9766 }
9767 }
9768 break;
9769 }
Romain Guy06882f82009-06-10 13:36:04 -07009770
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009771 case APP_TRANSITION_TIMEOUT: {
9772 synchronized (mWindowMap) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009773 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009774 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009775 "*** APP TRANSITION TIMEOUT");
9776 mAppTransitionReady = true;
9777 mAppTransitionTimeout = true;
9778 performLayoutAndPlaceSurfacesLocked();
9779 }
9780 }
9781 break;
9782 }
Romain Guy06882f82009-06-10 13:36:04 -07009783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009784 case PERSIST_ANIMATION_SCALE: {
9785 Settings.System.putFloat(mContext.getContentResolver(),
9786 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
9787 Settings.System.putFloat(mContext.getContentResolver(),
9788 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
9789 break;
9790 }
Romain Guy06882f82009-06-10 13:36:04 -07009791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009792 case FORCE_GC: {
9793 synchronized(mWindowMap) {
9794 if (mAnimationPending) {
9795 // If we are animating, don't do the gc now but
9796 // delay a bit so we don't interrupt the animation.
9797 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
9798 2000);
9799 return;
9800 }
9801 // If we are currently rotating the display, it will
9802 // schedule a new message when done.
9803 if (mDisplayFrozen) {
9804 return;
9805 }
9806 mFreezeGcPending = 0;
9807 }
9808 Runtime.getRuntime().gc();
9809 break;
9810 }
Romain Guy06882f82009-06-10 13:36:04 -07009811
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009812 case ENABLE_SCREEN: {
9813 performEnableScreen();
9814 break;
9815 }
Romain Guy06882f82009-06-10 13:36:04 -07009816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009817 case APP_FREEZE_TIMEOUT: {
9818 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009819 Slog.w(TAG, "App freeze timeout expired.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009820 int i = mAppTokens.size();
9821 while (i > 0) {
9822 i--;
9823 AppWindowToken tok = mAppTokens.get(i);
9824 if (tok.freezingScreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009825 Slog.w(TAG, "Force clearing freeze: " + tok);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009826 unsetAppFreezingScreenLocked(tok, true, true);
9827 }
9828 }
9829 }
9830 break;
9831 }
Romain Guy06882f82009-06-10 13:36:04 -07009832
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009833 case SEND_NEW_CONFIGURATION: {
9834 removeMessages(SEND_NEW_CONFIGURATION);
9835 sendNewConfiguration();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07009836 break;
9837 }
Romain Guy06882f82009-06-10 13:36:04 -07009838
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009839 }
9840 }
9841 }
9842
9843 // -------------------------------------------------------------
9844 // IWindowManager API
9845 // -------------------------------------------------------------
9846
9847 public IWindowSession openSession(IInputMethodClient client,
9848 IInputContext inputContext) {
9849 if (client == null) throw new IllegalArgumentException("null client");
9850 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07009851 Session session = new Session(client, inputContext);
9852 return session;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009853 }
9854
9855 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
9856 synchronized (mWindowMap) {
9857 // The focus for the client is the window immediately below
9858 // where we would place the input method window.
9859 int idx = findDesiredInputMethodWindowIndexLocked(false);
9860 WindowState imFocus;
9861 if (idx > 0) {
9862 imFocus = (WindowState)mWindows.get(idx-1);
9863 if (imFocus != null) {
9864 if (imFocus.mSession.mClient != null &&
9865 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
9866 return true;
9867 }
9868 }
9869 }
9870 }
9871 return false;
9872 }
Romain Guy06882f82009-06-10 13:36:04 -07009873
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009874 // -------------------------------------------------------------
9875 // Internals
9876 // -------------------------------------------------------------
9877
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009878 final WindowState windowForClientLocked(Session session, IWindow client,
9879 boolean throwOnError) {
9880 return windowForClientLocked(session, client.asBinder(), throwOnError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009881 }
Romain Guy06882f82009-06-10 13:36:04 -07009882
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009883 final WindowState windowForClientLocked(Session session, IBinder client,
9884 boolean throwOnError) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009885 WindowState win = mWindowMap.get(client);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009886 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009887 TAG, "Looking up client " + client + ": " + win);
9888 if (win == null) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009889 RuntimeException ex = new IllegalArgumentException(
9890 "Requested window " + client + " does not exist");
9891 if (throwOnError) {
9892 throw ex;
9893 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009894 Slog.w(TAG, "Failed looking up window", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009895 return null;
9896 }
9897 if (session != null && win.mSession != session) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009898 RuntimeException ex = new IllegalArgumentException(
9899 "Requested window " + client + " is in session " +
9900 win.mSession + ", not " + session);
9901 if (throwOnError) {
9902 throw ex;
9903 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009904 Slog.w(TAG, "Failed looking up window", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 return null;
9906 }
9907
9908 return win;
9909 }
9910
Dianne Hackborna8f60182009-09-01 19:01:50 -07009911 final void rebuildAppWindowListLocked() {
9912 int NW = mWindows.size();
9913 int i;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009914 int lastWallpaper = -1;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009915 int numRemoved = 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009916
Dianne Hackborna8f60182009-09-01 19:01:50 -07009917 // First remove all existing app windows.
9918 i=0;
9919 while (i < NW) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009920 WindowState w = (WindowState)mWindows.get(i);
9921 if (w.mAppToken != null) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009922 WindowState win = (WindowState)mWindows.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009923 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009924 "Rebuild removing window: " + win);
Dianne Hackborna8f60182009-09-01 19:01:50 -07009925 NW--;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009926 numRemoved++;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009927 continue;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009928 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
9929 && lastWallpaper == i-1) {
9930 lastWallpaper = i;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009931 }
9932 i++;
9933 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009934
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009935 // The wallpaper window(s) typically live at the bottom of the stack,
9936 // so skip them before adding app tokens.
9937 lastWallpaper++;
9938 i = lastWallpaper;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009939
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009940 // First add all of the exiting app tokens... these are no longer
9941 // in the main app list, but still have windows shown. We put them
9942 // in the back because now that the animation is over we no longer
9943 // will care about them.
9944 int NT = mExitingAppTokens.size();
Dianne Hackborna8f60182009-09-01 19:01:50 -07009945 for (int j=0; j<NT; j++) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009946 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
9947 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009948
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009949 // And add in the still active app tokens in Z order.
9950 NT = mAppTokens.size();
9951 for (int j=0; j<NT; j++) {
9952 i = reAddAppWindowsLocked(i, mAppTokens.get(j));
Dianne Hackborna8f60182009-09-01 19:01:50 -07009953 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009954
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009955 i -= lastWallpaper;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009956 if (i != numRemoved) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009957 Slog.w(TAG, "Rebuild removed " + numRemoved
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009958 + " windows but added " + i);
9959 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07009960 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009962 private final void assignLayersLocked() {
9963 int N = mWindows.size();
9964 int curBaseLayer = 0;
9965 int curLayer = 0;
9966 int i;
Romain Guy06882f82009-06-10 13:36:04 -07009967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009968 for (i=0; i<N; i++) {
9969 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009970 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
9971 || (i > 0 && w.mIsWallpaper)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009972 curLayer += WINDOW_LAYER_MULTIPLIER;
9973 w.mLayer = curLayer;
9974 } else {
9975 curBaseLayer = curLayer = w.mBaseLayer;
9976 w.mLayer = curLayer;
9977 }
9978 if (w.mTargetAppToken != null) {
9979 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
9980 } else if (w.mAppToken != null) {
9981 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
9982 } else {
9983 w.mAnimLayer = w.mLayer;
9984 }
9985 if (w.mIsImWindow) {
9986 w.mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07009987 } else if (w.mIsWallpaper) {
9988 w.mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009989 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009990 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009991 + w.mAnimLayer);
9992 //System.out.println(
9993 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
9994 }
9995 }
9996
9997 private boolean mInLayout = false;
9998 private final void performLayoutAndPlaceSurfacesLocked() {
9999 if (mInLayout) {
Dave Bortcfe65242009-04-09 14:51:04 -070010000 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010001 throw new RuntimeException("Recursive call!");
10002 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010003 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010004 return;
10005 }
10006
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010007 if (mWaitingForConfig) {
10008 // Our configuration has changed (most likely rotation), but we
10009 // don't yet have the complete configuration to report to
10010 // applications. Don't do any window layout until we have it.
10011 return;
10012 }
10013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010014 boolean recoveringMemory = false;
10015 if (mForceRemoves != null) {
10016 recoveringMemory = true;
10017 // Wait a little it for things to settle down, and off we go.
10018 for (int i=0; i<mForceRemoves.size(); i++) {
10019 WindowState ws = mForceRemoves.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010020 Slog.i(TAG, "Force removing: " + ws);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010021 removeWindowInnerLocked(ws.mSession, ws);
10022 }
10023 mForceRemoves = null;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010024 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010025 Object tmp = new Object();
10026 synchronized (tmp) {
10027 try {
10028 tmp.wait(250);
10029 } catch (InterruptedException e) {
10030 }
10031 }
10032 }
Romain Guy06882f82009-06-10 13:36:04 -070010033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010034 mInLayout = true;
10035 try {
10036 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
Romain Guy06882f82009-06-10 13:36:04 -070010037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038 int i = mPendingRemove.size()-1;
10039 if (i >= 0) {
10040 while (i >= 0) {
10041 WindowState w = mPendingRemove.get(i);
10042 removeWindowInnerLocked(w.mSession, w);
10043 i--;
10044 }
10045 mPendingRemove.clear();
10046
10047 mInLayout = false;
10048 assignLayersLocked();
10049 mLayoutNeeded = true;
10050 performLayoutAndPlaceSurfacesLocked();
10051
10052 } else {
10053 mInLayout = false;
10054 if (mLayoutNeeded) {
10055 requestAnimationLocked(0);
10056 }
10057 }
10058 } catch (RuntimeException e) {
10059 mInLayout = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010060 Slog.e(TAG, "Unhandled exception while layout out windows", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010061 }
10062 }
10063
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010064 private final int performLayoutLockedInner() {
10065 if (!mLayoutNeeded) {
10066 return 0;
10067 }
10068
10069 mLayoutNeeded = false;
10070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010071 final int dw = mDisplay.getWidth();
10072 final int dh = mDisplay.getHeight();
10073
10074 final int N = mWindows.size();
10075 int i;
10076
Joe Onorato8a9b2202010-02-26 18:56:32 -080010077 if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed="
Dianne Hackborn9b52a212009-12-11 14:51:35 -080010078 + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
10079
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010080 mPolicy.beginLayoutLw(dw, dh);
Romain Guy06882f82009-06-10 13:36:04 -070010081
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010082 int seq = mLayoutSeq+1;
10083 if (seq < 0) seq = 0;
10084 mLayoutSeq = seq;
10085
10086 // First perform layout of any root windows (not attached
10087 // to another window).
10088 int topAttached = -1;
10089 for (i = N-1; i >= 0; i--) {
10090 WindowState win = (WindowState) mWindows.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010091
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010092 // Don't do layout of a window if it is not visible, or
10093 // soon won't be visible, to avoid wasting time and funky
10094 // changes while a window is animating away.
10095 final AppWindowToken atoken = win.mAppToken;
10096 final boolean gone = win.mViewVisibility == View.GONE
10097 || !win.mRelayoutCalled
10098 || win.mRootToken.hidden
10099 || (atoken != null && atoken.hiddenRequested)
10100 || win.mAttachedHidden
10101 || win.mExiting || win.mDestroying;
10102
10103 if (!win.mLayoutAttached) {
10104 if (DEBUG_LAYOUT) Slog.v(TAG, "First pass " + win
10105 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
10106 + " mLayoutAttached=" + win.mLayoutAttached);
10107 if (DEBUG_LAYOUT && gone) Slog.v(TAG, " (mViewVisibility="
10108 + win.mViewVisibility + " mRelayoutCalled="
10109 + win.mRelayoutCalled + " hidden="
10110 + win.mRootToken.hidden + " hiddenRequested="
10111 + (atoken != null && atoken.hiddenRequested)
10112 + " mAttachedHidden=" + win.mAttachedHidden);
10113 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010114
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010115 // If this view is GONE, then skip it -- keep the current
10116 // frame, and let the caller know so they can ignore it
10117 // if they want. (We do the normal layout for INVISIBLE
10118 // windows, since that means "perform layout as normal,
10119 // just don't display").
10120 if (!gone || !win.mHaveFrame) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010121 if (!win.mLayoutAttached) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010122 mPolicy.layoutWindowLw(win, win.mAttrs, null);
10123 win.mLayoutSeq = seq;
10124 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
10125 + win.mFrame + " mContainingFrame="
10126 + win.mContainingFrame + " mDisplayFrame="
10127 + win.mDisplayFrame);
10128 } else {
10129 if (topAttached < 0) topAttached = i;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -070010130 }
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070010131 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010132 }
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010133
10134 // Now perform layout of attached windows, which usually
10135 // depend on the position of the window they are attached to.
10136 // XXX does not deal with windows that are attached to windows
10137 // that are themselves attached.
10138 for (i = topAttached; i >= 0; i--) {
10139 WindowState win = (WindowState) mWindows.get(i);
10140
10141 // If this view is GONE, then skip it -- keep the current
10142 // frame, and let the caller know so they can ignore it
10143 // if they want. (We do the normal layout for INVISIBLE
10144 // windows, since that means "perform layout as normal,
10145 // just don't display").
10146 if (win.mLayoutAttached) {
10147 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win
10148 + " mHaveFrame=" + win.mHaveFrame
10149 + " mViewVisibility=" + win.mViewVisibility
10150 + " mRelayoutCalled=" + win.mRelayoutCalled);
10151 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
10152 || !win.mHaveFrame) {
10153 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
10154 win.mLayoutSeq = seq;
10155 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
10156 + win.mFrame + " mContainingFrame="
10157 + win.mContainingFrame + " mDisplayFrame="
10158 + win.mDisplayFrame);
10159 }
10160 }
10161 }
10162
10163 return mPolicy.finishLayoutLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010164 }
Romain Guy06882f82009-06-10 13:36:04 -070010165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010166 private final void performLayoutAndPlaceSurfacesLockedInner(
10167 boolean recoveringMemory) {
10168 final long currentTime = SystemClock.uptimeMillis();
10169 final int dw = mDisplay.getWidth();
10170 final int dh = mDisplay.getHeight();
10171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010172 int i;
10173
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010174 if (mFocusMayChange) {
10175 mFocusMayChange = false;
10176 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
10177 }
10178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010179 if (mFxSession == null) {
10180 mFxSession = new SurfaceSession();
10181 }
Romain Guy06882f82009-06-10 13:36:04 -070010182
Joe Onorato8a9b2202010-02-26 18:56:32 -080010183 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010184
10185 // Initialize state of exiting tokens.
10186 for (i=mExitingTokens.size()-1; i>=0; i--) {
10187 mExitingTokens.get(i).hasVisible = false;
10188 }
10189
10190 // Initialize state of exiting applications.
10191 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
10192 mExitingAppTokens.get(i).hasVisible = false;
10193 }
10194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010195 boolean orientationChangeComplete = true;
10196 Session holdScreen = null;
10197 float screenBrightness = -1;
Mike Lockwoodfb73f792009-11-20 11:31:18 -050010198 float buttonBrightness = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010199 boolean focusDisplayed = false;
10200 boolean animating = false;
10201
10202 Surface.openTransaction();
10203 try {
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010204 boolean wallpaperForceHidingChanged = false;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010205 int repeats = 0;
10206 int changes = 0;
10207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010208 do {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010209 repeats++;
10210 if (repeats > 6) {
10211 Slog.w(TAG, "Animation repeat aborted after too many iterations");
10212 mLayoutNeeded = false;
10213 break;
10214 }
10215
10216 if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER
10217 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG
10218 | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) {
10219 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
10220 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
10221 assignLayersLocked();
10222 mLayoutNeeded = true;
10223 }
10224 }
10225 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
10226 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
10227 if (updateOrientationFromAppTokensLocked()) {
10228 mLayoutNeeded = true;
10229 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
10230 }
10231 }
10232 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
10233 mLayoutNeeded = true;
10234 }
10235 }
10236
10237 // FIRST LOOP: Perform a layout, if needed.
10238 if (repeats < 4) {
10239 changes = performLayoutLockedInner();
10240 if (changes != 0) {
10241 continue;
10242 }
10243 } else {
10244 Slog.w(TAG, "Layout repeat skipped after too many iterations");
10245 changes = 0;
10246 }
10247
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010248 final int transactionSequence = ++mTransactionSequence;
10249
10250 // Update animations of all applications, including those
10251 // associated with exiting/removed apps
10252 boolean tokensAnimating = false;
10253 final int NAT = mAppTokens.size();
10254 for (i=0; i<NAT; i++) {
10255 if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
10256 tokensAnimating = true;
10257 }
10258 }
10259 final int NEAT = mExitingAppTokens.size();
10260 for (i=0; i<NEAT; i++) {
10261 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
10262 tokensAnimating = true;
10263 }
10264 }
10265
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010266 // SECOND LOOP: Execute animations and update visibility of windows.
10267
Joe Onorato8a9b2202010-02-26 18:56:32 -080010268 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010269 + transactionSequence + " tokensAnimating="
10270 + tokensAnimating);
10271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010272 animating = tokensAnimating;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010273
10274 boolean tokenMayBeDrawn = false;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010275 boolean wallpaperMayChange = false;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010276 boolean forceHiding = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010277
10278 mPolicy.beginAnimationLw(dw, dh);
10279
Dianne Hackbornbdd52b22009-09-02 21:46:19 -070010280 final int N = mWindows.size();
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010282 for (i=N-1; i>=0; i--) {
10283 WindowState w = (WindowState)mWindows.get(i);
10284
10285 final WindowManager.LayoutParams attrs = w.mAttrs;
10286
10287 if (w.mSurface != null) {
10288 // Execute animation.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010289 if (w.commitFinishDrawingLocked(currentTime)) {
10290 if ((w.mAttrs.flags
10291 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010292 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010293 "First draw done in potential wallpaper target " + w);
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010294 wallpaperMayChange = true;
10295 }
10296 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010297
Dianne Hackborn6136b7e2009-09-18 01:53:49 -070010298 boolean wasAnimating = w.mAnimating;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010299 if (w.stepAnimationLocked(currentTime, dw, dh)) {
10300 animating = true;
10301 //w.dump(" ");
10302 }
Dianne Hackborn6136b7e2009-09-18 01:53:49 -070010303 if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
10304 wallpaperMayChange = true;
10305 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010306
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010307 if (mPolicy.doesForceHide(w, attrs)) {
10308 if (!wasAnimating && animating) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080010309 if (DEBUG_VISIBILITY) Slog.v(TAG,
10310 "Animation done that could impact force hide: "
10311 + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010312 wallpaperForceHidingChanged = true;
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010313 mFocusMayChange = true;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010314 } else if (w.isReadyForDisplay() && w.mAnimation == null) {
10315 forceHiding = true;
10316 }
10317 } else if (mPolicy.canBeForceHidden(w, attrs)) {
10318 boolean changed;
10319 if (forceHiding) {
10320 changed = w.hideLw(false, false);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080010321 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
10322 "Now policy hidden: " + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010323 } else {
10324 changed = w.showLw(false, false);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080010325 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
10326 "Now policy shown: " + w);
10327 if (changed) {
10328 if (wallpaperForceHidingChanged
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010329 && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080010330 // Assume we will need to animate. If
10331 // we don't (because the wallpaper will
10332 // stay with the lock screen), then we will
10333 // clean up later.
10334 Animation a = mPolicy.createForceHideEnterAnimation();
10335 if (a != null) {
10336 w.setAnimation(a);
10337 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010338 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -080010339 if (mCurrentFocus == null ||
10340 mCurrentFocus.mLayer < w.mLayer) {
10341 // We are showing on to of the current
10342 // focus, so re-evaluate focus to make
10343 // sure it is correct.
10344 mFocusMayChange = true;
10345 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010346 }
10347 }
10348 if (changed && (attrs.flags
10349 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
10350 wallpaperMayChange = true;
10351 }
10352 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010353
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010354 mPolicy.animatingWindowLw(w, attrs);
10355 }
10356
10357 final AppWindowToken atoken = w.mAppToken;
10358 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
10359 if (atoken.lastTransactionSequence != transactionSequence) {
10360 atoken.lastTransactionSequence = transactionSequence;
10361 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
10362 atoken.startingDisplayed = false;
10363 }
10364 if ((w.isOnScreen() || w.mAttrs.type
10365 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
10366 && !w.mExiting && !w.mDestroying) {
10367 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010368 Slog.v(TAG, "Eval win " + w + ": isDrawn="
Dianne Hackborn7433e8a2009-09-27 13:21:20 -070010369 + w.isDrawnLw()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370 + ", isAnimating=" + w.isAnimating());
Dianne Hackborn7433e8a2009-09-27 13:21:20 -070010371 if (!w.isDrawnLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010372 Slog.v(TAG, "Not displayed: s=" + w.mSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010373 + " pv=" + w.mPolicyVisibility
10374 + " dp=" + w.mDrawPending
10375 + " cdp=" + w.mCommitDrawPending
10376 + " ah=" + w.mAttachedHidden
10377 + " th=" + atoken.hiddenRequested
10378 + " a=" + w.mAnimating);
10379 }
10380 }
10381 if (w != atoken.startingWindow) {
10382 if (!atoken.freezingScreen || !w.mAppFreezing) {
10383 atoken.numInterestingWindows++;
Dianne Hackborn7433e8a2009-09-27 13:21:20 -070010384 if (w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010385 atoken.numDrawnWindows++;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010386 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010387 "tokenMayBeDrawn: " + atoken
10388 + " freezingScreen=" + atoken.freezingScreen
10389 + " mAppFreezing=" + w.mAppFreezing);
10390 tokenMayBeDrawn = true;
10391 }
10392 }
Dianne Hackborn7433e8a2009-09-27 13:21:20 -070010393 } else if (w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010394 atoken.startingDisplayed = true;
10395 }
10396 }
10397 } else if (w.mReadyToShow) {
10398 w.performShowLocked();
10399 }
10400 }
10401
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010402 changes |= mPolicy.finishAnimationLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403
10404 if (tokenMayBeDrawn) {
10405 // See if any windows have been drawn, so they (and others
10406 // associated with them) can now be shown.
10407 final int NT = mTokenList.size();
10408 for (i=0; i<NT; i++) {
10409 AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
10410 if (wtoken == null) {
10411 continue;
10412 }
10413 if (wtoken.freezingScreen) {
10414 int numInteresting = wtoken.numInterestingWindows;
10415 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010416 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010417 "allDrawn: " + wtoken
10418 + " interesting=" + numInteresting
10419 + " drawn=" + wtoken.numDrawnWindows);
10420 wtoken.showAllWindowsLocked();
10421 unsetAppFreezingScreenLocked(wtoken, false, true);
10422 orientationChangeComplete = true;
10423 }
10424 } else if (!wtoken.allDrawn) {
10425 int numInteresting = wtoken.numInterestingWindows;
10426 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010427 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010428 "allDrawn: " + wtoken
10429 + " interesting=" + numInteresting
10430 + " drawn=" + wtoken.numDrawnWindows);
10431 wtoken.allDrawn = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010432 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010433
10434 // We can now show all of the drawn windows!
10435 if (!mOpeningApps.contains(wtoken)) {
10436 wtoken.showAllWindowsLocked();
10437 }
10438 }
10439 }
10440 }
10441 }
10442
10443 // If we are ready to perform an app transition, check through
10444 // all of the app tokens to be shown and see if they are ready
10445 // to go.
10446 if (mAppTransitionReady) {
10447 int NN = mOpeningApps.size();
10448 boolean goodToGo = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010449 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010450 "Checking " + NN + " opening apps (frozen="
10451 + mDisplayFrozen + " timeout="
10452 + mAppTransitionTimeout + ")...");
10453 if (!mDisplayFrozen && !mAppTransitionTimeout) {
10454 // If the display isn't frozen, wait to do anything until
10455 // all of the apps are ready. Otherwise just go because
10456 // we'll unfreeze the display when everyone is ready.
10457 for (i=0; i<NN && goodToGo; i++) {
10458 AppWindowToken wtoken = mOpeningApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010459 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010460 "Check opening app" + wtoken + ": allDrawn="
10461 + wtoken.allDrawn + " startingDisplayed="
10462 + wtoken.startingDisplayed);
10463 if (!wtoken.allDrawn && !wtoken.startingDisplayed
10464 && !wtoken.startingMoved) {
10465 goodToGo = false;
10466 }
10467 }
10468 }
10469 if (goodToGo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010470 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010471 int transit = mNextAppTransition;
10472 if (mSkipAppTransitionAnimation) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -070010473 transit = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010474 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -070010475 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010476 mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -070010477 mAppTransitionRunning = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010478 mAppTransitionTimeout = false;
10479 mStartingIconInTransition = false;
10480 mSkipAppTransitionAnimation = false;
10481
10482 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
10483
Dianne Hackborna8f60182009-09-01 19:01:50 -070010484 // If there are applications waiting to come to the
10485 // top of the stack, now is the time to move their windows.
10486 // (Note that we don't do apps going to the bottom
10487 // here -- we want to keep their windows in the old
10488 // Z-order until the animation completes.)
10489 if (mToTopApps.size() > 0) {
10490 NN = mAppTokens.size();
10491 for (i=0; i<NN; i++) {
10492 AppWindowToken wtoken = mAppTokens.get(i);
10493 if (wtoken.sendingToTop) {
10494 wtoken.sendingToTop = false;
10495 moveAppWindowsLocked(wtoken, NN, false);
10496 }
10497 }
10498 mToTopApps.clear();
10499 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010500
Dianne Hackborn25994b42009-09-04 14:21:19 -070010501 WindowState oldWallpaper = mWallpaperTarget;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010502
Dianne Hackborn3be63c02009-08-20 19:31:38 -070010503 adjustWallpaperWindowsLocked();
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010504 wallpaperMayChange = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010505
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010506 // The top-most window will supply the layout params,
10507 // and we will determine it below.
10508 LayoutParams animLp = null;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010509 AppWindowToken animToken = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010510 int bestAnimLayer = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010511
Joe Onorato8a9b2202010-02-26 18:56:32 -080010512 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -070010513 "New wallpaper target=" + mWallpaperTarget
10514 + ", lower target=" + mLowerWallpaperTarget
10515 + ", upper target=" + mUpperWallpaperTarget);
Dianne Hackborn25994b42009-09-04 14:21:19 -070010516 int foundWallpapers = 0;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010517 // Do a first pass through the tokens for two
10518 // things:
10519 // (1) Determine if both the closing and opening
10520 // app token sets are wallpaper targets, in which
10521 // case special animations are needed
10522 // (since the wallpaper needs to stay static
10523 // behind them).
10524 // (2) Find the layout params of the top-most
10525 // application window in the tokens, which is
10526 // what will control the animation theme.
10527 final int NC = mClosingApps.size();
10528 NN = NC + mOpeningApps.size();
10529 for (i=0; i<NN; i++) {
10530 AppWindowToken wtoken;
10531 int mode;
10532 if (i < NC) {
10533 wtoken = mClosingApps.get(i);
10534 mode = 1;
10535 } else {
10536 wtoken = mOpeningApps.get(i-NC);
10537 mode = 2;
10538 }
10539 if (mLowerWallpaperTarget != null) {
10540 if (mLowerWallpaperTarget.mAppToken == wtoken
10541 || mUpperWallpaperTarget.mAppToken == wtoken) {
10542 foundWallpapers |= mode;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -070010543 }
10544 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010545 if (wtoken.appFullscreen) {
10546 WindowState ws = wtoken.findMainWindow();
10547 if (ws != null) {
10548 // If this is a compatibility mode
10549 // window, we will always use its anim.
10550 if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
10551 animLp = ws.mAttrs;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010552 animToken = ws.mAppToken;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010553 bestAnimLayer = Integer.MAX_VALUE;
10554 } else if (ws.mLayer > bestAnimLayer) {
10555 animLp = ws.mAttrs;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010556 animToken = ws.mAppToken;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010557 bestAnimLayer = ws.mLayer;
10558 }
Dianne Hackborn25994b42009-09-04 14:21:19 -070010559 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -070010560 }
10561 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010562
Dianne Hackborn25994b42009-09-04 14:21:19 -070010563 if (foundWallpapers == 3) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010564 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010565 "Wallpaper animation!");
10566 switch (transit) {
10567 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
10568 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
10569 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
10570 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN;
10571 break;
10572 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
10573 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
10574 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
10575 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE;
10576 break;
10577 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010578 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010579 "New transit: " + transit);
10580 } else if (oldWallpaper != null) {
10581 // We are transitioning from an activity with
10582 // a wallpaper to one without.
10583 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010584 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010585 "New transit away from wallpaper: " + transit);
10586 } else if (mWallpaperTarget != null) {
10587 // We are transitioning from an activity without
10588 // a wallpaper to now showing the wallpaper
10589 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010590 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010591 "New transit into wallpaper: " + transit);
10592 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010593
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010594 if ((transit&WindowManagerPolicy.TRANSIT_ENTER_MASK) != 0) {
10595 mLastEnterAnimToken = animToken;
10596 mLastEnterAnimParams = animLp;
10597 } else if (mLastEnterAnimParams != null) {
10598 animLp = mLastEnterAnimParams;
10599 mLastEnterAnimToken = null;
10600 mLastEnterAnimParams = null;
10601 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010602
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010603 // If all closing windows are obscured, then there is
10604 // no need to do an animation. This is the case, for
10605 // example, when this transition is being done behind
10606 // the lock screen.
10607 if (!mPolicy.allowAppAnimationsLw()) {
10608 animLp = null;
10609 }
10610
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010611 NN = mOpeningApps.size();
10612 for (i=0; i<NN; i++) {
10613 AppWindowToken wtoken = mOpeningApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010614 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 "Now opening app" + wtoken);
10616 wtoken.reportedVisible = false;
10617 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -070010618 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010619 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010620 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070010621 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010622 wtoken.showAllWindowsLocked();
10623 }
10624 NN = mClosingApps.size();
10625 for (i=0; i<NN; i++) {
10626 AppWindowToken wtoken = mClosingApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010627 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010628 "Now closing app" + wtoken);
10629 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -070010630 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010631 setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010632 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070010633 wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010634 // Force the allDrawn flag, because we want to start
10635 // this guy's animations regardless of whether it's
10636 // gotten drawn.
10637 wtoken.allDrawn = true;
10638 }
10639
Dianne Hackborn8b571a82009-09-25 16:09:43 -070010640 mNextAppTransitionPackage = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010642 mOpeningApps.clear();
10643 mClosingApps.clear();
10644
10645 // This has changed the visibility of windows, so perform
10646 // a new layout to get them all up-to-date.
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010647 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010648 mLayoutNeeded = true;
Dianne Hackborn20583ff2009-07-27 21:51:05 -070010649 if (!moveInputMethodWindowsIfNeededLocked(true)) {
10650 assignLayersLocked();
10651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010653 mFocusMayChange = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010654 }
10655 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010656
Dianne Hackborn16064f92010-03-25 00:47:24 -070010657 int adjResult = 0;
10658
Dianne Hackborna8f60182009-09-01 19:01:50 -070010659 if (!animating && mAppTransitionRunning) {
10660 // We have finished the animation of an app transition. To do
10661 // this, we have delayed a lot of operations like showing and
10662 // hiding apps, moving apps in Z-order, etc. The app token list
10663 // reflects the correct Z-order, but the window list may now
10664 // be out of sync with it. So here we will just rebuild the
10665 // entire app window list. Fun!
10666 mAppTransitionRunning = false;
10667 // Clear information about apps that were moving.
10668 mToBottomApps.clear();
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010669
Dianne Hackborna8f60182009-09-01 19:01:50 -070010670 rebuildAppWindowListLocked();
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010671 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn16064f92010-03-25 00:47:24 -070010672 adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED;
Dianne Hackborna8f60182009-09-01 19:01:50 -070010673 moveInputMethodWindowsIfNeededLocked(false);
10674 wallpaperMayChange = true;
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -080010675 // Since the window list has been rebuilt, focus might
10676 // have to be recomputed since the actual order of windows
10677 // might have changed again.
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010678 mFocusMayChange = true;
Dianne Hackborna8f60182009-09-01 19:01:50 -070010679 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010680
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010681 if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010682 // At this point, there was a window with a wallpaper that
10683 // was force hiding other windows behind it, but now it
10684 // is going away. This may be simple -- just animate
10685 // away the wallpaper and its window -- or it may be
10686 // hard -- the wallpaper now needs to be shown behind
10687 // something that was hidden.
10688 WindowState oldWallpaper = mWallpaperTarget;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010689 if (mLowerWallpaperTarget != null
10690 && mLowerWallpaperTarget.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010691 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010692 "wallpaperForceHiding changed with lower="
10693 + mLowerWallpaperTarget);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010694 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010695 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden +
10696 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested);
10697 if (mLowerWallpaperTarget.mAppToken.hidden) {
10698 // The lower target has become hidden before we
10699 // actually started the animation... let's completely
10700 // re-evaluate everything.
10701 mLowerWallpaperTarget = mUpperWallpaperTarget = null;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010702 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010703 }
10704 }
Dianne Hackborn16064f92010-03-25 00:47:24 -070010705 adjResult |= adjustWallpaperWindowsLocked();
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010706 wallpaperMayChange = false;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010707 wallpaperForceHidingChanged = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010708 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010709 + " NEW: " + mWallpaperTarget
10710 + " LOWER: " + mLowerWallpaperTarget);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010711 if (mLowerWallpaperTarget == null) {
10712 // Whoops, we don't need a special wallpaper animation.
10713 // Clear them out.
10714 forceHiding = false;
10715 for (i=N-1; i>=0; i--) {
10716 WindowState w = (WindowState)mWindows.get(i);
10717 if (w.mSurface != null) {
10718 final WindowManager.LayoutParams attrs = w.mAttrs;
Suchi Amalapurapuc03d28b2009-10-28 14:32:05 -070010719 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010720 if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010721 forceHiding = true;
10722 } else if (mPolicy.canBeForceHidden(w, attrs)) {
10723 if (!w.mAnimating) {
10724 // We set the animation above so it
10725 // is not yet running.
10726 w.clearAnimation();
10727 }
10728 }
10729 }
10730 }
10731 }
10732 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010733
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010734 if (wallpaperMayChange) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010735 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010736 "Wallpaper may change! Adjusting");
Dianne Hackborn16064f92010-03-25 00:47:24 -070010737 adjResult |= adjustWallpaperWindowsLocked();
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010738 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010739
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010740 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010741 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010742 "Wallpaper layer changed: assigning layers + relayout");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010743 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010744 assignLayersLocked();
10745 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010746 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010747 "Wallpaper visibility changed: relayout");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010748 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010749 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010750
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010751 if (mFocusMayChange) {
10752 mFocusMayChange = false;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010753 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010754 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010755 adjResult = 0;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010756 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010757 }
10758
10759 if (mLayoutNeeded) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010760 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010761 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010762
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010763 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
10764 + Integer.toHexString(changes));
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010765
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010766 } while (changes != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010767
10768 // THIRD LOOP: Update the surfaces of all windows.
10769
10770 final boolean someoneLosingFocus = mLosingFocus.size() != 0;
10771
10772 boolean obscured = false;
10773 boolean blurring = false;
10774 boolean dimming = false;
10775 boolean covered = false;
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070010776 boolean syswin = false;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010777 boolean backgroundFillerShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010778
Dianne Hackbornbdd52b22009-09-02 21:46:19 -070010779 final int N = mWindows.size();
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010781 for (i=N-1; i>=0; i--) {
10782 WindowState w = (WindowState)mWindows.get(i);
10783
10784 boolean displayed = false;
10785 final WindowManager.LayoutParams attrs = w.mAttrs;
10786 final int attrFlags = attrs.flags;
10787
10788 if (w.mSurface != null) {
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010789 // XXX NOTE: The logic here could be improved. We have
10790 // the decision about whether to resize a window separated
10791 // from whether to hide the surface. This can cause us to
10792 // resize a surface even if we are going to hide it. You
10793 // can see this by (1) holding device in landscape mode on
10794 // home screen; (2) tapping browser icon (device will rotate
10795 // to landscape; (3) tap home. The wallpaper will be resized
10796 // in step 2 but then immediately hidden, causing us to
10797 // have to resize and then redraw it again in step 3. It
10798 // would be nice to figure out how to avoid this, but it is
10799 // difficult because we do need to resize surfaces in some
10800 // cases while they are hidden such as when first showing a
10801 // window.
10802
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010803 w.computeShownFrameLocked();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010804 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 TAG, "Placing surface #" + i + " " + w.mSurface
10806 + ": new=" + w.mShownFrame + ", old="
10807 + w.mLastShownFrame);
10808
10809 boolean resize;
10810 int width, height;
10811 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
10812 resize = w.mLastRequestedWidth != w.mRequestedWidth ||
10813 w.mLastRequestedHeight != w.mRequestedHeight;
10814 // for a scaled surface, we just want to use
10815 // the requested size.
10816 width = w.mRequestedWidth;
10817 height = w.mRequestedHeight;
10818 w.mLastRequestedWidth = width;
10819 w.mLastRequestedHeight = height;
10820 w.mLastShownFrame.set(w.mShownFrame);
10821 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010822 if (SHOW_TRANSACTIONS) logSurface(w,
10823 "POS " + w.mShownFrame.left
10824 + ", " + w.mShownFrame.top, null);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010825 w.mSurfaceX = w.mShownFrame.left;
10826 w.mSurfaceY = w.mShownFrame.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
10828 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010829 Slog.w(TAG, "Error positioning surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830 if (!recoveringMemory) {
10831 reclaimSomeSurfaceMemoryLocked(w, "position");
10832 }
10833 }
10834 } else {
10835 resize = !w.mLastShownFrame.equals(w.mShownFrame);
10836 width = w.mShownFrame.width();
10837 height = w.mShownFrame.height();
10838 w.mLastShownFrame.set(w.mShownFrame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 }
10840
10841 if (resize) {
10842 if (width < 1) width = 1;
10843 if (height < 1) height = 1;
10844 if (w.mSurface != null) {
10845 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010846 if (SHOW_TRANSACTIONS) logSurface(w,
10847 "POS " + w.mShownFrame.left + ","
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010848 + w.mShownFrame.top + " SIZE "
10849 + w.mShownFrame.width() + "x"
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010850 + w.mShownFrame.height(), null);
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010851 w.mSurfaceResized = true;
Dianne Hackborn16064f92010-03-25 00:47:24 -070010852 w.mSurfaceW = width;
10853 w.mSurfaceH = height;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010854 w.mSurface.setSize(width, height);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010855 w.mSurfaceX = w.mShownFrame.left;
10856 w.mSurfaceY = w.mShownFrame.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010857 w.mSurface.setPosition(w.mShownFrame.left,
10858 w.mShownFrame.top);
10859 } catch (RuntimeException e) {
10860 // If something goes wrong with the surface (such
10861 // as running out of memory), don't take down the
10862 // entire system.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010863 Slog.e(TAG, "Failure updating surface of " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 + "size=(" + width + "x" + height
10865 + "), pos=(" + w.mShownFrame.left
10866 + "," + w.mShownFrame.top + ")", e);
10867 if (!recoveringMemory) {
10868 reclaimSomeSurfaceMemoryLocked(w, "size");
10869 }
10870 }
10871 }
10872 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010873 if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010874 w.mContentInsetsChanged =
10875 !w.mLastContentInsets.equals(w.mContentInsets);
10876 w.mVisibleInsetsChanged =
10877 !w.mLastVisibleInsets.equals(w.mVisibleInsets);
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010878 boolean configChanged =
10879 w.mConfiguration != mCurConfiguration
10880 && (w.mConfiguration == null
10881 || mCurConfiguration.diff(w.mConfiguration) != 0);
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010882 if (DEBUG_CONFIGURATION && configChanged) {
10883 Slog.v(TAG, "Win " + w + " config changed: "
10884 + mCurConfiguration);
10885 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010886 if (localLOGV) Slog.v(TAG, "Resizing " + w
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010887 + ": configChanged=" + configChanged
10888 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
Romain Guy06882f82009-06-10 13:36:04 -070010889 if (!w.mLastFrame.equals(w.mFrame)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010890 || w.mContentInsetsChanged
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010891 || w.mVisibleInsetsChanged
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010892 || w.mSurfaceResized
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010893 || configChanged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010894 w.mLastFrame.set(w.mFrame);
10895 w.mLastContentInsets.set(w.mContentInsets);
10896 w.mLastVisibleInsets.set(w.mVisibleInsets);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010897 // If the screen is currently frozen, then keep
10898 // it frozen until this window draws at its new
10899 // orientation.
10900 if (mDisplayFrozen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010901 if (DEBUG_ORIENTATION) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010902 "Resizing while display frozen: " + w);
10903 w.mOrientationChanging = true;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010904 if (!mWindowsFreezingScreen) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010905 mWindowsFreezingScreen = true;
10906 // XXX should probably keep timeout from
10907 // when we first froze the display.
10908 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10909 mH.sendMessageDelayed(mH.obtainMessage(
10910 H.WINDOW_FREEZE_TIMEOUT), 2000);
10911 }
10912 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913 // If the orientation is changing, then we need to
10914 // hold off on unfreezing the display until this
10915 // window has been redrawn; to do that, we need
10916 // to go through the process of getting informed
10917 // by the application when it has finished drawing.
10918 if (w.mOrientationChanging) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010919 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010920 "Orientation start waiting for draw in "
10921 + w + ", surface " + w.mSurface);
10922 w.mDrawPending = true;
10923 w.mCommitDrawPending = false;
10924 w.mReadyToShow = false;
10925 if (w.mAppToken != null) {
10926 w.mAppToken.allDrawn = false;
10927 }
10928 }
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010929 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010930 "Resizing window " + w + " to " + w.mFrame);
10931 mResizingWindows.add(w);
10932 } else if (w.mOrientationChanging) {
10933 if (!w.mDrawPending && !w.mCommitDrawPending) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010934 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010935 "Orientation not waiting for draw in "
10936 + w + ", surface " + w.mSurface);
10937 w.mOrientationChanging = false;
10938 }
10939 }
10940 }
10941
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010942 if (w.mAttachedHidden || !w.isReadyForDisplay()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010943 if (!w.mLastHidden) {
10944 //dump();
10945 w.mLastHidden = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010946 if (SHOW_TRANSACTIONS) logSurface(w,
10947 "HIDE (performLayout)", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010948 if (w.mSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010949 w.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010950 try {
10951 w.mSurface.hide();
10952 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010953 Slog.w(TAG, "Exception hiding surface in " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010954 }
10955 }
10956 mKeyWaiter.releasePendingPointerLocked(w.mSession);
10957 }
10958 // If we are waiting for this window to handle an
10959 // orientation change, well, it is hidden, so
10960 // doesn't really matter. Note that this does
10961 // introduce a potential glitch if the window
10962 // becomes unhidden before it has drawn for the
10963 // new orientation.
10964 if (w.mOrientationChanging) {
10965 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010966 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010967 "Orientation change skips hidden " + w);
10968 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010969 } else if (w.mLastLayer != w.mAnimLayer
10970 || w.mLastAlpha != w.mShownAlpha
10971 || w.mLastDsDx != w.mDsDx
10972 || w.mLastDtDx != w.mDtDx
10973 || w.mLastDsDy != w.mDsDy
10974 || w.mLastDtDy != w.mDtDy
10975 || w.mLastHScale != w.mHScale
10976 || w.mLastVScale != w.mVScale
10977 || w.mLastHidden) {
10978 displayed = true;
10979 w.mLastAlpha = w.mShownAlpha;
10980 w.mLastLayer = w.mAnimLayer;
10981 w.mLastDsDx = w.mDsDx;
10982 w.mLastDtDx = w.mDtDx;
10983 w.mLastDsDy = w.mDsDy;
10984 w.mLastDtDy = w.mDtDy;
10985 w.mLastHScale = w.mHScale;
10986 w.mLastVScale = w.mVScale;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010987 if (SHOW_TRANSACTIONS) logSurface(w,
10988 "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010989 + " matrix=[" + (w.mDsDx*w.mHScale)
10990 + "," + (w.mDtDx*w.mVScale)
10991 + "][" + (w.mDsDy*w.mHScale)
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010992 + "," + (w.mDtDy*w.mVScale) + "]", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010993 if (w.mSurface != null) {
10994 try {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010995 w.mSurfaceAlpha = w.mShownAlpha;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010996 w.mSurface.setAlpha(w.mShownAlpha);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010997 w.mSurfaceLayer = w.mAnimLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010998 w.mSurface.setLayer(w.mAnimLayer);
10999 w.mSurface.setMatrix(
11000 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
11001 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
11002 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011003 Slog.w(TAG, "Error updating surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011004 if (!recoveringMemory) {
11005 reclaimSomeSurfaceMemoryLocked(w, "update");
11006 }
11007 }
11008 }
11009
11010 if (w.mLastHidden && !w.mDrawPending
11011 && !w.mCommitDrawPending
11012 && !w.mReadyToShow) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080011013 if (SHOW_TRANSACTIONS) logSurface(w,
11014 "SHOW (performLayout)", null);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011015 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011016 + " during relayout");
11017 if (showSurfaceRobustlyLocked(w)) {
11018 w.mHasDrawn = true;
11019 w.mLastHidden = false;
11020 } else {
11021 w.mOrientationChanging = false;
11022 }
11023 }
11024 if (w.mSurface != null) {
11025 w.mToken.hasVisible = true;
11026 }
11027 } else {
11028 displayed = true;
11029 }
11030
11031 if (displayed) {
11032 if (!covered) {
Romain Guy980a9382010-01-08 15:06:28 -080011033 if (attrs.width == LayoutParams.MATCH_PARENT
11034 && attrs.height == LayoutParams.MATCH_PARENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011035 covered = true;
11036 }
11037 }
11038 if (w.mOrientationChanging) {
11039 if (w.mDrawPending || w.mCommitDrawPending) {
11040 orientationChangeComplete = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011041 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 "Orientation continue waiting for draw in " + w);
11043 } else {
11044 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011045 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011046 "Orientation change complete in " + w);
11047 }
11048 }
11049 w.mToken.hasVisible = true;
11050 }
11051 } else if (w.mOrientationChanging) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011052 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011053 "Orientation change skips hidden " + w);
11054 w.mOrientationChanging = false;
11055 }
11056
11057 final boolean canBeSeen = w.isDisplayedLw();
11058
11059 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
11060 focusDisplayed = true;
11061 }
11062
Dianne Hackborne9e9bca2009-08-18 15:08:22 -070011063 final boolean obscuredChanged = w.mObscured != obscured;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011065 // Update effect.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011066 if (!(w.mObscured=obscured)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011067 if (w.mSurface != null) {
11068 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
11069 holdScreen = w.mSession;
11070 }
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070011071 if (!syswin && w.mAttrs.screenBrightness >= 0
11072 && screenBrightness < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011073 screenBrightness = w.mAttrs.screenBrightness;
11074 }
Mike Lockwoodfb73f792009-11-20 11:31:18 -050011075 if (!syswin && w.mAttrs.buttonBrightness >= 0
11076 && buttonBrightness < 0) {
11077 buttonBrightness = w.mAttrs.buttonBrightness;
11078 }
Mike Lockwood46af6a82010-03-09 08:28:22 -050011079 if (canBeSeen
11080 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
11081 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
11082 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070011083 syswin = true;
11084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011085 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011086
Dianne Hackborn25994b42009-09-04 14:21:19 -070011087 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
11088 if (opaqueDrawn && w.isFullscreen(dw, dh)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011089 // This window completely covers everything behind it,
11090 // so we want to leave all of them as unblurred (for
11091 // performance reasons).
11092 obscured = true;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011093 } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011094 if (SHOW_TRANSACTIONS) Slog.d(TAG, "showing background filler");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011095 // This window is in compatibility mode, and needs background filler.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011096 obscured = true;
11097 if (mBackgroundFillerSurface == null) {
11098 try {
11099 mBackgroundFillerSurface = new Surface(mFxSession, 0,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080011100 "BackGroundFiller",
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011101 0, dw, dh,
11102 PixelFormat.OPAQUE,
11103 Surface.FX_SURFACE_NORMAL);
11104 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011105 Slog.e(TAG, "Exception creating filler surface", e);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011106 }
11107 }
11108 try {
11109 mBackgroundFillerSurface.setPosition(0, 0);
11110 mBackgroundFillerSurface.setSize(dw, dh);
11111 // Using the same layer as Dim because they will never be shown at the
11112 // same time.
11113 mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
11114 mBackgroundFillerSurface.show();
11115 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011116 Slog.e(TAG, "Exception showing filler surface");
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011117 }
11118 backgroundFillerShown = true;
11119 mBackgroundFillerShown = true;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011120 } else if (canBeSeen && !obscured &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011121 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011122 if (localLOGV) Slog.v(TAG, "Win " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011123 + ": blurring=" + blurring
11124 + " obscured=" + obscured
11125 + " displayed=" + displayed);
11126 if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
11127 if (!dimming) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011128 //Slog.i(TAG, "DIM BEHIND: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129 dimming = true;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011130 if (mDimAnimator == null) {
11131 mDimAnimator = new DimAnimator(mFxSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011132 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011133 mDimAnimator.show(dw, dh);
Dianne Hackborn16064f92010-03-25 00:47:24 -070011134 mDimAnimator.updateParameters(w, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011135 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011136 }
11137 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
11138 if (!blurring) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011139 //Slog.i(TAG, "BLUR BEHIND: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011140 blurring = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011141 if (mBlurSurface == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011142 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011143 + mBlurSurface + ": CREATE");
11144 try {
Romain Guy06882f82009-06-10 13:36:04 -070011145 mBlurSurface = new Surface(mFxSession, 0,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080011146 "BlurSurface",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011147 -1, 16, 16,
11148 PixelFormat.OPAQUE,
11149 Surface.FX_SURFACE_BLUR);
11150 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011151 Slog.e(TAG, "Exception creating Blur surface", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011152 }
11153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 if (mBlurSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070011155 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
11156 + mBlurSurface + ": pos=(0,0) (" +
11157 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011158 mBlurSurface.setPosition(0, 0);
11159 mBlurSurface.setSize(dw, dh);
Dianne Hackborn16064f92010-03-25 00:47:24 -070011160 mBlurSurface.setLayer(w.mAnimLayer-2);
11161 if (!mBlurShown) {
11162 try {
11163 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
11164 + mBlurSurface + ": SHOW");
11165 mBlurSurface.show();
11166 } catch (RuntimeException e) {
11167 Slog.w(TAG, "Failure showing blur surface", e);
11168 }
11169 mBlurShown = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011170 }
11171 }
11172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011173 }
11174 }
11175 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011176
Dianne Hackborne9e9bca2009-08-18 15:08:22 -070011177 if (obscuredChanged && mWallpaperTarget == w) {
11178 // This is the wallpaper target and its obscured state
11179 // changed... make sure the current wallaper's visibility
11180 // has been updated accordingly.
11181 updateWallpaperVisibilityLocked();
11182 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011183 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011184
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011185 if (backgroundFillerShown == false && mBackgroundFillerShown) {
11186 mBackgroundFillerShown = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011187 if (SHOW_TRANSACTIONS) Slog.d(TAG, "hiding background filler");
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011188 try {
11189 mBackgroundFillerSurface.hide();
11190 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011191 Slog.e(TAG, "Exception hiding filler surface", e);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070011192 }
11193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011194
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011195 if (mDimAnimator != null && mDimAnimator.mDimShown) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -080011196 animating |= mDimAnimator.updateSurface(dimming, currentTime,
11197 mDisplayFrozen || !mPolicy.isScreenOn());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 }
Romain Guy06882f82009-06-10 13:36:04 -070011199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011200 if (!blurring && mBlurShown) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011201 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " + mBlurSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011202 + ": HIDE");
11203 try {
11204 mBlurSurface.hide();
11205 } catch (IllegalArgumentException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011206 Slog.w(TAG, "Illegal argument exception hiding blur surface");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011207 }
11208 mBlurShown = false;
11209 }
11210
Joe Onorato8a9b2202010-02-26 18:56:32 -080011211 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011212 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011213 Slog.e(TAG, "Unhandled exception in Window Manager", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 }
11215
11216 Surface.closeTransaction();
Romain Guy06882f82009-06-10 13:36:04 -070011217
Joe Onorato8a9b2202010-02-26 18:56:32 -080011218 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011219 "With display frozen, orientationChangeComplete="
11220 + orientationChangeComplete);
11221 if (orientationChangeComplete) {
11222 if (mWindowsFreezingScreen) {
11223 mWindowsFreezingScreen = false;
11224 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
11225 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011226 stopFreezingDisplayLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 }
Romain Guy06882f82009-06-10 13:36:04 -070011228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011229 i = mResizingWindows.size();
11230 if (i > 0) {
11231 do {
11232 i--;
11233 WindowState win = mResizingWindows.get(i);
11234 try {
Dianne Hackbornac3587d2010-03-11 11:12:11 -080011235 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
11236 "Reporting new frame to " + win + ": " + win.mFrame);
Dianne Hackborn694f79b2010-03-17 19:44:59 -070011237 int diff = 0;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011238 boolean configChanged =
11239 win.mConfiguration != mCurConfiguration
11240 && (win.mConfiguration == null
Dianne Hackborn694f79b2010-03-17 19:44:59 -070011241 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0);
11242 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
11243 && configChanged) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011244 Slog.i(TAG, "Sending new config to window " + win + ": "
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011245 + win.mFrame.width() + "x" + win.mFrame.height()
Dianne Hackborn694f79b2010-03-17 19:44:59 -070011246 + " / " + mCurConfiguration + " / 0x"
11247 + Integer.toHexString(diff));
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011248 }
Dianne Hackborn694f79b2010-03-17 19:44:59 -070011249 win.mConfiguration = mCurConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011250 win.mClient.resized(win.mFrame.width(),
11251 win.mFrame.height(), win.mLastContentInsets,
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011252 win.mLastVisibleInsets, win.mDrawPending,
11253 configChanged ? win.mConfiguration : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011254 win.mContentInsetsChanged = false;
11255 win.mVisibleInsetsChanged = false;
Dianne Hackbornac3587d2010-03-11 11:12:11 -080011256 win.mSurfaceResized = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011257 } catch (RemoteException e) {
11258 win.mOrientationChanging = false;
11259 }
11260 } while (i > 0);
11261 mResizingWindows.clear();
11262 }
Romain Guy06882f82009-06-10 13:36:04 -070011263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011264 // Destroy the surface of any windows that are no longer visible.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011265 boolean wallpaperDestroyed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 i = mDestroySurface.size();
11267 if (i > 0) {
11268 do {
11269 i--;
11270 WindowState win = mDestroySurface.get(i);
11271 win.mDestroying = false;
11272 if (mInputMethodWindow == win) {
11273 mInputMethodWindow = null;
11274 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011275 if (win == mWallpaperTarget) {
11276 wallpaperDestroyed = true;
11277 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 win.destroySurfaceLocked();
11279 } while (i > 0);
11280 mDestroySurface.clear();
11281 }
11282
11283 // Time to remove any exiting tokens?
11284 for (i=mExitingTokens.size()-1; i>=0; i--) {
11285 WindowToken token = mExitingTokens.get(i);
11286 if (!token.hasVisible) {
11287 mExitingTokens.remove(i);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070011288 if (token.windowType == TYPE_WALLPAPER) {
11289 mWallpaperTokens.remove(token);
11290 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011291 }
11292 }
11293
11294 // Time to remove any exiting applications?
11295 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
11296 AppWindowToken token = mExitingAppTokens.get(i);
11297 if (!token.hasVisible && !mClosingApps.contains(token)) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -070011298 // Make sure there is no animation running on this token,
11299 // so any windows associated with it will be removed as
11300 // soon as their animations are complete
11301 token.animation = null;
11302 token.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011303 mAppTokens.remove(token);
11304 mExitingAppTokens.remove(i);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011305 if (mLastEnterAnimToken == token) {
11306 mLastEnterAnimToken = null;
11307 mLastEnterAnimParams = null;
11308 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011309 }
11310 }
11311
Dianne Hackborna8f60182009-09-01 19:01:50 -070011312 boolean needRelayout = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011313
Dianne Hackborna8f60182009-09-01 19:01:50 -070011314 if (!animating && mAppTransitionRunning) {
11315 // We have finished the animation of an app transition. To do
11316 // this, we have delayed a lot of operations like showing and
11317 // hiding apps, moving apps in Z-order, etc. The app token list
11318 // reflects the correct Z-order, but the window list may now
11319 // be out of sync with it. So here we will just rebuild the
11320 // entire app window list. Fun!
11321 mAppTransitionRunning = false;
11322 needRelayout = true;
11323 rebuildAppWindowListLocked();
Dianne Hackborn16064f92010-03-25 00:47:24 -070011324 assignLayersLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070011325 // Clear information about apps that were moving.
11326 mToBottomApps.clear();
11327 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011328
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011329 if (focusDisplayed) {
11330 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
11331 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011332 if (wallpaperDestroyed) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011333 needRelayout = adjustWallpaperWindowsLocked() != 0;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011334 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070011335 if (needRelayout) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070011336 requestAnimationLocked(0);
11337 } else if (animating) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011338 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
11339 }
Jeff Brown8e03b752010-06-13 19:16:55 -070011340 setHoldScreenLocked(holdScreen != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011341 if (screenBrightness < 0 || screenBrightness > 1.0f) {
11342 mPowerManager.setScreenBrightnessOverride(-1);
11343 } else {
11344 mPowerManager.setScreenBrightnessOverride((int)
11345 (screenBrightness * Power.BRIGHTNESS_ON));
11346 }
Mike Lockwoodfb73f792009-11-20 11:31:18 -050011347 if (buttonBrightness < 0 || buttonBrightness > 1.0f) {
11348 mPowerManager.setButtonBrightnessOverride(-1);
11349 } else {
11350 mPowerManager.setButtonBrightnessOverride((int)
11351 (buttonBrightness * Power.BRIGHTNESS_ON));
11352 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011353 if (holdScreen != mHoldingScreenOn) {
11354 mHoldingScreenOn = holdScreen;
11355 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
11356 mH.sendMessage(m);
11357 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011358
Dianne Hackborn93e462b2009-09-15 22:50:40 -070011359 if (mTurnOnScreen) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -080011360 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
Dianne Hackborn93e462b2009-09-15 22:50:40 -070011361 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
11362 LocalPowerManager.BUTTON_EVENT, true);
11363 mTurnOnScreen = false;
11364 }
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -080011365
11366 // Check to see if we are now in a state where the screen should
11367 // be enabled, because the window obscured flags have changed.
11368 enableScreenIfNeededLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011369 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070011370
11371 /**
11372 * Must be called with the main window manager lock held.
11373 */
11374 void setHoldScreenLocked(boolean holding) {
11375 boolean state = mHoldingScreenWakeLock.isHeld();
11376 if (holding != state) {
11377 if (holding) {
11378 mHoldingScreenWakeLock.acquire();
11379 } else {
11380 mPolicy.screenOnStoppedLw();
11381 mHoldingScreenWakeLock.release();
11382 }
11383 }
11384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011385
11386 void requestAnimationLocked(long delay) {
11387 if (!mAnimationPending) {
11388 mAnimationPending = true;
11389 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
11390 }
11391 }
Romain Guy06882f82009-06-10 13:36:04 -070011392
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011393 /**
11394 * Have the surface flinger show a surface, robustly dealing with
11395 * error conditions. In particular, if there is not enough memory
11396 * to show the surface, then we will try to get rid of other surfaces
11397 * in order to succeed.
Romain Guy06882f82009-06-10 13:36:04 -070011398 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011399 * @return Returns true if the surface was successfully shown.
11400 */
11401 boolean showSurfaceRobustlyLocked(WindowState win) {
11402 try {
11403 if (win.mSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070011404 win.mSurfaceShown = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011405 win.mSurface.show();
Dianne Hackborn93e462b2009-09-15 22:50:40 -070011406 if (win.mTurnOnScreen) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -080011407 if (DEBUG_VISIBILITY) Slog.v(TAG,
11408 "Show surface turning screen on: " + win);
Dianne Hackborn93e462b2009-09-15 22:50:40 -070011409 win.mTurnOnScreen = false;
11410 mTurnOnScreen = true;
11411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011412 }
11413 return true;
11414 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011415 Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011416 }
Romain Guy06882f82009-06-10 13:36:04 -070011417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011418 reclaimSomeSurfaceMemoryLocked(win, "show");
Romain Guy06882f82009-06-10 13:36:04 -070011419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011420 return false;
11421 }
Romain Guy06882f82009-06-10 13:36:04 -070011422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011423 void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
11424 final Surface surface = win.mSurface;
Romain Guy06882f82009-06-10 13:36:04 -070011425
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011426 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011427 win.mSession.mPid, operation);
Romain Guy06882f82009-06-10 13:36:04 -070011428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011429 if (mForceRemoves == null) {
11430 mForceRemoves = new ArrayList<WindowState>();
11431 }
Romain Guy06882f82009-06-10 13:36:04 -070011432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011433 long callingIdentity = Binder.clearCallingIdentity();
11434 try {
11435 // There was some problem... first, do a sanity check of the
11436 // window list to make sure we haven't left any dangling surfaces
11437 // around.
11438 int N = mWindows.size();
11439 boolean leakedSurface = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011440 Slog.i(TAG, "Out of memory for surface! Looking for leaks...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011441 for (int i=0; i<N; i++) {
11442 WindowState ws = (WindowState)mWindows.get(i);
11443 if (ws.mSurface != null) {
11444 if (!mSessions.contains(ws.mSession)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011445 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011446 + ws + " surface=" + ws.mSurface
11447 + " token=" + win.mToken
11448 + " pid=" + ws.mSession.mPid
11449 + " uid=" + ws.mSession.mUid);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011450 ws.mSurface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070011451 ws.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011452 ws.mSurface = null;
11453 mForceRemoves.add(ws);
11454 i--;
11455 N--;
11456 leakedSurface = true;
11457 } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011458 Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011459 + ws + " surface=" + ws.mSurface
11460 + " token=" + win.mAppToken);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011461 ws.mSurface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070011462 ws.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011463 ws.mSurface = null;
11464 leakedSurface = true;
11465 }
11466 }
11467 }
Romain Guy06882f82009-06-10 13:36:04 -070011468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011469 boolean killedApps = false;
11470 if (!leakedSurface) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011471 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011472 SparseIntArray pidCandidates = new SparseIntArray();
11473 for (int i=0; i<N; i++) {
11474 WindowState ws = (WindowState)mWindows.get(i);
11475 if (ws.mSurface != null) {
11476 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
11477 }
11478 }
11479 if (pidCandidates.size() > 0) {
11480 int[] pids = new int[pidCandidates.size()];
11481 for (int i=0; i<pids.length; i++) {
11482 pids[i] = pidCandidates.keyAt(i);
11483 }
11484 try {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070011485 if (mActivityManager.killPids(pids, "Free memory")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011486 killedApps = true;
11487 }
11488 } catch (RemoteException e) {
11489 }
11490 }
11491 }
Romain Guy06882f82009-06-10 13:36:04 -070011492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011493 if (leakedSurface || killedApps) {
11494 // We managed to reclaim some memory, so get rid of the trouble
11495 // surface and ask the app to request another one.
Joe Onorato8a9b2202010-02-26 18:56:32 -080011496 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011497 if (surface != null) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011498 surface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070011499 win.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011500 win.mSurface = null;
11501 }
Romain Guy06882f82009-06-10 13:36:04 -070011502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011503 try {
11504 win.mClient.dispatchGetNewSurface();
11505 } catch (RemoteException e) {
11506 }
11507 }
11508 } finally {
11509 Binder.restoreCallingIdentity(callingIdentity);
11510 }
11511 }
Romain Guy06882f82009-06-10 13:36:04 -070011512
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011513 private boolean updateFocusedWindowLocked(int mode) {
11514 WindowState newFocus = computeFocusedWindowLocked();
11515 if (mCurrentFocus != newFocus) {
11516 // This check makes sure that we don't already have the focus
11517 // change message pending.
11518 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
11519 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
Joe Onorato8a9b2202010-02-26 18:56:32 -080011520 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011521 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
11522 final WindowState oldFocus = mCurrentFocus;
11523 mCurrentFocus = newFocus;
11524 mLosingFocus.remove(newFocus);
Romain Guy06882f82009-06-10 13:36:04 -070011525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011526 final WindowState imWindow = mInputMethodWindow;
11527 if (newFocus != imWindow && oldFocus != imWindow) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080011528 if (moveInputMethodWindowsIfNeededLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011529 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080011530 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
11531 mLayoutNeeded = true;
11532 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011533 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
11534 performLayoutLockedInner();
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080011535 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
11536 // Client will do the layout, but we need to assign layers
11537 // for handleNewWindowLocked() below.
11538 assignLayersLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011539 }
11540 }
Romain Guy06882f82009-06-10 13:36:04 -070011541
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080011542 if (newFocus != null && mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
11543 mKeyWaiter.handleNewWindowLocked(newFocus);
11544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011545 return true;
11546 }
11547 return false;
11548 }
11549
11550 private WindowState computeFocusedWindowLocked() {
11551 WindowState result = null;
11552 WindowState win;
11553
11554 int i = mWindows.size() - 1;
11555 int nextAppIndex = mAppTokens.size()-1;
11556 WindowToken nextApp = nextAppIndex >= 0
11557 ? mAppTokens.get(nextAppIndex) : null;
11558
11559 while (i >= 0) {
11560 win = (WindowState)mWindows.get(i);
11561
Joe Onorato8a9b2202010-02-26 18:56:32 -080011562 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011563 TAG, "Looking for focus: " + i
11564 + " = " + win
11565 + ", flags=" + win.mAttrs.flags
11566 + ", canReceive=" + win.canReceiveKeys());
11567
11568 AppWindowToken thisApp = win.mAppToken;
Romain Guy06882f82009-06-10 13:36:04 -070011569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011570 // If this window's application has been removed, just skip it.
11571 if (thisApp != null && thisApp.removed) {
11572 i--;
11573 continue;
11574 }
Romain Guy06882f82009-06-10 13:36:04 -070011575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011576 // If there is a focused app, don't allow focus to go to any
11577 // windows below it. If this is an application window, step
11578 // through the app tokens until we find its app.
11579 if (thisApp != null && nextApp != null && thisApp != nextApp
11580 && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
11581 int origAppIndex = nextAppIndex;
11582 while (nextAppIndex > 0) {
11583 if (nextApp == mFocusedApp) {
11584 // Whoops, we are below the focused app... no focus
11585 // for you!
Joe Onorato8a9b2202010-02-26 18:56:32 -080011586 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011587 TAG, "Reached focused app: " + mFocusedApp);
11588 return null;
11589 }
11590 nextAppIndex--;
11591 nextApp = mAppTokens.get(nextAppIndex);
11592 if (nextApp == thisApp) {
11593 break;
11594 }
11595 }
11596 if (thisApp != nextApp) {
11597 // Uh oh, the app token doesn't exist! This shouldn't
11598 // happen, but if it does we can get totally hosed...
11599 // so restart at the original app.
11600 nextAppIndex = origAppIndex;
11601 nextApp = mAppTokens.get(nextAppIndex);
11602 }
11603 }
11604
11605 // Dispatch to this window if it is wants key events.
11606 if (win.canReceiveKeys()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011607 if (DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011608 TAG, "Found focus @ " + i + " = " + win);
11609 result = win;
11610 break;
11611 }
11612
11613 i--;
11614 }
11615
11616 return result;
11617 }
11618
11619 private void startFreezingDisplayLocked() {
11620 if (mDisplayFrozen) {
Chris Tate2ad63a92009-03-25 17:36:48 -070011621 // Freezing the display also suspends key event delivery, to
11622 // keep events from going astray while the display is reconfigured.
11623 // If someone has changed orientation again while the screen is
11624 // still frozen, the events will continue to be blocked while the
11625 // successive orientation change is processed. To prevent spurious
11626 // ANRs, we reset the event dispatch timeout in this case.
11627 synchronized (mKeyWaiter) {
11628 mKeyWaiter.mWasFrozen = true;
11629 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011630 return;
11631 }
Romain Guy06882f82009-06-10 13:36:04 -070011632
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011633 mScreenFrozenLock.acquire();
Romain Guy06882f82009-06-10 13:36:04 -070011634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011635 long now = SystemClock.uptimeMillis();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011636 //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011637 if (mFreezeGcPending != 0) {
11638 if (now > (mFreezeGcPending+1000)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011639 //Slog.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011640 mH.removeMessages(H.FORCE_GC);
11641 Runtime.getRuntime().gc();
11642 mFreezeGcPending = now;
11643 }
11644 } else {
11645 mFreezeGcPending = now;
11646 }
Romain Guy06882f82009-06-10 13:36:04 -070011647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011648 mDisplayFrozen = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -070011649 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
11650 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011651 mNextAppTransitionPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011652 mAppTransitionReady = true;
11653 }
Romain Guy06882f82009-06-10 13:36:04 -070011654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011655 if (PROFILE_ORIENTATION) {
11656 File file = new File("/data/system/frozen");
11657 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
11658 }
11659 Surface.freezeDisplay(0);
11660 }
Romain Guy06882f82009-06-10 13:36:04 -070011661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011662 private void stopFreezingDisplayLocked() {
11663 if (!mDisplayFrozen) {
11664 return;
11665 }
Romain Guy06882f82009-06-10 13:36:04 -070011666
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011667 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
11668 return;
11669 }
11670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011671 mDisplayFrozen = false;
11672 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
11673 if (PROFILE_ORIENTATION) {
11674 Debug.stopMethodTracing();
11675 }
11676 Surface.unfreezeDisplay(0);
Romain Guy06882f82009-06-10 13:36:04 -070011677
Chris Tate2ad63a92009-03-25 17:36:48 -070011678 // Reset the key delivery timeout on unfreeze, too. We force a wakeup here
11679 // too because regular key delivery processing should resume immediately.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011680 synchronized (mKeyWaiter) {
11681 mKeyWaiter.mWasFrozen = true;
11682 mKeyWaiter.notifyAll();
11683 }
11684
Christopher Tateb696aee2010-04-02 19:08:30 -070011685 // While the display is frozen we don't re-compute the orientation
11686 // to avoid inconsistent states. However, something interesting
11687 // could have actually changed during that time so re-evaluate it
11688 // now to catch that.
11689 if (updateOrientationFromAppTokensLocked()) {
11690 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
11691 }
11692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011693 // A little kludge: a lot could have happened while the
11694 // display was frozen, so now that we are coming back we
11695 // do a gc so that any remote references the system
11696 // processes holds on others can be released if they are
11697 // no longer needed.
11698 mH.removeMessages(H.FORCE_GC);
11699 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
11700 2000);
Romain Guy06882f82009-06-10 13:36:04 -070011701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011702 mScreenFrozenLock.release();
11703 }
Romain Guy06882f82009-06-10 13:36:04 -070011704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011705 @Override
11706 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
11707 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
11708 != PackageManager.PERMISSION_GRANTED) {
11709 pw.println("Permission Denial: can't dump WindowManager from from pid="
11710 + Binder.getCallingPid()
11711 + ", uid=" + Binder.getCallingUid());
11712 return;
11713 }
Romain Guy06882f82009-06-10 13:36:04 -070011714
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070011715 if (ENABLE_NATIVE_INPUT_DISPATCH) {
11716 pw.println("Input Dispatcher State:");
11717 mInputManager.dump(pw);
11718 } else {
11719 pw.println("Input State:");
11720 mQueue.dump(pw, " ");
11721 }
Dianne Hackborna2e92262010-03-02 17:19:29 -080011722 pw.println(" ");
11723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011724 synchronized(mWindowMap) {
11725 pw.println("Current Window Manager state:");
11726 for (int i=mWindows.size()-1; i>=0; i--) {
11727 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011728 pw.print(" Window #"); pw.print(i); pw.print(' ');
11729 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 w.dump(pw, " ");
11731 }
11732 if (mInputMethodDialogs.size() > 0) {
11733 pw.println(" ");
11734 pw.println(" Input method dialogs:");
11735 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
11736 WindowState w = mInputMethodDialogs.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011737 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011738 }
11739 }
11740 if (mPendingRemove.size() > 0) {
11741 pw.println(" ");
11742 pw.println(" Remove pending for:");
11743 for (int i=mPendingRemove.size()-1; i>=0; i--) {
11744 WindowState w = mPendingRemove.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011745 pw.print(" Remove #"); pw.print(i); pw.print(' ');
11746 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011747 w.dump(pw, " ");
11748 }
11749 }
11750 if (mForceRemoves != null && mForceRemoves.size() > 0) {
11751 pw.println(" ");
11752 pw.println(" Windows force removing:");
11753 for (int i=mForceRemoves.size()-1; i>=0; i--) {
11754 WindowState w = mForceRemoves.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011755 pw.print(" Removing #"); pw.print(i); pw.print(' ');
11756 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011757 w.dump(pw, " ");
11758 }
11759 }
11760 if (mDestroySurface.size() > 0) {
11761 pw.println(" ");
11762 pw.println(" Windows waiting to destroy their surface:");
11763 for (int i=mDestroySurface.size()-1; i>=0; i--) {
11764 WindowState w = mDestroySurface.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011765 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
11766 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011767 w.dump(pw, " ");
11768 }
11769 }
11770 if (mLosingFocus.size() > 0) {
11771 pw.println(" ");
11772 pw.println(" Windows losing focus:");
11773 for (int i=mLosingFocus.size()-1; i>=0; i--) {
11774 WindowState w = mLosingFocus.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011775 pw.print(" Losing #"); pw.print(i); pw.print(' ');
11776 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011777 w.dump(pw, " ");
11778 }
11779 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011780 if (mResizingWindows.size() > 0) {
11781 pw.println(" ");
11782 pw.println(" Windows waiting to resize:");
11783 for (int i=mResizingWindows.size()-1; i>=0; i--) {
11784 WindowState w = mResizingWindows.get(i);
11785 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
11786 pw.print(w); pw.println(":");
11787 w.dump(pw, " ");
11788 }
11789 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011790 if (mSessions.size() > 0) {
11791 pw.println(" ");
11792 pw.println(" All active sessions:");
11793 Iterator<Session> it = mSessions.iterator();
11794 while (it.hasNext()) {
11795 Session s = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011796 pw.print(" Session "); pw.print(s); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011797 s.dump(pw, " ");
11798 }
11799 }
11800 if (mTokenMap.size() > 0) {
11801 pw.println(" ");
11802 pw.println(" All tokens:");
11803 Iterator<WindowToken> it = mTokenMap.values().iterator();
11804 while (it.hasNext()) {
11805 WindowToken token = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011806 pw.print(" Token "); pw.print(token.token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011807 token.dump(pw, " ");
11808 }
11809 }
11810 if (mTokenList.size() > 0) {
11811 pw.println(" ");
11812 pw.println(" Window token list:");
11813 for (int i=0; i<mTokenList.size(); i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011814 pw.print(" #"); pw.print(i); pw.print(": ");
11815 pw.println(mTokenList.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011816 }
11817 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070011818 if (mWallpaperTokens.size() > 0) {
11819 pw.println(" ");
11820 pw.println(" Wallpaper tokens:");
11821 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
11822 WindowToken token = mWallpaperTokens.get(i);
11823 pw.print(" Wallpaper #"); pw.print(i);
11824 pw.print(' '); pw.print(token); pw.println(':');
11825 token.dump(pw, " ");
11826 }
11827 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011828 if (mAppTokens.size() > 0) {
11829 pw.println(" ");
11830 pw.println(" Application tokens in Z order:");
11831 for (int i=mAppTokens.size()-1; i>=0; i--) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011832 pw.print(" App #"); pw.print(i); pw.print(": ");
11833 pw.println(mAppTokens.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011834 }
11835 }
11836 if (mFinishedStarting.size() > 0) {
11837 pw.println(" ");
11838 pw.println(" Finishing start of application tokens:");
11839 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
11840 WindowToken token = mFinishedStarting.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011841 pw.print(" Finished Starting #"); pw.print(i);
11842 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011843 token.dump(pw, " ");
11844 }
11845 }
11846 if (mExitingTokens.size() > 0) {
11847 pw.println(" ");
11848 pw.println(" Exiting tokens:");
11849 for (int i=mExitingTokens.size()-1; i>=0; i--) {
11850 WindowToken token = mExitingTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011851 pw.print(" Exiting #"); pw.print(i);
11852 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011853 token.dump(pw, " ");
11854 }
11855 }
11856 if (mExitingAppTokens.size() > 0) {
11857 pw.println(" ");
11858 pw.println(" Exiting application tokens:");
11859 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
11860 WindowToken token = mExitingAppTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011861 pw.print(" Exiting App #"); pw.print(i);
11862 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011863 token.dump(pw, " ");
11864 }
11865 }
11866 pw.println(" ");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011867 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
11868 pw.print(" mLastFocus="); pw.println(mLastFocus);
11869 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
11870 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
11871 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
Dianne Hackbornf21adf62009-08-13 10:20:21 -070011872 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
Dianne Hackborn284ac932009-08-28 10:34:25 -070011873 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
11874 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
11875 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
11876 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011877 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration);
11878 pw.print(" mInTouchMode="); pw.print(mInTouchMode);
11879 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011880 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
11881 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
11882 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
11883 pw.print(" mBlurShown="); pw.println(mBlurShown);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011884 if (mDimAnimator != null) {
11885 mDimAnimator.printTo(pw);
11886 } else {
Dianne Hackborna2e92262010-03-02 17:19:29 -080011887 pw.println( " no DimAnimator ");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011888 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011889 pw.print(" mInputMethodAnimLayerAdjustment=");
Dianne Hackborn759a39e2009-08-09 17:20:27 -070011890 pw.print(mInputMethodAnimLayerAdjustment);
11891 pw.print(" mWallpaperAnimLayerAdjustment=");
11892 pw.println(mWallpaperAnimLayerAdjustment);
Dianne Hackborn284ac932009-08-28 10:34:25 -070011893 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
11894 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011895 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
11896 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011897 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
11898 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011899 pw.print(" mRotation="); pw.print(mRotation);
11900 pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
11901 pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
11902 pw.print(" mAnimationPending="); pw.print(mAnimationPending);
11903 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
11904 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
11905 pw.print(" mNextAppTransition=0x");
11906 pw.print(Integer.toHexString(mNextAppTransition));
11907 pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
Dianne Hackborna8f60182009-09-01 19:01:50 -070011908 pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011909 pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011910 if (mNextAppTransitionPackage != null) {
11911 pw.print(" mNextAppTransitionPackage=");
11912 pw.print(mNextAppTransitionPackage);
11913 pw.print(", mNextAppTransitionEnter=0x");
11914 pw.print(Integer.toHexString(mNextAppTransitionEnter));
11915 pw.print(", mNextAppTransitionExit=0x");
11916 pw.print(Integer.toHexString(mNextAppTransitionExit));
11917 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011918 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
11919 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011920 if (mLastEnterAnimToken != null || mLastEnterAnimToken != null) {
11921 pw.print(" mLastEnterAnimToken="); pw.print(mLastEnterAnimToken);
11922 pw.print(", mLastEnterAnimParams="); pw.println(mLastEnterAnimParams);
11923 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011924 if (mOpeningApps.size() > 0) {
11925 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
11926 }
11927 if (mClosingApps.size() > 0) {
11928 pw.print(" mClosingApps="); pw.println(mClosingApps);
11929 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070011930 if (mToTopApps.size() > 0) {
11931 pw.print(" mToTopApps="); pw.println(mToTopApps);
11932 }
11933 if (mToBottomApps.size() > 0) {
11934 pw.print(" mToBottomApps="); pw.println(mToBottomApps);
11935 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011936 pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth());
11937 pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011938 pw.println(" KeyWaiter state:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011939 pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin);
11940 pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
11941 pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished);
11942 pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
11943 pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
11944 pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011945 }
11946 }
11947
11948 public void monitor() {
11949 synchronized (mWindowMap) { }
Mike Lockwood983ee092009-11-22 01:42:24 -050011950 synchronized (mKeyguardTokenWatcher) { }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011951 synchronized (mKeyWaiter) { }
11952 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011953
Dianne Hackbornddca3ee2009-07-23 19:01:31 -070011954 public void virtualKeyFeedback(KeyEvent event) {
11955 mPolicy.keyFeedbackFromInput(event);
11956 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011957
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011958 /**
11959 * DimAnimator class that controls the dim animation. This holds the surface and
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011960 * all state used for dim animation.
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011961 */
11962 private static class DimAnimator {
11963 Surface mDimSurface;
11964 boolean mDimShown = false;
11965 float mDimCurrentAlpha;
11966 float mDimTargetAlpha;
11967 float mDimDeltaPerMs;
11968 long mLastDimAnimTime;
Dianne Hackbornf83c5552010-03-31 22:19:32 -070011969
11970 int mLastDimWidth, mLastDimHeight;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011971
11972 DimAnimator (SurfaceSession session) {
11973 if (mDimSurface == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011974 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011975 + mDimSurface + ": CREATE");
11976 try {
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080011977 mDimSurface = new Surface(session, 0,
11978 "DimSurface",
11979 -1, 16, 16, PixelFormat.OPAQUE,
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011980 Surface.FX_SURFACE_DIM);
Maciej Białka9ee5c222010-03-24 10:25:40 +010011981 mDimSurface.setAlpha(0.0f);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011982 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011983 Slog.e(TAG, "Exception creating Dim surface", e);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011984 }
11985 }
11986 }
11987
11988 /**
11989 * Show the dim surface.
11990 */
11991 void show(int dw, int dh) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070011992 if (!mDimShown) {
11993 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
11994 dw + "x" + dh + ")");
11995 mDimShown = true;
11996 try {
Dianne Hackbornf83c5552010-03-31 22:19:32 -070011997 mLastDimWidth = dw;
11998 mLastDimHeight = dh;
Dianne Hackborn16064f92010-03-25 00:47:24 -070011999 mDimSurface.setPosition(0, 0);
12000 mDimSurface.setSize(dw, dh);
12001 mDimSurface.show();
12002 } catch (RuntimeException e) {
12003 Slog.w(TAG, "Failure showing dim surface", e);
12004 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -070012005 } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
12006 mLastDimWidth = dw;
12007 mLastDimHeight = dh;
12008 mDimSurface.setSize(dw, dh);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012009 }
12010 }
12011
12012 /**
12013 * Set's the dim surface's layer and update dim parameters that will be used in
12014 * {@link updateSurface} after all windows are examined.
12015 */
12016 void updateParameters(WindowState w, long currentTime) {
12017 mDimSurface.setLayer(w.mAnimLayer-1);
12018
12019 final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012020 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070012021 + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012022 if (mDimTargetAlpha != target) {
12023 // If the desired dim level has changed, then
12024 // start an animation to it.
12025 mLastDimAnimTime = currentTime;
12026 long duration = (w.mAnimating && w.mAnimation != null)
12027 ? w.mAnimation.computeDurationHint()
12028 : DEFAULT_DIM_DURATION;
12029 if (target > mDimTargetAlpha) {
12030 // This is happening behind the activity UI,
12031 // so we can make it run a little longer to
12032 // give a stronger impression without disrupting
12033 // the user.
12034 duration *= DIM_DURATION_MULTIPLIER;
12035 }
12036 if (duration < 1) {
12037 // Don't divide by zero
12038 duration = 1;
12039 }
12040 mDimTargetAlpha = target;
12041 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
12042 }
12043 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080012044
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012045 /**
12046 * Updating the surface's alpha. Returns true if the animation continues, or returns
12047 * false when the animation is finished and the dim surface is hidden.
12048 */
12049 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
12050 if (!dimming) {
12051 if (mDimTargetAlpha != 0) {
12052 mLastDimAnimTime = currentTime;
12053 mDimTargetAlpha = 0;
12054 mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
12055 }
12056 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080012057
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012058 boolean animating = false;
12059 if (mLastDimAnimTime != 0) {
12060 mDimCurrentAlpha += mDimDeltaPerMs
12061 * (currentTime-mLastDimAnimTime);
12062 boolean more = true;
12063 if (displayFrozen) {
12064 // If the display is frozen, there is no reason to animate.
12065 more = false;
12066 } else if (mDimDeltaPerMs > 0) {
12067 if (mDimCurrentAlpha > mDimTargetAlpha) {
12068 more = false;
12069 }
12070 } else if (mDimDeltaPerMs < 0) {
12071 if (mDimCurrentAlpha < mDimTargetAlpha) {
12072 more = false;
12073 }
12074 } else {
12075 more = false;
12076 }
12077
12078 // Do we need to continue animating?
12079 if (more) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012080 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012081 + mDimSurface + ": alpha=" + mDimCurrentAlpha);
12082 mLastDimAnimTime = currentTime;
12083 mDimSurface.setAlpha(mDimCurrentAlpha);
12084 animating = true;
12085 } else {
12086 mDimCurrentAlpha = mDimTargetAlpha;
12087 mLastDimAnimTime = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -080012088 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012089 + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
12090 mDimSurface.setAlpha(mDimCurrentAlpha);
12091 if (!dimming) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012092 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012093 + ": HIDE");
12094 try {
12095 mDimSurface.hide();
12096 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080012097 Slog.w(TAG, "Illegal argument exception hiding dim surface");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012098 }
12099 mDimShown = false;
12100 }
12101 }
12102 }
12103 return animating;
12104 }
12105
12106 public void printTo(PrintWriter pw) {
12107 pw.print(" mDimShown="); pw.print(mDimShown);
12108 pw.print(" current="); pw.print(mDimCurrentAlpha);
12109 pw.print(" target="); pw.print(mDimTargetAlpha);
12110 pw.print(" delta="); pw.print(mDimDeltaPerMs);
12111 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
12112 }
12113 }
12114
12115 /**
12116 * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
12117 * This is used for opening/closing transition for apps in compatible mode.
12118 */
12119 private static class FadeInOutAnimation extends Animation {
12120 int mWidth;
12121 boolean mFadeIn;
12122
12123 public FadeInOutAnimation(boolean fadeIn) {
12124 setInterpolator(new AccelerateInterpolator());
12125 setDuration(DEFAULT_FADE_IN_OUT_DURATION);
12126 mFadeIn = fadeIn;
12127 }
12128
12129 @Override
12130 protected void applyTransformation(float interpolatedTime, Transformation t) {
12131 float x = interpolatedTime;
12132 if (!mFadeIn) {
12133 x = 1.0f - x; // reverse the interpolation for fade out
12134 }
12135 if (x < 0.5) {
12136 // move the window out of the screen.
12137 t.getMatrix().setTranslate(mWidth, 0);
12138 } else {
12139 t.getMatrix().setTranslate(0, 0);// show
12140 t.setAlpha((x - 0.5f) * 2);
12141 }
12142 }
12143
12144 @Override
12145 public void initialize(int width, int height, int parentWidth, int parentHeight) {
12146 // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
12147 mWidth = width;
12148 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012149
12150 @Override
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -070012151 public int getZAdjustment() {
12152 return Animation.ZORDER_TOP;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070012153 }
12154 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012155}