blob: 97d0f9b3d94de572368466fddb3aa98803f4d1df [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;
104import android.view.KeyEvent;
105import android.view.MotionEvent;
106import android.view.RawInputEvent;
107import android.view.Surface;
108import android.view.SurfaceSession;
109import android.view.View;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -0700110import android.view.ViewConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111import android.view.ViewTreeObserver;
112import android.view.WindowManager;
113import android.view.WindowManagerImpl;
114import android.view.WindowManagerPolicy;
115import android.view.WindowManager.LayoutParams;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700116import android.view.animation.AccelerateInterpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117import android.view.animation.Animation;
118import android.view.animation.AnimationUtils;
119import android.view.animation.Transformation;
120
121import java.io.BufferedWriter;
122import java.io.File;
123import java.io.FileDescriptor;
124import java.io.IOException;
125import java.io.OutputStream;
126import java.io.OutputStreamWriter;
127import java.io.PrintWriter;
128import java.io.StringWriter;
129import java.net.Socket;
130import java.util.ArrayList;
131import java.util.HashMap;
132import java.util.HashSet;
133import java.util.Iterator;
134import java.util.List;
135
136/** {@hide} */
Dianne Hackbornddca3ee2009-07-23 19:01:31 -0700137public class WindowManagerService extends IWindowManager.Stub
138 implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 static final String TAG = "WindowManager";
140 static final boolean DEBUG = false;
141 static final boolean DEBUG_FOCUS = false;
142 static final boolean DEBUG_ANIM = false;
Dianne Hackborn9b52a212009-12-11 14:51:35 -0800143 static final boolean DEBUG_LAYOUT = false;
Dianne Hackbornac3587d2010-03-11 11:12:11 -0800144 static final boolean DEBUG_RESIZE = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145 static final boolean DEBUG_LAYERS = false;
146 static final boolean DEBUG_INPUT = false;
147 static final boolean DEBUG_INPUT_METHOD = false;
148 static final boolean DEBUG_VISIBILITY = false;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -0700149 static final boolean DEBUG_WINDOW_MOVEMENT = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 static final boolean DEBUG_ORIENTATION = false;
Dianne Hackborn694f79b2010-03-17 19:44:59 -0700151 static final boolean DEBUG_CONFIGURATION = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 static final boolean DEBUG_APP_TRANSITIONS = false;
153 static final boolean DEBUG_STARTING_WINDOW = false;
154 static final boolean DEBUG_REORDER = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -0700155 static final boolean DEBUG_WALLPAPER = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 static final boolean SHOW_TRANSACTIONS = false;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700157 static final boolean HIDE_STACK_CRAWLS = true;
Michael Chan53071d62009-05-13 17:29:48 -0700158 static final boolean MEASURE_LATENCY = false;
159 static private LatencyTimer lt;
160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 static final boolean PROFILE_ORIENTATION = false;
162 static final boolean BLUR = true;
Dave Bortcfe65242009-04-09 14:51:04 -0700163 static final boolean localLOGV = DEBUG;
Romain Guy06882f82009-06-10 13:36:04 -0700164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 /** How long to wait for subsequent key repeats, in milliseconds */
166 static final int KEY_REPEAT_DELAY = 50;
167
168 /** How much to multiply the policy's type layer, to reserve room
169 * for multiple windows of the same type and Z-ordering adjustment
170 * with TYPE_LAYER_OFFSET. */
171 static final int TYPE_LAYER_MULTIPLIER = 10000;
Romain Guy06882f82009-06-10 13:36:04 -0700172
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
174 * or below others in the same layer. */
175 static final int TYPE_LAYER_OFFSET = 1000;
Romain Guy06882f82009-06-10 13:36:04 -0700176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 /** How much to increment the layer for each window, to reserve room
178 * for effect surfaces between them.
179 */
180 static final int WINDOW_LAYER_MULTIPLIER = 5;
Romain Guy06882f82009-06-10 13:36:04 -0700181
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 /** The maximum length we will accept for a loaded animation duration:
183 * this is 10 seconds.
184 */
185 static final int MAX_ANIMATION_DURATION = 10*1000;
186
187 /** Amount of time (in milliseconds) to animate the dim surface from one
188 * value to another, when no window animation is driving it.
189 */
190 static final int DEFAULT_DIM_DURATION = 200;
191
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700192 /** Amount of time (in milliseconds) to animate the fade-in-out transition for
193 * compatible windows.
194 */
195 static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 /** Adjustment to time to perform a dim, to make it more dramatic.
198 */
199 static final int DIM_DURATION_MULTIPLIER = 6;
Romain Guy06882f82009-06-10 13:36:04 -0700200
Dianne Hackborncfaef692009-06-15 14:24:44 -0700201 static final int INJECT_FAILED = 0;
202 static final int INJECT_SUCCEEDED = 1;
203 static final int INJECT_NO_PERMISSION = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800204
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800205 static final int UPDATE_FOCUS_NORMAL = 0;
206 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
207 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
208 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
Romain Guy06882f82009-06-10 13:36:04 -0700209
Michael Chane96440f2009-05-06 10:27:36 -0700210 /** The minimum time between dispatching touch events. */
211 int mMinWaitTimeBetweenTouchEvents = 1000 / 35;
212
213 // Last touch event time
214 long mLastTouchEventTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700215
Michael Chane96440f2009-05-06 10:27:36 -0700216 // Last touch event type
217 int mLastTouchEventType = OTHER_EVENT;
Romain Guy06882f82009-06-10 13:36:04 -0700218
Michael Chane96440f2009-05-06 10:27:36 -0700219 // Time to wait before calling useractivity again. This saves CPU usage
220 // when we get a flood of touch events.
221 static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000;
222
223 // Last time we call user activity
224 long mLastUserActivityCallTime = 0;
225
Romain Guy06882f82009-06-10 13:36:04 -0700226 // Last time we updated battery stats
Michael Chane96440f2009-05-06 10:27:36 -0700227 long mLastBatteryStatsCallTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700228
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 private static final String SYSTEM_SECURE = "ro.secure";
Romain Guy06882f82009-06-10 13:36:04 -0700230 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231
232 /**
233 * Condition waited on by {@link #reenableKeyguard} to know the call to
234 * the window policy has finished.
Mike Lockwood983ee092009-11-22 01:42:24 -0500235 * This is set to true only if mKeyguardTokenWatcher.acquired() has
236 * actually disabled the keyguard.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 */
Mike Lockwood983ee092009-11-22 01:42:24 -0500238 private boolean mKeyguardDisabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239
Jim Miller284b62e2010-06-08 14:27:42 -0700240 private static final int ALLOW_DISABLE_YES = 1;
241 private static final int ALLOW_DISABLE_NO = 0;
242 private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
243 private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
244
Mike Lockwood983ee092009-11-22 01:42:24 -0500245 final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
246 new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 public void acquired() {
Jim Miller284b62e2010-06-08 14:27:42 -0700248 if (shouldAllowDisableKeyguard()) {
249 mPolicy.enableKeyguard(false);
250 mKeyguardDisabled = true;
251 } else {
252 Log.v(TAG, "Not disabling keyguard since device policy is enforced");
253 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800254 }
255 public void released() {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700256 mPolicy.enableKeyguard(true);
Mike Lockwood983ee092009-11-22 01:42:24 -0500257 synchronized (mKeyguardTokenWatcher) {
258 mKeyguardDisabled = false;
259 mKeyguardTokenWatcher.notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 }
261 }
262 };
263
Jim Miller284b62e2010-06-08 14:27:42 -0700264 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
265 @Override
266 public void onReceive(Context context, Intent intent) {
267 mPolicy.enableKeyguard(true);
268 synchronized(mKeyguardTokenWatcher) {
269 // lazily evaluate this next time we're asked to disable keyguard
270 mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
271 mKeyguardDisabled = false;
272 }
273 }
274 };
275
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 final Context mContext;
277
278 final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 final boolean mLimitedAlphaCompositing;
Romain Guy06882f82009-06-10 13:36:04 -0700281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
283
284 final IActivityManager mActivityManager;
Romain Guy06882f82009-06-10 13:36:04 -0700285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 final IBatteryStats mBatteryStats;
Romain Guy06882f82009-06-10 13:36:04 -0700287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 /**
289 * All currently active sessions with clients.
290 */
291 final HashSet<Session> mSessions = new HashSet<Session>();
Romain Guy06882f82009-06-10 13:36:04 -0700292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293 /**
294 * Mapping from an IWindow IBinder to the server's Window object.
295 * This is also used as the lock for all of our state.
296 */
297 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
298
299 /**
300 * Mapping from a token IBinder to a WindowToken object.
301 */
302 final HashMap<IBinder, WindowToken> mTokenMap =
303 new HashMap<IBinder, WindowToken>();
304
305 /**
306 * The same tokens as mTokenMap, stored in a list for efficient iteration
307 * over them.
308 */
309 final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800311 /**
312 * Window tokens that are in the process of exiting, but still
313 * on screen for animations.
314 */
315 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
316
317 /**
318 * Z-ordered (bottom-most first) list of all application tokens, for
319 * controlling the ordering of windows in different applications. This
320 * contains WindowToken objects.
321 */
322 final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
323
324 /**
325 * Application tokens that are in the process of exiting, but still
326 * on screen for animations.
327 */
328 final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
329
330 /**
331 * List of window tokens that have finished starting their application,
332 * and now need to have the policy remove their windows.
333 */
334 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
335
336 /**
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700337 * This was the app token that was used to retrieve the last enter
338 * animation. It will be used for the next exit animation.
339 */
340 AppWindowToken mLastEnterAnimToken;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800341
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700342 /**
343 * These were the layout params used to retrieve the last enter animation.
344 * They will be used for the next exit animation.
345 */
346 LayoutParams mLastEnterAnimParams;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800347
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700348 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 * Z-ordered (bottom-most first) list of all Window objects.
350 */
351 final ArrayList mWindows = new ArrayList();
352
353 /**
354 * Windows that are being resized. Used so we can tell the client about
355 * the resize after closing the transaction in which we resized the
356 * underlying surface.
357 */
358 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
359
360 /**
361 * Windows whose animations have ended and now must be removed.
362 */
363 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
364
365 /**
366 * Windows whose surface should be destroyed.
367 */
368 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
369
370 /**
371 * Windows that have lost input focus and are waiting for the new
372 * focus window to be displayed before they are told about this.
373 */
374 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
375
376 /**
377 * This is set when we have run out of memory, and will either be an empty
378 * list or contain windows that need to be force removed.
379 */
380 ArrayList<WindowState> mForceRemoves;
Romain Guy06882f82009-06-10 13:36:04 -0700381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382 IInputMethodManager mInputMethodManager;
Romain Guy06882f82009-06-10 13:36:04 -0700383
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 SurfaceSession mFxSession;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700385 private DimAnimator mDimAnimator = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 Surface mBlurSurface;
387 boolean mBlurShown;
Romain Guy06882f82009-06-10 13:36:04 -0700388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 int mTransactionSequence = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 final float[] mTmpFloats = new float[9];
392
393 boolean mSafeMode;
394 boolean mDisplayEnabled = false;
395 boolean mSystemBooted = false;
Christopher Tateb696aee2010-04-02 19:08:30 -0700396 int mInitialDisplayWidth = 0;
397 int mInitialDisplayHeight = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800398 int mRotation = 0;
399 int mRequestedRotation = 0;
400 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Dianne Hackborn321ae682009-03-27 16:16:03 -0700401 int mLastRotationFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 ArrayList<IRotationWatcher> mRotationWatchers
403 = new ArrayList<IRotationWatcher>();
Romain Guy06882f82009-06-10 13:36:04 -0700404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 boolean mLayoutNeeded = true;
406 boolean mAnimationPending = false;
407 boolean mDisplayFrozen = false;
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800408 boolean mWaitingForConfig = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 boolean mWindowsFreezingScreen = false;
410 long mFreezeGcPending = 0;
411 int mAppsFreezingScreen = 0;
412
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800413 int mLayoutSeq = 0;
414
Dianne Hackbornb601ce12010-03-01 23:36:02 -0800415 // State while inside of layoutAndPlaceSurfacesLocked().
416 boolean mFocusMayChange;
417
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800418 Configuration mCurConfiguration = new Configuration();
419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800420 // This is held as long as we have the screen frozen, to give us time to
421 // perform a rotation animation when turning off shows the lock screen which
422 // changes the orientation.
423 PowerManager.WakeLock mScreenFrozenLock;
Romain Guy06882f82009-06-10 13:36:04 -0700424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800425 // State management of app transitions. When we are preparing for a
426 // transition, mNextAppTransition will be the kind of transition to
427 // perform or TRANSIT_NONE if we are not waiting. If we are waiting,
428 // mOpeningApps and mClosingApps are the lists of tokens that will be
429 // made visible or hidden at the next transition.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700430 int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700431 String mNextAppTransitionPackage;
432 int mNextAppTransitionEnter;
433 int mNextAppTransitionExit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 boolean mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -0700435 boolean mAppTransitionRunning = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 boolean mAppTransitionTimeout = false;
437 boolean mStartingIconInTransition = false;
438 boolean mSkipAppTransitionAnimation = false;
439 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
440 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
Dianne Hackborna8f60182009-09-01 19:01:50 -0700441 final ArrayList<AppWindowToken> mToTopApps = new ArrayList<AppWindowToken>();
442 final ArrayList<AppWindowToken> mToBottomApps = new ArrayList<AppWindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 //flag to detect fat touch events
445 boolean mFatTouch = false;
446 Display mDisplay;
Romain Guy06882f82009-06-10 13:36:04 -0700447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800448 H mH = new H();
449
450 WindowState mCurrentFocus = null;
451 WindowState mLastFocus = null;
Romain Guy06882f82009-06-10 13:36:04 -0700452
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 // This just indicates the window the input method is on top of, not
454 // necessarily the window its input is going to.
455 WindowState mInputMethodTarget = null;
456 WindowState mUpcomingInputMethodTarget = null;
457 boolean mInputMethodTargetWaitingAnim;
458 int mInputMethodAnimLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -0700459
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 WindowState mInputMethodWindow = null;
461 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
462
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700463 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800464
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700465 // If non-null, this is the currently visible window that is associated
466 // with the wallpaper.
467 WindowState mWallpaperTarget = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700468 // If non-null, we are in the middle of animating from one wallpaper target
469 // to another, and this is the lower one in Z-order.
470 WindowState mLowerWallpaperTarget = null;
471 // If non-null, we are in the middle of animating from one wallpaper target
472 // to another, and this is the higher one in Z-order.
473 WindowState mUpperWallpaperTarget = null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700474 int mWallpaperAnimLayerAdjustment;
Dianne Hackborn73e92b42009-10-15 14:29:19 -0700475 float mLastWallpaperX = -1;
476 float mLastWallpaperY = -1;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800477 float mLastWallpaperXStep = -1;
478 float mLastWallpaperYStep = -1;
Dianne Hackborn6adba242009-11-10 11:10:09 -0800479 boolean mSendingPointersToWallpaper = false;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700480 // This is set when we are waiting for a wallpaper to tell us it is done
481 // changing its scroll position.
482 WindowState mWaitingOnWallpaper;
483 // The last time we had a timeout when waiting for a wallpaper.
484 long mLastWallpaperTimeoutTime;
485 // We give a wallpaper up to 150ms to finish scrolling.
486 static final long WALLPAPER_TIMEOUT = 150;
487 // Time we wait after a timeout before trying to wait again.
488 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800489
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490 AppWindowToken mFocusedApp = null;
491
492 PowerManagerService mPowerManager;
Romain Guy06882f82009-06-10 13:36:04 -0700493
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 float mWindowAnimationScale = 1.0f;
495 float mTransitionAnimationScale = 1.0f;
Romain Guy06882f82009-06-10 13:36:04 -0700496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 final KeyWaiter mKeyWaiter = new KeyWaiter();
498 final KeyQ mQueue;
499 final InputDispatcherThread mInputThread;
500
501 // Who is holding the screen on.
502 Session mHoldingScreenOn;
Romain Guy06882f82009-06-10 13:36:04 -0700503
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700504 boolean mTurnOnScreen;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800506 /**
507 * Whether the UI is currently running in touch mode (not showing
508 * navigational focus because the user is directly pressing the screen).
509 */
510 boolean mInTouchMode = false;
511
512 private ViewServer mViewServer;
513
514 final Rect mTempRect = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -0700515
Dianne Hackbornc485a602009-03-24 22:39:49 -0700516 final Configuration mTempConfiguration = new Configuration();
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700517 int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700518
519 // The frame use to limit the size of the app running in compatibility mode.
520 Rect mCompatibleScreenFrame = new Rect();
521 // The surface used to fill the outer rim of the app running in compatibility mode.
522 Surface mBackgroundFillerSurface = null;
523 boolean mBackgroundFillerShown = false;
524
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525 public static WindowManagerService main(Context context,
526 PowerManagerService pm, boolean haveInputMethods) {
527 WMThread thr = new WMThread(context, pm, haveInputMethods);
528 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 synchronized (thr) {
531 while (thr.mService == null) {
532 try {
533 thr.wait();
534 } catch (InterruptedException e) {
535 }
536 }
537 }
Romain Guy06882f82009-06-10 13:36:04 -0700538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800539 return thr.mService;
540 }
Romain Guy06882f82009-06-10 13:36:04 -0700541
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 static class WMThread extends Thread {
543 WindowManagerService mService;
Romain Guy06882f82009-06-10 13:36:04 -0700544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800545 private final Context mContext;
546 private final PowerManagerService mPM;
547 private final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 public WMThread(Context context, PowerManagerService pm,
550 boolean haveInputMethods) {
551 super("WindowManager");
552 mContext = context;
553 mPM = pm;
554 mHaveInputMethods = haveInputMethods;
555 }
Romain Guy06882f82009-06-10 13:36:04 -0700556
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800557 public void run() {
558 Looper.prepare();
559 WindowManagerService s = new WindowManagerService(mContext, mPM,
560 mHaveInputMethods);
561 android.os.Process.setThreadPriority(
562 android.os.Process.THREAD_PRIORITY_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -0700563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 synchronized (this) {
565 mService = s;
566 notifyAll();
567 }
Romain Guy06882f82009-06-10 13:36:04 -0700568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569 Looper.loop();
570 }
571 }
572
573 static class PolicyThread extends Thread {
574 private final WindowManagerPolicy mPolicy;
575 private final WindowManagerService mService;
576 private final Context mContext;
577 private final PowerManagerService mPM;
578 boolean mRunning = false;
Romain Guy06882f82009-06-10 13:36:04 -0700579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 public PolicyThread(WindowManagerPolicy policy,
581 WindowManagerService service, Context context,
582 PowerManagerService pm) {
583 super("WindowManagerPolicy");
584 mPolicy = policy;
585 mService = service;
586 mContext = context;
587 mPM = pm;
588 }
Romain Guy06882f82009-06-10 13:36:04 -0700589
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800590 public void run() {
591 Looper.prepare();
Dianne Hackbornac3587d2010-03-11 11:12:11 -0800592 WindowManagerPolicyThread.set(this, Looper.myLooper());
593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 //Looper.myLooper().setMessageLogging(new LogPrinter(
Joe Onorato8a9b2202010-02-26 18:56:32 -0800595 // Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 android.os.Process.setThreadPriority(
597 android.os.Process.THREAD_PRIORITY_FOREGROUND);
598 mPolicy.init(mContext, mService, mPM);
Romain Guy06882f82009-06-10 13:36:04 -0700599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 synchronized (this) {
601 mRunning = true;
602 notifyAll();
603 }
Romain Guy06882f82009-06-10 13:36:04 -0700604
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800605 Looper.loop();
606 }
607 }
608
609 private WindowManagerService(Context context, PowerManagerService pm,
610 boolean haveInputMethods) {
Michael Chan53071d62009-05-13 17:29:48 -0700611 if (MEASURE_LATENCY) {
612 lt = new LatencyTimer(100, 1000);
613 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800615 mContext = context;
616 mHaveInputMethods = haveInputMethods;
617 mLimitedAlphaCompositing = context.getResources().getBoolean(
618 com.android.internal.R.bool.config_sf_limitedAlpha);
Romain Guy06882f82009-06-10 13:36:04 -0700619
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 mPowerManager = pm;
621 mPowerManager.setPolicy(mPolicy);
622 PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
623 mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
624 "SCREEN_FROZEN");
625 mScreenFrozenLock.setReferenceCounted(false);
626
627 mActivityManager = ActivityManagerNative.getDefault();
628 mBatteryStats = BatteryStatsService.getService();
629
630 // Get persisted window scale setting
631 mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
632 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
633 mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
634 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
Romain Guy06882f82009-06-10 13:36:04 -0700635
Jim Miller284b62e2010-06-08 14:27:42 -0700636 // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
637 IntentFilter filter = new IntentFilter();
638 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
639 mContext.registerReceiver(mBroadcastReceiver, filter);
640
Michael Chan9f028e62009-08-04 17:37:46 -0700641 int max_events_per_sec = 35;
642 try {
643 max_events_per_sec = Integer.parseInt(SystemProperties
644 .get("windowsmgr.max_events_per_sec"));
645 if (max_events_per_sec < 1) {
646 max_events_per_sec = 35;
647 }
648 } catch (NumberFormatException e) {
649 }
650 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 mQueue = new KeyQ();
653
654 mInputThread = new InputDispatcherThread();
Romain Guy06882f82009-06-10 13:36:04 -0700655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800656 PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
657 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 synchronized (thr) {
660 while (!thr.mRunning) {
661 try {
662 thr.wait();
663 } catch (InterruptedException e) {
664 }
665 }
666 }
Romain Guy06882f82009-06-10 13:36:04 -0700667
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 mInputThread.start();
Romain Guy06882f82009-06-10 13:36:04 -0700669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 // Add ourself to the Watchdog monitors.
671 Watchdog.getInstance().addMonitor(this);
672 }
673
674 @Override
675 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
676 throws RemoteException {
677 try {
678 return super.onTransact(code, data, reply, flags);
679 } catch (RuntimeException e) {
680 // The window manager only throws security exceptions, so let's
681 // log all others.
682 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800683 Slog.e(TAG, "Window Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800684 }
685 throw e;
686 }
687 }
688
689 private void placeWindowAfter(Object pos, WindowState window) {
690 final int i = mWindows.indexOf(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800691 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800692 TAG, "Adding window " + window + " at "
693 + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
694 mWindows.add(i+1, window);
695 }
696
697 private void placeWindowBefore(Object pos, WindowState window) {
698 final int i = mWindows.indexOf(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800699 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 TAG, "Adding window " + window + " at "
701 + i + " of " + mWindows.size() + " (before " + pos + ")");
702 mWindows.add(i, window);
703 }
704
705 //This method finds out the index of a window that has the same app token as
706 //win. used for z ordering the windows in mWindows
707 private int findIdxBasedOnAppTokens(WindowState win) {
708 //use a local variable to cache mWindows
709 ArrayList localmWindows = mWindows;
710 int jmax = localmWindows.size();
711 if(jmax == 0) {
712 return -1;
713 }
714 for(int j = (jmax-1); j >= 0; j--) {
715 WindowState wentry = (WindowState)localmWindows.get(j);
716 if(wentry.mAppToken == win.mAppToken) {
717 return j;
718 }
719 }
720 return -1;
721 }
Romain Guy06882f82009-06-10 13:36:04 -0700722
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723 private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
724 final IWindow client = win.mClient;
725 final WindowToken token = win.mToken;
726 final ArrayList localmWindows = mWindows;
Romain Guy06882f82009-06-10 13:36:04 -0700727
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800728 final int N = localmWindows.size();
729 final WindowState attached = win.mAttachedWindow;
730 int i;
731 if (attached == null) {
732 int tokenWindowsPos = token.windows.size();
733 if (token.appWindowToken != null) {
734 int index = tokenWindowsPos-1;
735 if (index >= 0) {
736 // If this application has existing windows, we
737 // simply place the new window on top of them... but
738 // keep the starting window on top.
739 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
740 // Base windows go behind everything else.
741 placeWindowBefore(token.windows.get(0), win);
742 tokenWindowsPos = 0;
743 } else {
744 AppWindowToken atoken = win.mAppToken;
745 if (atoken != null &&
746 token.windows.get(index) == atoken.startingWindow) {
747 placeWindowBefore(token.windows.get(index), win);
748 tokenWindowsPos--;
749 } else {
750 int newIdx = findIdxBasedOnAppTokens(win);
751 if(newIdx != -1) {
Romain Guy06882f82009-06-10 13:36:04 -0700752 //there is a window above this one associated with the same
753 //apptoken note that the window could be a floating window
754 //that was created later or a window at the top of the list of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755 //windows associated with this token.
Joe Onorato8a9b2202010-02-26 18:56:32 -0800756 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700757 TAG, "Adding window " + win + " at "
758 + (newIdx+1) + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 localmWindows.add(newIdx+1, win);
Romain Guy06882f82009-06-10 13:36:04 -0700760 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 }
762 }
763 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800764 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 TAG, "Figuring out where to add app window "
766 + client.asBinder() + " (token=" + token + ")");
767 // Figure out where the window should go, based on the
768 // order of applications.
769 final int NA = mAppTokens.size();
770 Object pos = null;
771 for (i=NA-1; i>=0; i--) {
772 AppWindowToken t = mAppTokens.get(i);
773 if (t == token) {
774 i--;
775 break;
776 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800777
Dianne Hackborna8f60182009-09-01 19:01:50 -0700778 // We haven't reached the token yet; if this token
779 // is not going to the bottom and has windows, we can
780 // use it as an anchor for when we do reach the token.
781 if (!t.sendingToBottom && t.windows.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 pos = t.windows.get(0);
783 }
784 }
785 // We now know the index into the apps. If we found
786 // an app window above, that gives us the position; else
787 // we need to look some more.
788 if (pos != null) {
789 // Move behind any windows attached to this one.
Romain Guy06882f82009-06-10 13:36:04 -0700790 WindowToken atoken =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 mTokenMap.get(((WindowState)pos).mClient.asBinder());
792 if (atoken != null) {
793 final int NC = atoken.windows.size();
794 if (NC > 0) {
795 WindowState bottom = atoken.windows.get(0);
796 if (bottom.mSubLayer < 0) {
797 pos = bottom;
798 }
799 }
800 }
801 placeWindowBefore(pos, win);
802 } else {
Dianne Hackborna8f60182009-09-01 19:01:50 -0700803 // Continue looking down until we find the first
804 // token that has windows.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800805 while (i >= 0) {
806 AppWindowToken t = mAppTokens.get(i);
807 final int NW = t.windows.size();
808 if (NW > 0) {
809 pos = t.windows.get(NW-1);
810 break;
811 }
812 i--;
813 }
814 if (pos != null) {
815 // Move in front of any windows attached to this
816 // one.
817 WindowToken atoken =
818 mTokenMap.get(((WindowState)pos).mClient.asBinder());
819 if (atoken != null) {
820 final int NC = atoken.windows.size();
821 if (NC > 0) {
822 WindowState top = atoken.windows.get(NC-1);
823 if (top.mSubLayer >= 0) {
824 pos = top;
825 }
826 }
827 }
828 placeWindowAfter(pos, win);
829 } else {
830 // Just search for the start of this layer.
831 final int myLayer = win.mBaseLayer;
832 for (i=0; i<N; i++) {
833 WindowState w = (WindowState)localmWindows.get(i);
834 if (w.mBaseLayer > myLayer) {
835 break;
836 }
837 }
Joe Onorato8a9b2202010-02-26 18:56:32 -0800838 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700839 TAG, "Adding window " + win + " at "
840 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800841 localmWindows.add(i, win);
842 }
843 }
844 }
845 } else {
846 // Figure out where window should go, based on layer.
847 final int myLayer = win.mBaseLayer;
848 for (i=N-1; i>=0; i--) {
849 if (((WindowState)localmWindows.get(i)).mBaseLayer <= myLayer) {
850 i++;
851 break;
852 }
853 }
854 if (i < 0) i = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800855 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700856 TAG, "Adding window " + win + " at "
857 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800858 localmWindows.add(i, win);
859 }
860 if (addToToken) {
861 token.windows.add(tokenWindowsPos, win);
862 }
863
864 } else {
865 // Figure out this window's ordering relative to the window
866 // it is attached to.
867 final int NA = token.windows.size();
868 final int sublayer = win.mSubLayer;
869 int largestSublayer = Integer.MIN_VALUE;
870 WindowState windowWithLargestSublayer = null;
871 for (i=0; i<NA; i++) {
872 WindowState w = token.windows.get(i);
873 final int wSublayer = w.mSubLayer;
874 if (wSublayer >= largestSublayer) {
875 largestSublayer = wSublayer;
876 windowWithLargestSublayer = w;
877 }
878 if (sublayer < 0) {
879 // For negative sublayers, we go below all windows
880 // in the same sublayer.
881 if (wSublayer >= sublayer) {
882 if (addToToken) {
883 token.windows.add(i, win);
884 }
885 placeWindowBefore(
886 wSublayer >= 0 ? attached : w, win);
887 break;
888 }
889 } else {
890 // For positive sublayers, we go above all windows
891 // in the same sublayer.
892 if (wSublayer > sublayer) {
893 if (addToToken) {
894 token.windows.add(i, win);
895 }
896 placeWindowBefore(w, win);
897 break;
898 }
899 }
900 }
901 if (i >= NA) {
902 if (addToToken) {
903 token.windows.add(win);
904 }
905 if (sublayer < 0) {
906 placeWindowBefore(attached, win);
907 } else {
908 placeWindowAfter(largestSublayer >= 0
909 ? windowWithLargestSublayer
910 : attached,
911 win);
912 }
913 }
914 }
Romain Guy06882f82009-06-10 13:36:04 -0700915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800916 if (win.mAppToken != null && addToToken) {
917 win.mAppToken.allAppWindows.add(win);
918 }
919 }
Romain Guy06882f82009-06-10 13:36:04 -0700920
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 static boolean canBeImeTarget(WindowState w) {
922 final int fl = w.mAttrs.flags
923 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
924 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
925 return w.isVisibleOrAdding();
926 }
927 return false;
928 }
Romain Guy06882f82009-06-10 13:36:04 -0700929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
931 final ArrayList localmWindows = mWindows;
932 final int N = localmWindows.size();
933 WindowState w = null;
934 int i = N;
935 while (i > 0) {
936 i--;
937 w = (WindowState)localmWindows.get(i);
Romain Guy06882f82009-06-10 13:36:04 -0700938
Joe Onorato8a9b2202010-02-26 18:56:32 -0800939 //Slog.i(TAG, "Checking window @" + i + " " + w + " fl=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800940 // + Integer.toHexString(w.mAttrs.flags));
941 if (canBeImeTarget(w)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800942 //Slog.i(TAG, "Putting input method here!");
Romain Guy06882f82009-06-10 13:36:04 -0700943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 // Yet more tricksyness! If this window is a "starting"
945 // window, we do actually want to be on top of it, but
946 // it is not -really- where input will go. So if the caller
947 // is not actually looking to move the IME, look down below
948 // for a real window to target...
949 if (!willMove
950 && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
951 && i > 0) {
952 WindowState wb = (WindowState)localmWindows.get(i-1);
953 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
954 i--;
955 w = wb;
956 }
957 }
958 break;
959 }
960 }
Romain Guy06882f82009-06-10 13:36:04 -0700961
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 mUpcomingInputMethodTarget = w;
Romain Guy06882f82009-06-10 13:36:04 -0700963
Joe Onorato8a9b2202010-02-26 18:56:32 -0800964 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 + w + " willMove=" + willMove);
Romain Guy06882f82009-06-10 13:36:04 -0700966
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800967 if (willMove && w != null) {
968 final WindowState curTarget = mInputMethodTarget;
969 if (curTarget != null && curTarget.mAppToken != null) {
Romain Guy06882f82009-06-10 13:36:04 -0700970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800971 // Now some fun for dealing with window animations that
972 // modify the Z order. We need to look at all windows below
973 // the current target that are in this app, finding the highest
974 // visible one in layering.
975 AppWindowToken token = curTarget.mAppToken;
976 WindowState highestTarget = null;
977 int highestPos = 0;
978 if (token.animating || token.animation != null) {
979 int pos = 0;
980 pos = localmWindows.indexOf(curTarget);
981 while (pos >= 0) {
982 WindowState win = (WindowState)localmWindows.get(pos);
983 if (win.mAppToken != token) {
984 break;
985 }
986 if (!win.mRemoved) {
987 if (highestTarget == null || win.mAnimLayer >
988 highestTarget.mAnimLayer) {
989 highestTarget = win;
990 highestPos = pos;
991 }
992 }
993 pos--;
994 }
995 }
Romain Guy06882f82009-06-10 13:36:04 -0700996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 if (highestTarget != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800998 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "mNextAppTransition="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800999 + mNextAppTransition + " " + highestTarget
1000 + " animating=" + highestTarget.isAnimating()
1001 + " layer=" + highestTarget.mAnimLayer
1002 + " new layer=" + w.mAnimLayer);
Romain Guy06882f82009-06-10 13:36:04 -07001003
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001004 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 // If we are currently setting up for an animation,
1006 // hold everything until we can find out what will happen.
1007 mInputMethodTargetWaitingAnim = true;
1008 mInputMethodTarget = highestTarget;
1009 return highestPos + 1;
1010 } else if (highestTarget.isAnimating() &&
1011 highestTarget.mAnimLayer > w.mAnimLayer) {
1012 // If the window we are currently targeting is involved
1013 // with an animation, and it is on top of the next target
1014 // we will be over, then hold off on moving until
1015 // that is done.
1016 mInputMethodTarget = highestTarget;
1017 return highestPos + 1;
1018 }
1019 }
1020 }
1021 }
Romain Guy06882f82009-06-10 13:36:04 -07001022
Joe Onorato8a9b2202010-02-26 18:56:32 -08001023 //Slog.i(TAG, "Placing input method @" + (i+1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001024 if (w != null) {
1025 if (willMove) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08001026 if (DEBUG_INPUT_METHOD) {
1027 RuntimeException e = null;
1028 if (!HIDE_STACK_CRAWLS) {
1029 e = new RuntimeException();
1030 e.fillInStackTrace();
1031 }
1032 Slog.w(TAG, "Moving IM target from "
1033 + mInputMethodTarget + " to " + w, e);
1034 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 mInputMethodTarget = w;
1036 if (w.mAppToken != null) {
1037 setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
1038 } else {
1039 setInputMethodAnimLayerAdjustment(0);
1040 }
1041 }
1042 return i+1;
1043 }
1044 if (willMove) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08001045 if (DEBUG_INPUT_METHOD) {
1046 RuntimeException e = null;
1047 if (!HIDE_STACK_CRAWLS) {
1048 e = new RuntimeException();
1049 e.fillInStackTrace();
1050 }
1051 Slog.w(TAG, "Moving IM target from "
1052 + mInputMethodTarget + " to null", e);
1053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001054 mInputMethodTarget = null;
1055 setInputMethodAnimLayerAdjustment(0);
1056 }
1057 return -1;
1058 }
Romain Guy06882f82009-06-10 13:36:04 -07001059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001060 void addInputMethodWindowToListLocked(WindowState win) {
1061 int pos = findDesiredInputMethodWindowIndexLocked(true);
1062 if (pos >= 0) {
1063 win.mTargetAppToken = mInputMethodTarget.mAppToken;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001064 if (DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001065 TAG, "Adding input method window " + win + " at " + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 mWindows.add(pos, win);
1067 moveInputMethodDialogsLocked(pos+1);
1068 return;
1069 }
1070 win.mTargetAppToken = null;
1071 addWindowToListInOrderLocked(win, true);
1072 moveInputMethodDialogsLocked(pos);
1073 }
Romain Guy06882f82009-06-10 13:36:04 -07001074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 void setInputMethodAnimLayerAdjustment(int adj) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001076 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 mInputMethodAnimLayerAdjustment = adj;
1078 WindowState imw = mInputMethodWindow;
1079 if (imw != null) {
1080 imw.mAnimLayer = imw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001081 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 + " anim layer: " + imw.mAnimLayer);
1083 int wi = imw.mChildWindows.size();
1084 while (wi > 0) {
1085 wi--;
1086 WindowState cw = (WindowState)imw.mChildWindows.get(wi);
1087 cw.mAnimLayer = cw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001088 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001089 + " anim layer: " + cw.mAnimLayer);
1090 }
1091 }
1092 int di = mInputMethodDialogs.size();
1093 while (di > 0) {
1094 di --;
1095 imw = mInputMethodDialogs.get(di);
1096 imw.mAnimLayer = imw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001097 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 + " anim layer: " + imw.mAnimLayer);
1099 }
1100 }
Romain Guy06882f82009-06-10 13:36:04 -07001101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1103 int wpos = mWindows.indexOf(win);
1104 if (wpos >= 0) {
1105 if (wpos < interestingPos) interestingPos--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001106 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 mWindows.remove(wpos);
1108 int NC = win.mChildWindows.size();
1109 while (NC > 0) {
1110 NC--;
1111 WindowState cw = (WindowState)win.mChildWindows.get(NC);
1112 int cpos = mWindows.indexOf(cw);
1113 if (cpos >= 0) {
1114 if (cpos < interestingPos) interestingPos--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001115 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001116 + cpos + ": " + cw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001117 mWindows.remove(cpos);
1118 }
1119 }
1120 }
1121 return interestingPos;
1122 }
Romain Guy06882f82009-06-10 13:36:04 -07001123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 private void reAddWindowToListInOrderLocked(WindowState win) {
1125 addWindowToListInOrderLocked(win, false);
1126 // This is a hack to get all of the child windows added as well
1127 // at the right position. Child windows should be rare and
1128 // this case should be rare, so it shouldn't be that big a deal.
1129 int wpos = mWindows.indexOf(win);
1130 if (wpos >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001131 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001132 + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001133 mWindows.remove(wpos);
1134 reAddWindowLocked(wpos, win);
1135 }
1136 }
Romain Guy06882f82009-06-10 13:36:04 -07001137
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 void logWindowList(String prefix) {
1139 int N = mWindows.size();
1140 while (N > 0) {
1141 N--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001142 Slog.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143 }
1144 }
Romain Guy06882f82009-06-10 13:36:04 -07001145
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001146 void moveInputMethodDialogsLocked(int pos) {
1147 ArrayList<WindowState> dialogs = mInputMethodDialogs;
Romain Guy06882f82009-06-10 13:36:04 -07001148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001149 final int N = dialogs.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001150 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 for (int i=0; i<N; i++) {
1152 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1153 }
1154 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001155 Slog.v(TAG, "Window list w/pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 logWindowList(" ");
1157 }
Romain Guy06882f82009-06-10 13:36:04 -07001158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 if (pos >= 0) {
1160 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1161 if (pos < mWindows.size()) {
1162 WindowState wp = (WindowState)mWindows.get(pos);
1163 if (wp == mInputMethodWindow) {
1164 pos++;
1165 }
1166 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001167 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 for (int i=0; i<N; i++) {
1169 WindowState win = dialogs.get(i);
1170 win.mTargetAppToken = targetAppToken;
1171 pos = reAddWindowLocked(pos, win);
1172 }
1173 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001174 Slog.v(TAG, "Final window list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 logWindowList(" ");
1176 }
1177 return;
1178 }
1179 for (int i=0; i<N; i++) {
1180 WindowState win = dialogs.get(i);
1181 win.mTargetAppToken = null;
1182 reAddWindowToListInOrderLocked(win);
1183 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001184 Slog.v(TAG, "No IM target, final list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 logWindowList(" ");
1186 }
1187 }
1188 }
Romain Guy06882f82009-06-10 13:36:04 -07001189
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1191 final WindowState imWin = mInputMethodWindow;
1192 final int DN = mInputMethodDialogs.size();
1193 if (imWin == null && DN == 0) {
1194 return false;
1195 }
Romain Guy06882f82009-06-10 13:36:04 -07001196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1198 if (imPos >= 0) {
1199 // In this case, the input method windows are to be placed
1200 // immediately above the window they are targeting.
Romain Guy06882f82009-06-10 13:36:04 -07001201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001202 // First check to see if the input method windows are already
1203 // located here, and contiguous.
1204 final int N = mWindows.size();
1205 WindowState firstImWin = imPos < N
1206 ? (WindowState)mWindows.get(imPos) : null;
Romain Guy06882f82009-06-10 13:36:04 -07001207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208 // Figure out the actual input method window that should be
1209 // at the bottom of their stack.
1210 WindowState baseImWin = imWin != null
1211 ? imWin : mInputMethodDialogs.get(0);
1212 if (baseImWin.mChildWindows.size() > 0) {
1213 WindowState cw = (WindowState)baseImWin.mChildWindows.get(0);
1214 if (cw.mSubLayer < 0) baseImWin = cw;
1215 }
Romain Guy06882f82009-06-10 13:36:04 -07001216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001217 if (firstImWin == baseImWin) {
1218 // The windows haven't moved... but are they still contiguous?
1219 // First find the top IM window.
1220 int pos = imPos+1;
1221 while (pos < N) {
1222 if (!((WindowState)mWindows.get(pos)).mIsImWindow) {
1223 break;
1224 }
1225 pos++;
1226 }
1227 pos++;
1228 // Now there should be no more input method windows above.
1229 while (pos < N) {
1230 if (((WindowState)mWindows.get(pos)).mIsImWindow) {
1231 break;
1232 }
1233 pos++;
1234 }
1235 if (pos >= N) {
1236 // All is good!
1237 return false;
1238 }
1239 }
Romain Guy06882f82009-06-10 13:36:04 -07001240
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241 if (imWin != null) {
1242 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001243 Slog.v(TAG, "Moving IM from " + imPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 logWindowList(" ");
1245 }
1246 imPos = tmpRemoveWindowLocked(imPos, imWin);
1247 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001248 Slog.v(TAG, "List after moving with new pos " + imPos + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001249 logWindowList(" ");
1250 }
1251 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1252 reAddWindowLocked(imPos, imWin);
1253 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001254 Slog.v(TAG, "List after moving IM to " + imPos + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 logWindowList(" ");
1256 }
1257 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1258 } else {
1259 moveInputMethodDialogsLocked(imPos);
1260 }
Romain Guy06882f82009-06-10 13:36:04 -07001261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001262 } else {
1263 // In this case, the input method windows go in a fixed layer,
1264 // because they aren't currently associated with a focus window.
Romain Guy06882f82009-06-10 13:36:04 -07001265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001266 if (imWin != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001267 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001268 tmpRemoveWindowLocked(0, imWin);
1269 imWin.mTargetAppToken = null;
1270 reAddWindowToListInOrderLocked(imWin);
1271 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001272 Slog.v(TAG, "List with no IM target:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 logWindowList(" ");
1274 }
1275 if (DN > 0) moveInputMethodDialogsLocked(-1);;
1276 } else {
1277 moveInputMethodDialogsLocked(-1);;
1278 }
Romain Guy06882f82009-06-10 13:36:04 -07001279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 }
Romain Guy06882f82009-06-10 13:36:04 -07001281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001282 if (needAssignLayers) {
1283 assignLayersLocked();
1284 }
Romain Guy06882f82009-06-10 13:36:04 -07001285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 return true;
1287 }
Romain Guy06882f82009-06-10 13:36:04 -07001288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 void adjustInputMethodDialogsLocked() {
1290 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
1291 }
Romain Guy06882f82009-06-10 13:36:04 -07001292
Dianne Hackborn25994b42009-09-04 14:21:19 -07001293 final boolean isWallpaperVisible(WindowState wallpaperTarget) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001294 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target obscured="
Dianne Hackborn25994b42009-09-04 14:21:19 -07001295 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1296 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1297 ? wallpaperTarget.mAppToken.animation : null)
1298 + " upper=" + mUpperWallpaperTarget
1299 + " lower=" + mLowerWallpaperTarget);
1300 return (wallpaperTarget != null
1301 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1302 && wallpaperTarget.mAppToken.animation != null)))
1303 || mUpperWallpaperTarget != null
1304 || mLowerWallpaperTarget != null;
1305 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001306
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001307 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1308 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001309
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001310 int adjustWallpaperWindowsLocked() {
1311 int changed = 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001312
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001313 final int dw = mDisplay.getWidth();
1314 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001315
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001316 // First find top-most window that has asked to be on top of the
1317 // wallpaper; all wallpapers go behind it.
1318 final ArrayList localmWindows = mWindows;
1319 int N = localmWindows.size();
1320 WindowState w = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001321 WindowState foundW = null;
1322 int foundI = 0;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001323 WindowState topCurW = null;
1324 int topCurI = 0;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001325 int i = N;
1326 while (i > 0) {
1327 i--;
1328 w = (WindowState)localmWindows.get(i);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001329 if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
1330 if (topCurW == null) {
1331 topCurW = w;
1332 topCurI = i;
1333 }
1334 continue;
1335 }
1336 topCurW = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001337 if (w.mAppToken != null) {
1338 // If this window's app token is hidden and not animating,
1339 // it is of no interest to us.
1340 if (w.mAppToken.hidden && w.mAppToken.animation == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001341 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001342 "Skipping hidden or animating token: " + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001343 topCurW = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001344 continue;
1345 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001346 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001347 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": readyfordisplay="
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001348 + w.isReadyForDisplay() + " drawpending=" + w.mDrawPending
1349 + " commitdrawpending=" + w.mCommitDrawPending);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001350 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07001351 && (mWallpaperTarget == w
1352 || (!w.mDrawPending && !w.mCommitDrawPending))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001353 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001354 "Found wallpaper activity: #" + i + "=" + w);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001355 foundW = w;
1356 foundI = i;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001357 if (w == mWallpaperTarget && ((w.mAppToken != null
1358 && w.mAppToken.animation != null)
1359 || w.mAnimation != null)) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001360 // The current wallpaper target is animating, so we'll
1361 // look behind it for another possible target and figure
1362 // out what is going on below.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001363 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001364 + ": token animating, looking behind.");
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001365 continue;
1366 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001367 break;
1368 }
1369 }
1370
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001371 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001372 // If we are currently waiting for an app transition, and either
1373 // the current target or the next target are involved with it,
1374 // then hold off on doing anything with the wallpaper.
1375 // Note that we are checking here for just whether the target
1376 // is part of an app token... which is potentially overly aggressive
1377 // (the app token may not be involved in the transition), but good
1378 // enough (we'll just wait until whatever transition is pending
1379 // executes).
1380 if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001381 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001382 "Wallpaper not changing: waiting for app anim in current target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001383 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001384 }
1385 if (foundW != null && foundW.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001386 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001387 "Wallpaper not changing: waiting for app anim in found target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001388 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001389 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001390 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001391
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001392 if (mWallpaperTarget != foundW) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001393 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001394 Slog.v(TAG, "New wallpaper target: " + foundW
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001395 + " oldTarget: " + mWallpaperTarget);
1396 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001397
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001398 mLowerWallpaperTarget = null;
1399 mUpperWallpaperTarget = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001400
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001401 WindowState oldW = mWallpaperTarget;
1402 mWallpaperTarget = foundW;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001403
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001404 // Now what is happening... if the current and new targets are
1405 // animating, then we are in our super special mode!
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001406 if (foundW != null && oldW != null) {
1407 boolean oldAnim = oldW.mAnimation != null
1408 || (oldW.mAppToken != null && oldW.mAppToken.animation != null);
1409 boolean foundAnim = foundW.mAnimation != null
1410 || (foundW.mAppToken != null && foundW.mAppToken.animation != null);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001411 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001412 Slog.v(TAG, "New animation: " + foundAnim
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001413 + " old animation: " + oldAnim);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001414 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001415 if (foundAnim && oldAnim) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001416 int oldI = localmWindows.indexOf(oldW);
1417 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001418 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001419 }
1420 if (oldI >= 0) {
1421 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001422 Slog.v(TAG, "Animating wallpapers: old#" + oldI
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001423 + "=" + oldW + "; new#" + foundI
1424 + "=" + foundW);
1425 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001426
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001427 // Set the new target correctly.
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001428 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001429 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001430 Slog.v(TAG, "Old wallpaper still the target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001431 }
1432 mWallpaperTarget = oldW;
1433 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001434
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001435 // Now set the upper and lower wallpaper targets
1436 // correctly, and make sure that we are positioning
1437 // the wallpaper below the lower.
1438 if (foundI > oldI) {
1439 // The new target is on top of the old one.
1440 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001441 Slog.v(TAG, "Found target above old target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001442 }
1443 mUpperWallpaperTarget = foundW;
1444 mLowerWallpaperTarget = oldW;
1445 foundW = oldW;
1446 foundI = oldI;
1447 } else {
1448 // The new target is below the old one.
1449 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001450 Slog.v(TAG, "Found target below old target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001451 }
1452 mUpperWallpaperTarget = oldW;
1453 mLowerWallpaperTarget = foundW;
1454 }
1455 }
1456 }
1457 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001458
Dianne Hackborn6b1cb352009-09-28 18:27:26 -07001459 } else if (mLowerWallpaperTarget != null) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001460 // Is it time to stop animating?
Dianne Hackborn6b1cb352009-09-28 18:27:26 -07001461 boolean lowerAnimating = mLowerWallpaperTarget.mAnimation != null
1462 || (mLowerWallpaperTarget.mAppToken != null
1463 && mLowerWallpaperTarget.mAppToken.animation != null);
1464 boolean upperAnimating = mUpperWallpaperTarget.mAnimation != null
1465 || (mUpperWallpaperTarget.mAppToken != null
1466 && mUpperWallpaperTarget.mAppToken.animation != null);
1467 if (!lowerAnimating || !upperAnimating) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001468 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001469 Slog.v(TAG, "No longer animating wallpaper targets!");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001470 }
1471 mLowerWallpaperTarget = null;
1472 mUpperWallpaperTarget = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001473 }
1474 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001475
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001476 boolean visible = foundW != null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001477 if (visible) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001478 // The window is visible to the compositor... but is it visible
1479 // to the user? That is what the wallpaper cares about.
Dianne Hackborn25994b42009-09-04 14:21:19 -07001480 visible = isWallpaperVisible(foundW);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001481 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001482
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001483 // If the wallpaper target is animating, we may need to copy
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001484 // its layer adjustment. Only do this if we are not transfering
1485 // between two wallpaper targets.
1486 mWallpaperAnimLayerAdjustment =
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001487 (mLowerWallpaperTarget == null && foundW.mAppToken != null)
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001488 ? foundW.mAppToken.animLayerAdjustment : 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001489
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001490 final int maxLayer = mPolicy.getMaxWallpaperLayer()
1491 * TYPE_LAYER_MULTIPLIER
1492 + TYPE_LAYER_OFFSET;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001493
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001494 // Now w is the window we are supposed to be behind... but we
1495 // need to be sure to also be behind any of its attached windows,
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001496 // AND any starting window associated with it, AND below the
1497 // maximum layer the policy allows for wallpapers.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001498 while (foundI > 0) {
1499 WindowState wb = (WindowState)localmWindows.get(foundI-1);
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001500 if (wb.mBaseLayer < maxLayer &&
1501 wb.mAttachedWindow != foundW &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001502 (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001503 wb.mToken != foundW.mToken)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001504 // This window is not related to the previous one in any
1505 // interesting way, so stop here.
1506 break;
1507 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001508 foundW = wb;
1509 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001510 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07001511 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001512 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001513 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001514
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001515 if (foundW == null && topCurW != null) {
1516 // There is no wallpaper target, so it goes at the bottom.
1517 // We will assume it is the same place as last time, if known.
1518 foundW = topCurW;
1519 foundI = topCurI+1;
1520 } else {
1521 // Okay i is the position immediately above the wallpaper. Look at
1522 // what is below it for later.
1523 foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
1524 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001525
Dianne Hackborn284ac932009-08-28 10:34:25 -07001526 if (visible) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001527 if (mWallpaperTarget.mWallpaperX >= 0) {
1528 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001529 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001530 }
1531 if (mWallpaperTarget.mWallpaperY >= 0) {
1532 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001533 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001534 }
Dianne Hackborn284ac932009-08-28 10:34:25 -07001535 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001536
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001537 // Start stepping backwards from here, ensuring that our wallpaper windows
1538 // are correctly placed.
1539 int curTokenIndex = mWallpaperTokens.size();
1540 while (curTokenIndex > 0) {
1541 curTokenIndex--;
1542 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001543 if (token.hidden == visible) {
1544 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1545 token.hidden = !visible;
1546 // Need to do a layout to ensure the wallpaper now has the
1547 // correct size.
1548 mLayoutNeeded = true;
1549 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001550
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001551 int curWallpaperIndex = token.windows.size();
1552 while (curWallpaperIndex > 0) {
1553 curWallpaperIndex--;
1554 WindowState wallpaper = token.windows.get(curWallpaperIndex);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001555
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001556 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001557 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001558 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001559
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001560 // First, make sure the client has the current visibility
1561 // state.
1562 if (wallpaper.mWallpaperVisible != visible) {
1563 wallpaper.mWallpaperVisible = visible;
1564 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001565 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001566 "Setting visibility of wallpaper " + wallpaper
1567 + ": " + visible);
1568 wallpaper.mClient.dispatchAppVisibility(visible);
1569 } catch (RemoteException e) {
1570 }
1571 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001572
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001573 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001574 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001575 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001576
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001577 // First, if this window is at the current index, then all
1578 // is well.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001579 if (wallpaper == foundW) {
1580 foundI--;
1581 foundW = foundI > 0
1582 ? (WindowState)localmWindows.get(foundI-1) : null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001583 continue;
1584 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001585
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001586 // The window didn't match... the current wallpaper window,
1587 // wherever it is, is in the wrong place, so make sure it is
1588 // not in the list.
1589 int oldIndex = localmWindows.indexOf(wallpaper);
1590 if (oldIndex >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001591 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001592 + oldIndex + ": " + wallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001593 localmWindows.remove(oldIndex);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001594 if (oldIndex < foundI) {
1595 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001596 }
1597 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001598
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001599 // Now stick it in.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001600 if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001601 "Moving wallpaper " + wallpaper
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001602 + " from " + oldIndex + " to " + foundI);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001603
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001604 localmWindows.add(foundI, wallpaper);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001605 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001606 }
1607 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001608
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001609 return changed;
1610 }
1611
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001612 void setWallpaperAnimLayerAdjustmentLocked(int adj) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001613 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001614 "Setting wallpaper layer adj to " + adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001615 mWallpaperAnimLayerAdjustment = adj;
1616 int curTokenIndex = mWallpaperTokens.size();
1617 while (curTokenIndex > 0) {
1618 curTokenIndex--;
1619 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1620 int curWallpaperIndex = token.windows.size();
1621 while (curWallpaperIndex > 0) {
1622 curWallpaperIndex--;
1623 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1624 wallpaper.mAnimLayer = wallpaper.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001625 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001626 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001627 }
1628 }
1629 }
1630
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001631 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1632 boolean sync) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001633 boolean changed = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001634 boolean rawChanged = false;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001635 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001636 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001637 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1638 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1639 changed = wallpaperWin.mXOffset != offset;
1640 if (changed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001641 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001642 + wallpaperWin + " x: " + offset);
1643 wallpaperWin.mXOffset = offset;
1644 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001645 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001646 wallpaperWin.mWallpaperX = wpx;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001647 wallpaperWin.mWallpaperXStep = wpxs;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001648 rawChanged = true;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001649 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001650
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001651 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001652 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001653 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1654 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
1655 if (wallpaperWin.mYOffset != offset) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001656 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001657 + wallpaperWin + " y: " + offset);
1658 changed = true;
1659 wallpaperWin.mYOffset = offset;
1660 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001661 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001662 wallpaperWin.mWallpaperY = wpy;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001663 wallpaperWin.mWallpaperYStep = wpys;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001664 rawChanged = true;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001665 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001666
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001667 if (rawChanged) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001668 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001669 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001670 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1671 + " y=" + wallpaperWin.mWallpaperY);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001672 if (sync) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001673 mWaitingOnWallpaper = wallpaperWin;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001674 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001675 wallpaperWin.mClient.dispatchWallpaperOffsets(
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001676 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
1677 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001678 if (sync) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001679 if (mWaitingOnWallpaper != null) {
1680 long start = SystemClock.uptimeMillis();
1681 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
1682 < start) {
1683 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001684 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn75804932009-10-20 20:15:20 -07001685 "Waiting for offset complete...");
1686 mWindowMap.wait(WALLPAPER_TIMEOUT);
1687 } catch (InterruptedException e) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001688 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001689 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
Dianne Hackborn75804932009-10-20 20:15:20 -07001690 if ((start+WALLPAPER_TIMEOUT)
1691 < SystemClock.uptimeMillis()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001692 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
Dianne Hackborn75804932009-10-20 20:15:20 -07001693 + wallpaperWin);
1694 mLastWallpaperTimeoutTime = start;
1695 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001696 }
Dianne Hackborn75804932009-10-20 20:15:20 -07001697 mWaitingOnWallpaper = null;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001698 }
1699 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001700 } catch (RemoteException e) {
1701 }
1702 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001703
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001704 return changed;
1705 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001706
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001707 void wallpaperOffsetsComplete(IBinder window) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001708 synchronized (mWindowMap) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001709 if (mWaitingOnWallpaper != null &&
1710 mWaitingOnWallpaper.mClient.asBinder() == window) {
1711 mWaitingOnWallpaper = null;
Dianne Hackborn75804932009-10-20 20:15:20 -07001712 mWindowMap.notifyAll();
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001713 }
1714 }
1715 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001716
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001717 boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001718 final int dw = mDisplay.getWidth();
1719 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001720
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001721 boolean changed = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001722
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001723 WindowState target = mWallpaperTarget;
1724 if (target != null) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001725 if (target.mWallpaperX >= 0) {
1726 mLastWallpaperX = target.mWallpaperX;
1727 } else if (changingTarget.mWallpaperX >= 0) {
1728 mLastWallpaperX = changingTarget.mWallpaperX;
1729 }
1730 if (target.mWallpaperY >= 0) {
1731 mLastWallpaperY = target.mWallpaperY;
1732 } else if (changingTarget.mWallpaperY >= 0) {
1733 mLastWallpaperY = changingTarget.mWallpaperY;
1734 }
1735 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001736
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001737 int curTokenIndex = mWallpaperTokens.size();
1738 while (curTokenIndex > 0) {
1739 curTokenIndex--;
1740 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1741 int curWallpaperIndex = token.windows.size();
1742 while (curWallpaperIndex > 0) {
1743 curWallpaperIndex--;
1744 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1745 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
1746 wallpaper.computeShownFrameLocked();
1747 changed = true;
1748 // We only want to be synchronous with one wallpaper.
1749 sync = false;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001750 }
1751 }
1752 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001753
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001754 return changed;
1755 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001756
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001757 void updateWallpaperVisibilityLocked() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07001758 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001759 final int dw = mDisplay.getWidth();
1760 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001761
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001762 int curTokenIndex = mWallpaperTokens.size();
1763 while (curTokenIndex > 0) {
1764 curTokenIndex--;
1765 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001766 if (token.hidden == visible) {
1767 token.hidden = !visible;
1768 // Need to do a layout to ensure the wallpaper now has the
1769 // correct size.
1770 mLayoutNeeded = true;
1771 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001772
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001773 int curWallpaperIndex = token.windows.size();
1774 while (curWallpaperIndex > 0) {
1775 curWallpaperIndex--;
1776 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1777 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001778 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001779 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001780
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001781 if (wallpaper.mWallpaperVisible != visible) {
1782 wallpaper.mWallpaperVisible = visible;
1783 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001784 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07001785 "Updating visibility of wallpaper " + wallpaper
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001786 + ": " + visible);
1787 wallpaper.mClient.dispatchAppVisibility(visible);
1788 } catch (RemoteException e) {
1789 }
1790 }
1791 }
1792 }
1793 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001794
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001795 void sendPointerToWallpaperLocked(WindowState srcWin,
1796 MotionEvent pointer, long eventTime) {
1797 int curTokenIndex = mWallpaperTokens.size();
1798 while (curTokenIndex > 0) {
1799 curTokenIndex--;
1800 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1801 int curWallpaperIndex = token.windows.size();
1802 while (curWallpaperIndex > 0) {
1803 curWallpaperIndex--;
1804 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1805 if ((wallpaper.mAttrs.flags &
1806 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
1807 continue;
1808 }
1809 try {
1810 MotionEvent ev = MotionEvent.obtainNoHistory(pointer);
Dianne Hackborn6adba242009-11-10 11:10:09 -08001811 if (srcWin != null) {
1812 ev.offsetLocation(srcWin.mFrame.left-wallpaper.mFrame.left,
1813 srcWin.mFrame.top-wallpaper.mFrame.top);
1814 } else {
1815 ev.offsetLocation(-wallpaper.mFrame.left, -wallpaper.mFrame.top);
1816 }
1817 switch (pointer.getAction()) {
1818 case MotionEvent.ACTION_DOWN:
1819 mSendingPointersToWallpaper = true;
1820 break;
1821 case MotionEvent.ACTION_UP:
1822 mSendingPointersToWallpaper = false;
1823 break;
1824 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001825 wallpaper.mClient.dispatchPointer(ev, eventTime, false);
1826 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001827 Slog.w(TAG, "Failure sending pointer to wallpaper", e);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001828 }
1829 }
1830 }
1831 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001832
Dianne Hackborn90d2db32010-02-11 22:19:06 -08001833 void dispatchPointerElsewhereLocked(WindowState srcWin, WindowState relWin,
1834 MotionEvent pointer, long eventTime, boolean skipped) {
1835 if (relWin != null) {
1836 mPolicy.dispatchedPointerEventLw(pointer, relWin.mFrame.left, relWin.mFrame.top);
1837 } else {
1838 mPolicy.dispatchedPointerEventLw(pointer, 0, 0);
1839 }
1840
1841 // If we sent an initial down to the wallpaper, then continue
1842 // sending events until the final up.
1843 if (mSendingPointersToWallpaper) {
1844 if (skipped) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001845 Slog.i(TAG, "Sending skipped pointer to wallpaper!");
Dianne Hackborn90d2db32010-02-11 22:19:06 -08001846 }
1847 sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1848
1849 // If we are on top of the wallpaper, then the wallpaper also
1850 // gets to see this movement.
1851 } else if (srcWin != null
1852 && pointer.getAction() == MotionEvent.ACTION_DOWN
1853 && mWallpaperTarget == srcWin
1854 && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
1855 sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1856 }
1857 }
1858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001859 public int addWindow(Session session, IWindow client,
1860 WindowManager.LayoutParams attrs, int viewVisibility,
1861 Rect outContentInsets) {
1862 int res = mPolicy.checkAddPermission(attrs);
1863 if (res != WindowManagerImpl.ADD_OKAY) {
1864 return res;
1865 }
Romain Guy06882f82009-06-10 13:36:04 -07001866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001867 boolean reportNewConfig = false;
1868 WindowState attachedWindow = null;
1869 WindowState win = null;
Romain Guy06882f82009-06-10 13:36:04 -07001870
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001871 synchronized(mWindowMap) {
1872 // Instantiating a Display requires talking with the simulator,
1873 // so don't do it until we know the system is mostly up and
1874 // running.
1875 if (mDisplay == null) {
1876 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1877 mDisplay = wm.getDefaultDisplay();
Christopher Tateb696aee2010-04-02 19:08:30 -07001878 mInitialDisplayWidth = mDisplay.getWidth();
1879 mInitialDisplayHeight = mDisplay.getHeight();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001880 mQueue.setDisplay(mDisplay);
1881 reportNewConfig = true;
1882 }
Romain Guy06882f82009-06-10 13:36:04 -07001883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001884 if (mWindowMap.containsKey(client.asBinder())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001885 Slog.w(TAG, "Window " + client + " is already added");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001886 return WindowManagerImpl.ADD_DUPLICATE_ADD;
1887 }
1888
1889 if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001890 attachedWindow = windowForClientLocked(null, attrs.token, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 if (attachedWindow == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001892 Slog.w(TAG, "Attempted to add window with token that is not a window: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 + attrs.token + ". Aborting.");
1894 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1895 }
1896 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1897 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001898 Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001899 + attrs.token + ". Aborting.");
1900 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1901 }
1902 }
1903
1904 boolean addToken = false;
1905 WindowToken token = mTokenMap.get(attrs.token);
1906 if (token == null) {
1907 if (attrs.type >= FIRST_APPLICATION_WINDOW
1908 && attrs.type <= LAST_APPLICATION_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001909 Slog.w(TAG, "Attempted to add application window with unknown token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 + attrs.token + ". Aborting.");
1911 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1912 }
1913 if (attrs.type == TYPE_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001914 Slog.w(TAG, "Attempted to add input method window with unknown token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001915 + attrs.token + ". Aborting.");
1916 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1917 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001918 if (attrs.type == TYPE_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001919 Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001920 + attrs.token + ". Aborting.");
1921 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1922 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001923 token = new WindowToken(attrs.token, -1, false);
1924 addToken = true;
1925 } else if (attrs.type >= FIRST_APPLICATION_WINDOW
1926 && attrs.type <= LAST_APPLICATION_WINDOW) {
1927 AppWindowToken atoken = token.appWindowToken;
1928 if (atoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001929 Slog.w(TAG, "Attempted to add window with non-application token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 + token + ". Aborting.");
1931 return WindowManagerImpl.ADD_NOT_APP_TOKEN;
1932 } else if (atoken.removed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001933 Slog.w(TAG, "Attempted to add window with exiting application token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001934 + token + ". Aborting.");
1935 return WindowManagerImpl.ADD_APP_EXITING;
1936 }
1937 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1938 // No need for this guy!
Joe Onorato8a9b2202010-02-26 18:56:32 -08001939 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001940 TAG, "**** NO NEED TO START: " + attrs.getTitle());
1941 return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
1942 }
1943 } else if (attrs.type == TYPE_INPUT_METHOD) {
1944 if (token.windowType != TYPE_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001945 Slog.w(TAG, "Attempted to add input method window with bad token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001946 + attrs.token + ". Aborting.");
1947 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1948 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001949 } else if (attrs.type == TYPE_WALLPAPER) {
1950 if (token.windowType != TYPE_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001951 Slog.w(TAG, "Attempted to add wallpaper window with bad token "
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001952 + attrs.token + ". Aborting.");
1953 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1954 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001955 }
1956
1957 win = new WindowState(session, client, token,
1958 attachedWindow, attrs, viewVisibility);
1959 if (win.mDeathRecipient == null) {
1960 // Client has apparently died, so there is no reason to
1961 // continue.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001962 Slog.w(TAG, "Adding window client " + client.asBinder()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963 + " that is dead, aborting.");
1964 return WindowManagerImpl.ADD_APP_EXITING;
1965 }
1966
1967 mPolicy.adjustWindowParamsLw(win.mAttrs);
Romain Guy06882f82009-06-10 13:36:04 -07001968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001969 res = mPolicy.prepareAddWindowLw(win, attrs);
1970 if (res != WindowManagerImpl.ADD_OKAY) {
1971 return res;
1972 }
1973
1974 // From now on, no exceptions or errors allowed!
1975
1976 res = WindowManagerImpl.ADD_OKAY;
Romain Guy06882f82009-06-10 13:36:04 -07001977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001978 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07001979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001980 if (addToken) {
1981 mTokenMap.put(attrs.token, token);
1982 mTokenList.add(token);
1983 }
1984 win.attach();
1985 mWindowMap.put(client.asBinder(), win);
1986
1987 if (attrs.type == TYPE_APPLICATION_STARTING &&
1988 token.appWindowToken != null) {
1989 token.appWindowToken.startingWindow = win;
1990 }
1991
1992 boolean imMayMove = true;
Romain Guy06882f82009-06-10 13:36:04 -07001993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994 if (attrs.type == TYPE_INPUT_METHOD) {
1995 mInputMethodWindow = win;
1996 addInputMethodWindowToListLocked(win);
1997 imMayMove = false;
1998 } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
1999 mInputMethodDialogs.add(win);
2000 addWindowToListInOrderLocked(win, true);
2001 adjustInputMethodDialogsLocked();
2002 imMayMove = false;
2003 } else {
2004 addWindowToListInOrderLocked(win, true);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002005 if (attrs.type == TYPE_WALLPAPER) {
2006 mLastWallpaperTimeoutTime = 0;
2007 adjustWallpaperWindowsLocked();
2008 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002009 adjustWallpaperWindowsLocked();
2010 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002011 }
Romain Guy06882f82009-06-10 13:36:04 -07002012
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002013 win.mEnterAnimationPending = true;
Romain Guy06882f82009-06-10 13:36:04 -07002014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
Romain Guy06882f82009-06-10 13:36:04 -07002016
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 if (mInTouchMode) {
2018 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
2019 }
2020 if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
2021 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
2022 }
Romain Guy06882f82009-06-10 13:36:04 -07002023
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002024 boolean focusChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002025 if (win.canReceiveKeys()) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002026 if ((focusChanged=updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS))
2027 == true) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002028 imMayMove = false;
2029 }
2030 }
Romain Guy06882f82009-06-10 13:36:04 -07002031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002032 if (imMayMove) {
Romain Guy06882f82009-06-10 13:36:04 -07002033 moveInputMethodWindowsIfNeededLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002034 }
Romain Guy06882f82009-06-10 13:36:04 -07002035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002036 assignLayersLocked();
2037 // Don't do layout here, the window must call
2038 // relayout to be displayed, so we'll do it there.
Romain Guy06882f82009-06-10 13:36:04 -07002039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 //dump();
2041
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002042 if (focusChanged) {
2043 if (mCurrentFocus != null) {
2044 mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
2045 }
2046 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002047 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002048 TAG, "New client " + client.asBinder()
2049 + ": window=" + win);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002050
2051 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked()) {
2052 reportNewConfig = true;
2053 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 }
2055
2056 // sendNewConfiguration() checks caller permissions so we must call it with
2057 // privilege. updateOrientationFromAppTokens() clears and resets the caller
2058 // identity anyway, so it's safe to just clear & restore around this whole
2059 // block.
2060 final long origId = Binder.clearCallingIdentity();
2061 if (reportNewConfig) {
2062 sendNewConfiguration();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002063 }
2064 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07002065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002066 return res;
2067 }
Romain Guy06882f82009-06-10 13:36:04 -07002068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002069 public void removeWindow(Session session, IWindow client) {
2070 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002071 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 if (win == null) {
2073 return;
2074 }
2075 removeWindowLocked(session, win);
2076 }
2077 }
Romain Guy06882f82009-06-10 13:36:04 -07002078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002079 public void removeWindowLocked(Session session, WindowState win) {
2080
Joe Onorato8a9b2202010-02-26 18:56:32 -08002081 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 TAG, "Remove " + win + " client="
2083 + Integer.toHexString(System.identityHashCode(
2084 win.mClient.asBinder()))
2085 + ", surface=" + win.mSurface);
2086
2087 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002088
Joe Onorato8a9b2202010-02-26 18:56:32 -08002089 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002090 TAG, "Remove " + win + ": mSurface=" + win.mSurface
2091 + " mExiting=" + win.mExiting
2092 + " isAnimating=" + win.isAnimating()
2093 + " app-animation="
2094 + (win.mAppToken != null ? win.mAppToken.animation : null)
2095 + " inPendingTransaction="
2096 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2097 + " mDisplayFrozen=" + mDisplayFrozen);
2098 // Visibility of the removed window. Will be used later to update orientation later on.
2099 boolean wasVisible = false;
2100 // First, see if we need to run an animation. If we do, we have
2101 // to hold off on removing the window until the animation is done.
2102 // If the display is frozen, just remove immediately, since the
2103 // animation wouldn't be seen.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002104 if (win.mSurface != null && !mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002105 // If we are not currently running the exit animation, we
2106 // need to see about starting one.
2107 if (wasVisible=win.isWinVisibleLw()) {
Romain Guy06882f82009-06-10 13:36:04 -07002108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2110 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2111 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2112 }
2113 // Try starting an animation.
2114 if (applyAnimationLocked(win, transit, false)) {
2115 win.mExiting = true;
2116 }
2117 }
2118 if (win.mExiting || win.isAnimating()) {
2119 // The exit animation is running... wait for it!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002120 //Slog.i(TAG, "*** Running exit animation...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002121 win.mExiting = true;
2122 win.mRemoveOnExit = true;
2123 mLayoutNeeded = true;
2124 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
2125 performLayoutAndPlaceSurfacesLocked();
2126 if (win.mAppToken != null) {
2127 win.mAppToken.updateReportedVisibilityLocked();
2128 }
2129 //dump();
2130 Binder.restoreCallingIdentity(origId);
2131 return;
2132 }
2133 }
2134
2135 removeWindowInnerLocked(session, win);
2136 // Removing a visible window will effect the computed orientation
2137 // So just update orientation if needed.
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002138 if (wasVisible && computeForcedAppOrientationLocked()
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002139 != mForcedAppOrientation
2140 && updateOrientationFromAppTokensLocked()) {
2141 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 }
2143 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2144 Binder.restoreCallingIdentity(origId);
2145 }
Romain Guy06882f82009-06-10 13:36:04 -07002146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 private void removeWindowInnerLocked(Session session, WindowState win) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07002148 mKeyWaiter.finishedKey(session, win.mClient, true,
2149 KeyWaiter.RETURN_NOTHING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002150 mKeyWaiter.releasePendingPointerLocked(win.mSession);
2151 mKeyWaiter.releasePendingTrackballLocked(win.mSession);
Romain Guy06882f82009-06-10 13:36:04 -07002152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002153 win.mRemoved = true;
Romain Guy06882f82009-06-10 13:36:04 -07002154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002155 if (mInputMethodTarget == win) {
2156 moveInputMethodWindowsIfNeededLocked(false);
2157 }
Romain Guy06882f82009-06-10 13:36:04 -07002158
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002159 if (false) {
2160 RuntimeException e = new RuntimeException("here");
2161 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002162 Slog.w(TAG, "Removing window " + win, e);
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002163 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002165 mPolicy.removeWindowLw(win);
2166 win.removeLocked();
2167
2168 mWindowMap.remove(win.mClient.asBinder());
2169 mWindows.remove(win);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002170 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002171
2172 if (mInputMethodWindow == win) {
2173 mInputMethodWindow = null;
2174 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2175 mInputMethodDialogs.remove(win);
2176 }
Romain Guy06882f82009-06-10 13:36:04 -07002177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002178 final WindowToken token = win.mToken;
2179 final AppWindowToken atoken = win.mAppToken;
2180 token.windows.remove(win);
2181 if (atoken != null) {
2182 atoken.allAppWindows.remove(win);
2183 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002184 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 TAG, "**** Removing window " + win + ": count="
2186 + token.windows.size());
2187 if (token.windows.size() == 0) {
2188 if (!token.explicit) {
2189 mTokenMap.remove(token.token);
2190 mTokenList.remove(token);
2191 } else if (atoken != null) {
2192 atoken.firstWindowDrawn = false;
2193 }
2194 }
2195
2196 if (atoken != null) {
2197 if (atoken.startingWindow == win) {
2198 atoken.startingWindow = null;
2199 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2200 // If this is the last window and we had requested a starting
2201 // transition window, well there is no point now.
2202 atoken.startingData = null;
2203 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2204 // If this is the last window except for a starting transition
2205 // window, we need to get rid of the starting transition.
2206 if (DEBUG_STARTING_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002207 Slog.v(TAG, "Schedule remove starting " + token
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002208 + ": no more real windows");
2209 }
2210 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
2211 mH.sendMessage(m);
2212 }
2213 }
Romain Guy06882f82009-06-10 13:36:04 -07002214
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002215 if (win.mAttrs.type == TYPE_WALLPAPER) {
2216 mLastWallpaperTimeoutTime = 0;
2217 adjustWallpaperWindowsLocked();
2218 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07002219 adjustWallpaperWindowsLocked();
2220 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002222 if (!mInLayout) {
2223 assignLayersLocked();
2224 mLayoutNeeded = true;
2225 performLayoutAndPlaceSurfacesLocked();
2226 if (win.mAppToken != null) {
2227 win.mAppToken.updateReportedVisibilityLocked();
2228 }
2229 }
2230 }
2231
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002232 private static void logSurface(WindowState w, String msg, RuntimeException where) {
2233 String str = " SURFACE " + Integer.toHexString(w.hashCode())
2234 + ": " + msg + " / " + w.mAttrs.getTitle();
2235 if (where != null) {
2236 Slog.i(TAG, str, where);
2237 } else {
2238 Slog.i(TAG, str);
2239 }
2240 }
2241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002242 private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2243 long origId = Binder.clearCallingIdentity();
2244 try {
2245 synchronized (mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002246 WindowState w = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002247 if ((w != null) && (w.mSurface != null)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002248 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002249 Surface.openTransaction();
2250 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002251 if (SHOW_TRANSACTIONS) logSurface(w,
2252 "transparentRegionHint=" + region, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002253 w.mSurface.setTransparentRegionHint(region);
2254 } finally {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002255 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002256 Surface.closeTransaction();
2257 }
2258 }
2259 }
2260 } finally {
2261 Binder.restoreCallingIdentity(origId);
2262 }
2263 }
2264
2265 void setInsetsWindow(Session session, IWindow client,
Romain Guy06882f82009-06-10 13:36:04 -07002266 int touchableInsets, Rect contentInsets,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002267 Rect visibleInsets) {
2268 long origId = Binder.clearCallingIdentity();
2269 try {
2270 synchronized (mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002271 WindowState w = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 if (w != null) {
2273 w.mGivenInsetsPending = false;
2274 w.mGivenContentInsets.set(contentInsets);
2275 w.mGivenVisibleInsets.set(visibleInsets);
2276 w.mTouchableInsets = touchableInsets;
2277 mLayoutNeeded = true;
2278 performLayoutAndPlaceSurfacesLocked();
2279 }
2280 }
2281 } finally {
2282 Binder.restoreCallingIdentity(origId);
2283 }
2284 }
Romain Guy06882f82009-06-10 13:36:04 -07002285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002286 public void getWindowDisplayFrame(Session session, IWindow client,
2287 Rect outDisplayFrame) {
2288 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002289 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002290 if (win == null) {
2291 outDisplayFrame.setEmpty();
2292 return;
2293 }
2294 outDisplayFrame.set(win.mDisplayFrame);
2295 }
2296 }
2297
Marco Nelissenbf6956b2009-11-09 15:21:13 -08002298 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2299 float xStep, float yStep) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002300 if (window.mWallpaperX != x || window.mWallpaperY != y) {
2301 window.mWallpaperX = x;
2302 window.mWallpaperY = y;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08002303 window.mWallpaperXStep = xStep;
2304 window.mWallpaperYStep = yStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07002305 if (updateWallpaperOffsetLocked(window, true)) {
2306 performLayoutAndPlaceSurfacesLocked();
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002307 }
2308 }
2309 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002310
Dianne Hackborn75804932009-10-20 20:15:20 -07002311 void wallpaperCommandComplete(IBinder window, Bundle result) {
2312 synchronized (mWindowMap) {
2313 if (mWaitingOnWallpaper != null &&
2314 mWaitingOnWallpaper.mClient.asBinder() == window) {
2315 mWaitingOnWallpaper = null;
2316 mWindowMap.notifyAll();
2317 }
2318 }
2319 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002320
Dianne Hackborn75804932009-10-20 20:15:20 -07002321 public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2322 String action, int x, int y, int z, Bundle extras, boolean sync) {
2323 if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2324 || window == mUpperWallpaperTarget) {
2325 boolean doWait = sync;
2326 int curTokenIndex = mWallpaperTokens.size();
2327 while (curTokenIndex > 0) {
2328 curTokenIndex--;
2329 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2330 int curWallpaperIndex = token.windows.size();
2331 while (curWallpaperIndex > 0) {
2332 curWallpaperIndex--;
2333 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2334 try {
2335 wallpaper.mClient.dispatchWallpaperCommand(action,
2336 x, y, z, extras, sync);
2337 // We only want to be synchronous with one wallpaper.
2338 sync = false;
2339 } catch (RemoteException e) {
2340 }
2341 }
2342 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002343
Dianne Hackborn75804932009-10-20 20:15:20 -07002344 if (doWait) {
2345 // XXX Need to wait for result.
2346 }
2347 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002348
Dianne Hackborn75804932009-10-20 20:15:20 -07002349 return null;
2350 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 public int relayoutWindow(Session session, IWindow client,
2353 WindowManager.LayoutParams attrs, int requestedWidth,
2354 int requestedHeight, int viewVisibility, boolean insetsPending,
2355 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07002356 Configuration outConfig, Surface outSurface) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002357 boolean displayed = false;
2358 boolean inTouchMode;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002359 boolean configChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002360 long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002361
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002362 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002363 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002364 if (win == null) {
2365 return 0;
2366 }
2367 win.mRequestedWidth = requestedWidth;
2368 win.mRequestedHeight = requestedHeight;
2369
2370 if (attrs != null) {
2371 mPolicy.adjustWindowParamsLw(attrs);
2372 }
Romain Guy06882f82009-06-10 13:36:04 -07002373
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002374 int attrChanges = 0;
2375 int flagChanges = 0;
2376 if (attrs != null) {
2377 flagChanges = win.mAttrs.flags ^= attrs.flags;
2378 attrChanges = win.mAttrs.copyFrom(attrs);
2379 }
2380
Joe Onorato8a9b2202010-02-26 18:56:32 -08002381 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": " + win.mAttrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002382
2383 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2384 win.mAlpha = attrs.alpha;
2385 }
2386
2387 final boolean scaledWindow =
2388 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2389
2390 if (scaledWindow) {
2391 // requested{Width|Height} Surface's physical size
2392 // attrs.{width|height} Size on screen
2393 win.mHScale = (attrs.width != requestedWidth) ?
2394 (attrs.width / (float)requestedWidth) : 1.0f;
2395 win.mVScale = (attrs.height != requestedHeight) ?
2396 (attrs.height / (float)requestedHeight) : 1.0f;
Dianne Hackborn9b52a212009-12-11 14:51:35 -08002397 } else {
2398 win.mHScale = win.mVScale = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002399 }
2400
2401 boolean imMayMove = (flagChanges&(
2402 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
2403 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07002404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002405 boolean focusMayChange = win.mViewVisibility != viewVisibility
2406 || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
2407 || (!win.mRelayoutCalled);
Romain Guy06882f82009-06-10 13:36:04 -07002408
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002409 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2410 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002412 win.mRelayoutCalled = true;
2413 final int oldVisibility = win.mViewVisibility;
2414 win.mViewVisibility = viewVisibility;
2415 if (viewVisibility == View.VISIBLE &&
2416 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2417 displayed = !win.isVisibleLw();
2418 if (win.mExiting) {
2419 win.mExiting = false;
2420 win.mAnimation = null;
2421 }
2422 if (win.mDestroying) {
2423 win.mDestroying = false;
2424 mDestroySurface.remove(win);
2425 }
2426 if (oldVisibility == View.GONE) {
2427 win.mEnterAnimationPending = true;
2428 }
Dianne Hackborn694f79b2010-03-17 19:44:59 -07002429 if (displayed) {
2430 if (win.mSurface != null && !win.mDrawPending
2431 && !win.mCommitDrawPending && !mDisplayFrozen
2432 && mPolicy.isScreenOn()) {
2433 applyEnterAnimationLocked(win);
2434 }
2435 if ((win.mAttrs.flags
2436 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2437 if (DEBUG_VISIBILITY) Slog.v(TAG,
2438 "Relayout window turning screen on: " + win);
2439 win.mTurnOnScreen = true;
2440 }
2441 int diff = 0;
2442 if (win.mConfiguration != mCurConfiguration
2443 && (win.mConfiguration == null
2444 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0)) {
2445 win.mConfiguration = mCurConfiguration;
2446 if (DEBUG_CONFIGURATION) {
2447 Slog.i(TAG, "Window " + win + " visible with new config: "
2448 + win.mConfiguration + " / 0x"
2449 + Integer.toHexString(diff));
2450 }
2451 outConfig.setTo(mCurConfiguration);
2452 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07002453 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002454 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2455 // To change the format, we need to re-build the surface.
2456 win.destroySurfaceLocked();
2457 displayed = true;
2458 }
2459 try {
2460 Surface surface = win.createSurfaceLocked();
2461 if (surface != null) {
2462 outSurface.copyFrom(surface);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002463 win.mReportDestroySurface = false;
2464 win.mSurfacePendingDestroy = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002465 if (SHOW_TRANSACTIONS) Slog.i(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002466 " OUT SURFACE " + outSurface + ": copied");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467 } else {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002468 // For some reason there isn't a surface. Clear the
2469 // caller's object so they see the same state.
2470 outSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002471 }
2472 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002473 Slog.w(TAG, "Exception thrown when creating surface for client "
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002474 + client + " (" + win.mAttrs.getTitle() + ")",
2475 e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002476 Binder.restoreCallingIdentity(origId);
2477 return 0;
2478 }
2479 if (displayed) {
2480 focusMayChange = true;
2481 }
2482 if (win.mAttrs.type == TYPE_INPUT_METHOD
2483 && mInputMethodWindow == null) {
2484 mInputMethodWindow = win;
2485 imMayMove = true;
2486 }
Dianne Hackborn558947c2009-12-18 16:02:50 -08002487 if (win.mAttrs.type == TYPE_BASE_APPLICATION
2488 && win.mAppToken != null
2489 && win.mAppToken.startingWindow != null) {
2490 // Special handling of starting window over the base
2491 // window of the app: propagate lock screen flags to it,
2492 // to provide the correct semantics while starting.
2493 final int mask =
2494 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
Mike Lockwoodef731622010-01-27 17:51:34 -05002495 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
2496 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
Dianne Hackborn558947c2009-12-18 16:02:50 -08002497 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
2498 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
2499 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500 } else {
2501 win.mEnterAnimationPending = false;
2502 if (win.mSurface != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002503 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002504 + ": mExiting=" + win.mExiting
2505 + " mSurfacePendingDestroy=" + win.mSurfacePendingDestroy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002506 // If we are not currently running the exit animation, we
2507 // need to see about starting one.
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002508 if (!win.mExiting || win.mSurfacePendingDestroy) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002509 // Try starting an animation; if there isn't one, we
2510 // can destroy the surface right away.
2511 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2512 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2513 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2514 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002515 if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002516 applyAnimationLocked(win, transit, false)) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002517 focusMayChange = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002518 win.mExiting = true;
2519 mKeyWaiter.finishedKey(session, client, true,
2520 KeyWaiter.RETURN_NOTHING);
2521 } else if (win.isAnimating()) {
2522 // Currently in a hide animation... turn this into
2523 // an exit.
2524 win.mExiting = true;
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07002525 } else if (win == mWallpaperTarget) {
2526 // If the wallpaper is currently behind this
2527 // window, we need to change both of them inside
2528 // of a transaction to avoid artifacts.
2529 win.mExiting = true;
2530 win.mAnimating = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002531 } else {
2532 if (mInputMethodWindow == win) {
2533 mInputMethodWindow = null;
2534 }
2535 win.destroySurfaceLocked();
2536 }
2537 }
2538 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002539
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002540 if (win.mSurface == null || (win.getAttrs().flags
2541 & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0
2542 || win.mSurfacePendingDestroy) {
2543 // We are being called from a local process, which
2544 // means outSurface holds its current surface. Ensure the
2545 // surface object is cleared, but we don't want it actually
2546 // destroyed at this point.
2547 win.mSurfacePendingDestroy = false;
2548 outSurface.release();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002549 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002550 } else if (win.mSurface != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002551 if (DEBUG_VISIBILITY) Slog.i(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002552 "Keeping surface, will report destroy: " + win);
2553 win.mReportDestroySurface = true;
2554 outSurface.copyFrom(win.mSurface);
2555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002556 }
2557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002558 if (focusMayChange) {
2559 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2560 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002561 imMayMove = false;
2562 }
2563 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2564 }
Romain Guy06882f82009-06-10 13:36:04 -07002565
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002566 // updateFocusedWindowLocked() already assigned layers so we only need to
2567 // reassign them at this point if the IM window state gets shuffled
2568 boolean assignLayers = false;
Romain Guy06882f82009-06-10 13:36:04 -07002569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002570 if (imMayMove) {
Dianne Hackborn8abd5f02009-11-20 18:09:03 -08002571 if (moveInputMethodWindowsIfNeededLocked(false) || displayed) {
2572 // Little hack here -- we -should- be able to rely on the
2573 // function to return true if the IME has moved and needs
2574 // its layer recomputed. However, if the IME was hidden
2575 // and isn't actually moved in the list, its layer may be
2576 // out of data so we make sure to recompute it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002577 assignLayers = true;
2578 }
2579 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002580 if (wallpaperMayMove) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002581 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002582 assignLayers = true;
2583 }
2584 }
Romain Guy06882f82009-06-10 13:36:04 -07002585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002586 mLayoutNeeded = true;
2587 win.mGivenInsetsPending = insetsPending;
2588 if (assignLayers) {
2589 assignLayersLocked();
2590 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002591 configChanged = updateOrientationFromAppTokensLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002592 performLayoutAndPlaceSurfacesLocked();
Dianne Hackborn284ac932009-08-28 10:34:25 -07002593 if (displayed && win.mIsWallpaper) {
2594 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002595 mDisplay.getHeight(), false);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597 if (win.mAppToken != null) {
2598 win.mAppToken.updateReportedVisibilityLocked();
2599 }
2600 outFrame.set(win.mFrame);
2601 outContentInsets.set(win.mContentInsets);
2602 outVisibleInsets.set(win.mVisibleInsets);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002603 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002604 TAG, "Relayout given client " + client.asBinder()
Romain Guy06882f82009-06-10 13:36:04 -07002605 + ", requestedWidth=" + requestedWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002606 + ", requestedHeight=" + requestedHeight
2607 + ", viewVisibility=" + viewVisibility
2608 + "\nRelayout returning frame=" + outFrame
2609 + ", surface=" + outSurface);
2610
Joe Onorato8a9b2202010-02-26 18:56:32 -08002611 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002612 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2613
2614 inTouchMode = mInTouchMode;
2615 }
2616
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002617 if (configChanged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002618 sendNewConfiguration();
2619 }
Romain Guy06882f82009-06-10 13:36:04 -07002620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002621 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07002622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002623 return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
2624 | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
2625 }
2626
2627 public void finishDrawingWindow(Session session, IWindow client) {
2628 final long origId = Binder.clearCallingIdentity();
2629 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002630 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002631 if (win != null && win.finishDrawingLocked()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07002632 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2633 adjustWallpaperWindowsLocked();
2634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002635 mLayoutNeeded = true;
2636 performLayoutAndPlaceSurfacesLocked();
2637 }
2638 }
2639 Binder.restoreCallingIdentity(origId);
2640 }
2641
2642 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002643 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002644 + (lp != null ? lp.packageName : null)
2645 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
2646 if (lp != null && lp.windowAnimations != 0) {
2647 // If this is a system resource, don't try to load it from the
2648 // application resources. It is nice to avoid loading application
2649 // resources if we can.
2650 String packageName = lp.packageName != null ? lp.packageName : "android";
2651 int resId = lp.windowAnimations;
2652 if ((resId&0xFF000000) == 0x01000000) {
2653 packageName = "android";
2654 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002655 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002656 + packageName);
2657 return AttributeCache.instance().get(packageName, resId,
2658 com.android.internal.R.styleable.WindowAnimation);
2659 }
2660 return null;
2661 }
Romain Guy06882f82009-06-10 13:36:04 -07002662
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002663 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002664 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002665 + packageName + " resId=0x" + Integer.toHexString(resId));
2666 if (packageName != null) {
2667 if ((resId&0xFF000000) == 0x01000000) {
2668 packageName = "android";
2669 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002670 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002671 + packageName);
2672 return AttributeCache.instance().get(packageName, resId,
2673 com.android.internal.R.styleable.WindowAnimation);
2674 }
2675 return null;
2676 }
2677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002678 private void applyEnterAnimationLocked(WindowState win) {
2679 int transit = WindowManagerPolicy.TRANSIT_SHOW;
2680 if (win.mEnterAnimationPending) {
2681 win.mEnterAnimationPending = false;
2682 transit = WindowManagerPolicy.TRANSIT_ENTER;
2683 }
2684
2685 applyAnimationLocked(win, transit, true);
2686 }
2687
2688 private boolean applyAnimationLocked(WindowState win,
2689 int transit, boolean isEntrance) {
2690 if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
2691 // If we are trying to apply an animation, but already running
2692 // an animation of the same type, then just leave that one alone.
2693 return true;
2694 }
Romain Guy06882f82009-06-10 13:36:04 -07002695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002696 // Only apply an animation if the display isn't frozen. If it is
2697 // frozen, there is no reason to animate and it can cause strange
2698 // artifacts when we unfreeze the display if some different animation
2699 // is running.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002700 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002701 int anim = mPolicy.selectAnimationLw(win, transit);
2702 int attr = -1;
2703 Animation a = null;
2704 if (anim != 0) {
2705 a = AnimationUtils.loadAnimation(mContext, anim);
2706 } else {
2707 switch (transit) {
2708 case WindowManagerPolicy.TRANSIT_ENTER:
2709 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
2710 break;
2711 case WindowManagerPolicy.TRANSIT_EXIT:
2712 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
2713 break;
2714 case WindowManagerPolicy.TRANSIT_SHOW:
2715 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
2716 break;
2717 case WindowManagerPolicy.TRANSIT_HIDE:
2718 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
2719 break;
2720 }
2721 if (attr >= 0) {
2722 a = loadAnimation(win.mAttrs, attr);
2723 }
2724 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002725 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: win=" + win
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002726 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
2727 + " mAnimation=" + win.mAnimation
2728 + " isEntrance=" + isEntrance);
2729 if (a != null) {
2730 if (DEBUG_ANIM) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002731 RuntimeException e = null;
2732 if (!HIDE_STACK_CRAWLS) {
2733 e = new RuntimeException();
2734 e.fillInStackTrace();
2735 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002736 Slog.v(TAG, "Loaded animation " + a + " for " + win, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002737 }
2738 win.setAnimation(a);
2739 win.mAnimationIsEntrance = isEntrance;
2740 }
2741 } else {
2742 win.clearAnimation();
2743 }
2744
2745 return win.mAnimation != null;
2746 }
2747
2748 private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
2749 int anim = 0;
2750 Context context = mContext;
2751 if (animAttr >= 0) {
2752 AttributeCache.Entry ent = getCachedAnimations(lp);
2753 if (ent != null) {
2754 context = ent.context;
2755 anim = ent.array.getResourceId(animAttr, 0);
2756 }
2757 }
2758 if (anim != 0) {
2759 return AnimationUtils.loadAnimation(context, anim);
2760 }
2761 return null;
2762 }
Romain Guy06882f82009-06-10 13:36:04 -07002763
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002764 private Animation loadAnimation(String packageName, int resId) {
2765 int anim = 0;
2766 Context context = mContext;
2767 if (resId >= 0) {
2768 AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
2769 if (ent != null) {
2770 context = ent.context;
2771 anim = resId;
2772 }
2773 }
2774 if (anim != 0) {
2775 return AnimationUtils.loadAnimation(context, anim);
2776 }
2777 return null;
2778 }
2779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002780 private boolean applyAnimationLocked(AppWindowToken wtoken,
2781 WindowManager.LayoutParams lp, int transit, boolean enter) {
2782 // Only apply an animation if the display isn't frozen. If it is
2783 // frozen, there is no reason to animate and it can cause strange
2784 // artifacts when we unfreeze the display if some different animation
2785 // is running.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002786 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002787 Animation a;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07002788 if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002789 a = new FadeInOutAnimation(enter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002790 if (DEBUG_ANIM) Slog.v(TAG,
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002791 "applying FadeInOutAnimation for a window in compatibility mode");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002792 } else if (mNextAppTransitionPackage != null) {
2793 a = loadAnimation(mNextAppTransitionPackage, enter ?
2794 mNextAppTransitionEnter : mNextAppTransitionExit);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002795 } else {
2796 int animAttr = 0;
2797 switch (transit) {
2798 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
2799 animAttr = enter
2800 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
2801 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
2802 break;
2803 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
2804 animAttr = enter
2805 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
2806 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
2807 break;
2808 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
2809 animAttr = enter
2810 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
2811 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
2812 break;
2813 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
2814 animAttr = enter
2815 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
2816 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
2817 break;
2818 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
2819 animAttr = enter
2820 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
2821 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
2822 break;
2823 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
2824 animAttr = enter
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07002825 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002826 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
2827 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002828 case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002829 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002830 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation
2831 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002832 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002833 case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002834 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002835 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation
2836 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
2837 break;
2838 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN:
2839 animAttr = enter
2840 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation
2841 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
2842 break;
2843 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE:
2844 animAttr = enter
2845 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation
2846 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002847 break;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002848 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002849 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002850 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002851 + " anim=" + a
2852 + " animAttr=0x" + Integer.toHexString(animAttr)
2853 + " transit=" + transit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002854 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002855 if (a != null) {
2856 if (DEBUG_ANIM) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002857 RuntimeException e = null;
2858 if (!HIDE_STACK_CRAWLS) {
2859 e = new RuntimeException();
2860 e.fillInStackTrace();
2861 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002862 Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863 }
2864 wtoken.setAnimation(a);
2865 }
2866 } else {
2867 wtoken.clearAnimation();
2868 }
2869
2870 return wtoken.animation != null;
2871 }
2872
2873 // -------------------------------------------------------------
2874 // Application Window Tokens
2875 // -------------------------------------------------------------
2876
2877 public void validateAppTokens(List tokens) {
2878 int v = tokens.size()-1;
2879 int m = mAppTokens.size()-1;
2880 while (v >= 0 && m >= 0) {
2881 AppWindowToken wtoken = mAppTokens.get(m);
2882 if (wtoken.removed) {
2883 m--;
2884 continue;
2885 }
2886 if (tokens.get(v) != wtoken.token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002887 Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002888 + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
2889 }
2890 v--;
2891 m--;
2892 }
2893 while (v >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002894 Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 v--;
2896 }
2897 while (m >= 0) {
2898 AppWindowToken wtoken = mAppTokens.get(m);
2899 if (!wtoken.removed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002900 Slog.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002901 }
2902 m--;
2903 }
2904 }
2905
2906 boolean checkCallingPermission(String permission, String func) {
2907 // Quick check: if the calling permission is me, it's all okay.
2908 if (Binder.getCallingPid() == Process.myPid()) {
2909 return true;
2910 }
Romain Guy06882f82009-06-10 13:36:04 -07002911
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002912 if (mContext.checkCallingPermission(permission)
2913 == PackageManager.PERMISSION_GRANTED) {
2914 return true;
2915 }
2916 String msg = "Permission Denial: " + func + " from pid="
2917 + Binder.getCallingPid()
2918 + ", uid=" + Binder.getCallingUid()
2919 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002920 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002921 return false;
2922 }
Romain Guy06882f82009-06-10 13:36:04 -07002923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002924 AppWindowToken findAppWindowToken(IBinder token) {
2925 WindowToken wtoken = mTokenMap.get(token);
2926 if (wtoken == null) {
2927 return null;
2928 }
2929 return wtoken.appWindowToken;
2930 }
Romain Guy06882f82009-06-10 13:36:04 -07002931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932 public void addWindowToken(IBinder token, int type) {
2933 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2934 "addWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002935 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002936 }
Romain Guy06882f82009-06-10 13:36:04 -07002937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002938 synchronized(mWindowMap) {
2939 WindowToken wtoken = mTokenMap.get(token);
2940 if (wtoken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002941 Slog.w(TAG, "Attempted to add existing input method token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 return;
2943 }
2944 wtoken = new WindowToken(token, type, true);
2945 mTokenMap.put(token, wtoken);
2946 mTokenList.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002947 if (type == TYPE_WALLPAPER) {
2948 mWallpaperTokens.add(wtoken);
2949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002950 }
2951 }
Romain Guy06882f82009-06-10 13:36:04 -07002952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002953 public void removeWindowToken(IBinder token) {
2954 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2955 "removeWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002956 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002957 }
2958
2959 final long origId = Binder.clearCallingIdentity();
2960 synchronized(mWindowMap) {
2961 WindowToken wtoken = mTokenMap.remove(token);
2962 mTokenList.remove(wtoken);
2963 if (wtoken != null) {
2964 boolean delayed = false;
2965 if (!wtoken.hidden) {
2966 wtoken.hidden = true;
Romain Guy06882f82009-06-10 13:36:04 -07002967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 final int N = wtoken.windows.size();
2969 boolean changed = false;
Romain Guy06882f82009-06-10 13:36:04 -07002970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002971 for (int i=0; i<N; i++) {
2972 WindowState win = wtoken.windows.get(i);
2973
2974 if (win.isAnimating()) {
2975 delayed = true;
2976 }
Romain Guy06882f82009-06-10 13:36:04 -07002977
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002978 if (win.isVisibleNow()) {
2979 applyAnimationLocked(win,
2980 WindowManagerPolicy.TRANSIT_EXIT, false);
2981 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
2982 KeyWaiter.RETURN_NOTHING);
2983 changed = true;
2984 }
2985 }
2986
2987 if (changed) {
2988 mLayoutNeeded = true;
2989 performLayoutAndPlaceSurfacesLocked();
2990 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2991 }
Romain Guy06882f82009-06-10 13:36:04 -07002992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 if (delayed) {
2994 mExitingTokens.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002995 } else if (wtoken.windowType == TYPE_WALLPAPER) {
2996 mWallpaperTokens.remove(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002997 }
2998 }
Romain Guy06882f82009-06-10 13:36:04 -07002999
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003000 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003001 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003002 }
3003 }
3004 Binder.restoreCallingIdentity(origId);
3005 }
3006
3007 public void addAppToken(int addPos, IApplicationToken token,
3008 int groupId, int requestedOrientation, boolean fullscreen) {
3009 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3010 "addAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003011 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003012 }
Romain Guy06882f82009-06-10 13:36:04 -07003013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003014 synchronized(mWindowMap) {
3015 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3016 if (wtoken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003017 Slog.w(TAG, "Attempted to add existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003018 return;
3019 }
3020 wtoken = new AppWindowToken(token);
3021 wtoken.groupId = groupId;
3022 wtoken.appFullscreen = fullscreen;
3023 wtoken.requestedOrientation = requestedOrientation;
3024 mAppTokens.add(addPos, wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003025 if (localLOGV) Slog.v(TAG, "Adding new app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003026 mTokenMap.put(token.asBinder(), wtoken);
3027 mTokenList.add(wtoken);
Romain Guy06882f82009-06-10 13:36:04 -07003028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003029 // Application tokens start out hidden.
3030 wtoken.hidden = true;
3031 wtoken.hiddenRequested = true;
Romain Guy06882f82009-06-10 13:36:04 -07003032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003033 //dump();
3034 }
3035 }
Romain Guy06882f82009-06-10 13:36:04 -07003036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003037 public void setAppGroupId(IBinder token, int groupId) {
3038 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3039 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003040 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003041 }
3042
3043 synchronized(mWindowMap) {
3044 AppWindowToken wtoken = findAppWindowToken(token);
3045 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003046 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003047 return;
3048 }
3049 wtoken.groupId = groupId;
3050 }
3051 }
Romain Guy06882f82009-06-10 13:36:04 -07003052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003053 public int getOrientationFromWindowsLocked() {
3054 int pos = mWindows.size() - 1;
3055 while (pos >= 0) {
3056 WindowState wtoken = (WindowState) mWindows.get(pos);
3057 pos--;
3058 if (wtoken.mAppToken != null) {
3059 // We hit an application window. so the orientation will be determined by the
3060 // app window. No point in continuing further.
3061 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3062 }
Christopher Tateb696aee2010-04-02 19:08:30 -07003063 if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003064 continue;
3065 }
3066 int req = wtoken.mAttrs.screenOrientation;
3067 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3068 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3069 continue;
3070 } else {
3071 return req;
3072 }
3073 }
3074 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3075 }
Romain Guy06882f82009-06-10 13:36:04 -07003076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003077 public int getOrientationFromAppTokensLocked() {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003078 int pos = mAppTokens.size() - 1;
3079 int curGroup = 0;
3080 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3081 boolean findingBehind = false;
3082 boolean haveGroup = false;
3083 boolean lastFullscreen = false;
3084 while (pos >= 0) {
3085 AppWindowToken wtoken = mAppTokens.get(pos);
3086 pos--;
3087 // if we're about to tear down this window and not seek for
3088 // the behind activity, don't use it for orientation
3089 if (!findingBehind
3090 && (!wtoken.hidden && wtoken.hiddenRequested)) {
3091 continue;
3092 }
3093
3094 if (!haveGroup) {
3095 // We ignore any hidden applications on the top.
3096 if (wtoken.hiddenRequested || wtoken.willBeHidden) {
The Android Open Source Project10592532009-03-18 17:39:46 -07003097 continue;
3098 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003099 haveGroup = true;
3100 curGroup = wtoken.groupId;
3101 lastOrientation = wtoken.requestedOrientation;
3102 } else if (curGroup != wtoken.groupId) {
3103 // If we have hit a new application group, and the bottom
3104 // of the previous group didn't explicitly say to use
3105 // the orientation behind it, and the last app was
3106 // full screen, then we'll stick with the
3107 // user's orientation.
3108 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3109 && lastFullscreen) {
3110 return lastOrientation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003111 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003112 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003113 int or = wtoken.requestedOrientation;
3114 // If this application is fullscreen, and didn't explicitly say
3115 // to use the orientation behind it, then just take whatever
3116 // orientation it has and ignores whatever is under it.
3117 lastFullscreen = wtoken.appFullscreen;
3118 if (lastFullscreen
3119 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3120 return or;
3121 }
3122 // If this application has requested an explicit orientation,
3123 // then use it.
3124 if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
3125 or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
3126 or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
3127 or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
3128 or == ActivityInfo.SCREEN_ORIENTATION_USER) {
3129 return or;
3130 }
3131 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3132 }
3133 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003134 }
Romain Guy06882f82009-06-10 13:36:04 -07003135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003136 public Configuration updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003137 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003138 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3139 "updateOrientationFromAppTokens()")) {
3140 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3141 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003142
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003143 Configuration config = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144 long ident = Binder.clearCallingIdentity();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003145
3146 synchronized(mWindowMap) {
3147 if (updateOrientationFromAppTokensLocked()) {
3148 if (freezeThisOneIfNeeded != null) {
3149 AppWindowToken wtoken = findAppWindowToken(
3150 freezeThisOneIfNeeded);
3151 if (wtoken != null) {
3152 startAppFreezingScreenLocked(wtoken,
3153 ActivityInfo.CONFIG_ORIENTATION);
3154 }
3155 }
3156 config = computeNewConfigurationLocked();
3157
3158 } else if (currentConfig != null) {
3159 // No obvious action we need to take, but if our current
3160 // state mismatches the activity maanager's, update it
3161 mTempConfiguration.setToDefaults();
3162 if (computeNewConfigurationLocked(mTempConfiguration)) {
3163 if (currentConfig.diff(mTempConfiguration) != 0) {
3164 mWaitingForConfig = true;
3165 mLayoutNeeded = true;
3166 startFreezingDisplayLocked();
3167 config = new Configuration(mTempConfiguration);
3168 }
3169 }
3170 }
3171 }
3172
Dianne Hackborncfaef692009-06-15 14:24:44 -07003173 Binder.restoreCallingIdentity(ident);
3174 return config;
3175 }
3176
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003177 /*
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003178 * Determine the new desired orientation of the display, returning
3179 * a non-null new Configuration if it has changed from the current
3180 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
3181 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3182 * SCREEN. This will typically be done for you if you call
3183 * sendNewConfiguration().
3184 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003185 * The orientation is computed from non-application windows first. If none of
3186 * the non-application windows specify orientation, the orientation is computed from
Romain Guy06882f82009-06-10 13:36:04 -07003187 * application tokens.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003188 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3189 * android.os.IBinder)
3190 */
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003191 boolean updateOrientationFromAppTokensLocked() {
Christopher Tateb696aee2010-04-02 19:08:30 -07003192 if (mDisplayFrozen) {
3193 // If the display is frozen, some activities may be in the middle
3194 // of restarting, and thus have removed their old window. If the
3195 // window has the flag to hide the lock screen, then the lock screen
3196 // can re-appear and inflict its own orientation on us. Keep the
3197 // orientation stable until this all settles down.
3198 return false;
3199 }
3200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003201 boolean changed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003202 long ident = Binder.clearCallingIdentity();
3203 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003204 int req = computeForcedAppOrientationLocked();
Romain Guy06882f82009-06-10 13:36:04 -07003205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 if (req != mForcedAppOrientation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207 mForcedAppOrientation = req;
3208 //send a message to Policy indicating orientation change to take
3209 //action like disabling/enabling sensors etc.,
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003210 mPolicy.setCurrentOrientationLw(req);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003211 if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
3212 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)) {
3213 changed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003214 }
3215 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003216
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003217 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 } finally {
3219 Binder.restoreCallingIdentity(ident);
3220 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003221 }
Romain Guy06882f82009-06-10 13:36:04 -07003222
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003223 int computeForcedAppOrientationLocked() {
3224 int req = getOrientationFromWindowsLocked();
3225 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3226 req = getOrientationFromAppTokensLocked();
3227 }
3228 return req;
3229 }
Romain Guy06882f82009-06-10 13:36:04 -07003230
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003231 public void setNewConfiguration(Configuration config) {
3232 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3233 "setNewConfiguration()")) {
3234 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3235 }
3236
3237 synchronized(mWindowMap) {
3238 mCurConfiguration = new Configuration(config);
3239 mWaitingForConfig = false;
3240 performLayoutAndPlaceSurfacesLocked();
3241 }
3242 }
3243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003244 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3245 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3246 "setAppOrientation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003247 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003248 }
Romain Guy06882f82009-06-10 13:36:04 -07003249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003250 synchronized(mWindowMap) {
3251 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3252 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003253 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003254 return;
3255 }
Romain Guy06882f82009-06-10 13:36:04 -07003256
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003257 wtoken.requestedOrientation = requestedOrientation;
3258 }
3259 }
Romain Guy06882f82009-06-10 13:36:04 -07003260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003261 public int getAppOrientation(IApplicationToken token) {
3262 synchronized(mWindowMap) {
3263 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3264 if (wtoken == null) {
3265 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3266 }
Romain Guy06882f82009-06-10 13:36:04 -07003267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003268 return wtoken.requestedOrientation;
3269 }
3270 }
Romain Guy06882f82009-06-10 13:36:04 -07003271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003272 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3273 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3274 "setFocusedApp()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003275 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003276 }
3277
3278 synchronized(mWindowMap) {
3279 boolean changed = false;
3280 if (token == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003281 if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003282 changed = mFocusedApp != null;
3283 mFocusedApp = null;
3284 mKeyWaiter.tickle();
3285 } else {
3286 AppWindowToken newFocus = findAppWindowToken(token);
3287 if (newFocus == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003288 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003289 return;
3290 }
3291 changed = mFocusedApp != newFocus;
3292 mFocusedApp = newFocus;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003293 if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003294 mKeyWaiter.tickle();
3295 }
3296
3297 if (moveFocusNow && changed) {
3298 final long origId = Binder.clearCallingIdentity();
3299 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3300 Binder.restoreCallingIdentity(origId);
3301 }
3302 }
3303 }
3304
3305 public void prepareAppTransition(int transit) {
3306 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3307 "prepareAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003308 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003309 }
Romain Guy06882f82009-06-10 13:36:04 -07003310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003311 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003312 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003313 TAG, "Prepare app transition: transit=" + transit
3314 + " mNextAppTransition=" + mNextAppTransition);
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003315 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003316 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
3317 || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003318 mNextAppTransition = transit;
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07003319 } else if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
3320 && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) {
3321 // Opening a new task always supersedes a close for the anim.
3322 mNextAppTransition = transit;
3323 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
3324 && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) {
3325 // Opening a new activity always supersedes a close for the anim.
3326 mNextAppTransition = transit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003327 }
3328 mAppTransitionReady = false;
3329 mAppTransitionTimeout = false;
3330 mStartingIconInTransition = false;
3331 mSkipAppTransitionAnimation = false;
3332 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3333 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT),
3334 5000);
3335 }
3336 }
3337 }
3338
3339 public int getPendingAppTransition() {
3340 return mNextAppTransition;
3341 }
Romain Guy06882f82009-06-10 13:36:04 -07003342
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003343 public void overridePendingAppTransition(String packageName,
3344 int enterAnim, int exitAnim) {
Dianne Hackborn8b571a82009-09-25 16:09:43 -07003345 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003346 mNextAppTransitionPackage = packageName;
3347 mNextAppTransitionEnter = enterAnim;
3348 mNextAppTransitionExit = exitAnim;
3349 }
3350 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003352 public void executeAppTransition() {
3353 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3354 "executeAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003355 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003356 }
Romain Guy06882f82009-06-10 13:36:04 -07003357
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003358 synchronized(mWindowMap) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003359 if (DEBUG_APP_TRANSITIONS) {
3360 RuntimeException e = new RuntimeException("here");
3361 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -08003362 Slog.w(TAG, "Execute app transition: mNextAppTransition="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003363 + mNextAppTransition, e);
3364 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003365 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003366 mAppTransitionReady = true;
3367 final long origId = Binder.clearCallingIdentity();
3368 performLayoutAndPlaceSurfacesLocked();
3369 Binder.restoreCallingIdentity(origId);
3370 }
3371 }
3372 }
3373
3374 public void setAppStartingWindow(IBinder token, String pkg,
3375 int theme, CharSequence nonLocalizedLabel, int labelRes, int icon,
3376 IBinder transferFrom, boolean createIfNeeded) {
3377 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3378 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003379 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003380 }
3381
3382 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003383 if (DEBUG_STARTING_WINDOW) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003384 TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
3385 + " transferFrom=" + transferFrom);
Romain Guy06882f82009-06-10 13:36:04 -07003386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003387 AppWindowToken wtoken = findAppWindowToken(token);
3388 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003389 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003390 return;
3391 }
3392
3393 // If the display is frozen, we won't do anything until the
3394 // actual window is displayed so there is no reason to put in
3395 // the starting window.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08003396 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003397 return;
3398 }
Romain Guy06882f82009-06-10 13:36:04 -07003399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003400 if (wtoken.startingData != null) {
3401 return;
3402 }
Romain Guy06882f82009-06-10 13:36:04 -07003403
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003404 if (transferFrom != null) {
3405 AppWindowToken ttoken = findAppWindowToken(transferFrom);
3406 if (ttoken != null) {
3407 WindowState startingWindow = ttoken.startingWindow;
3408 if (startingWindow != null) {
3409 if (mStartingIconInTransition) {
3410 // In this case, the starting icon has already
3411 // been displayed, so start letting windows get
3412 // shown immediately without any more transitions.
3413 mSkipAppTransitionAnimation = true;
3414 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003415 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003416 "Moving existing starting from " + ttoken
3417 + " to " + wtoken);
3418 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07003419
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003420 // Transfer the starting window over to the new
3421 // token.
3422 wtoken.startingData = ttoken.startingData;
3423 wtoken.startingView = ttoken.startingView;
3424 wtoken.startingWindow = startingWindow;
3425 ttoken.startingData = null;
3426 ttoken.startingView = null;
3427 ttoken.startingWindow = null;
3428 ttoken.startingMoved = true;
3429 startingWindow.mToken = wtoken;
Dianne Hackbornef49c572009-03-24 19:27:32 -07003430 startingWindow.mRootToken = wtoken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003431 startingWindow.mAppToken = wtoken;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003432 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003433 "Removing starting window: " + startingWindow);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 mWindows.remove(startingWindow);
3435 ttoken.windows.remove(startingWindow);
3436 ttoken.allAppWindows.remove(startingWindow);
3437 addWindowToListInOrderLocked(startingWindow, true);
Romain Guy06882f82009-06-10 13:36:04 -07003438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003439 // Propagate other interesting state between the
3440 // tokens. If the old token is displayed, we should
3441 // immediately force the new one to be displayed. If
3442 // it is animating, we need to move that animation to
3443 // the new one.
3444 if (ttoken.allDrawn) {
3445 wtoken.allDrawn = true;
3446 }
3447 if (ttoken.firstWindowDrawn) {
3448 wtoken.firstWindowDrawn = true;
3449 }
3450 if (!ttoken.hidden) {
3451 wtoken.hidden = false;
3452 wtoken.hiddenRequested = false;
3453 wtoken.willBeHidden = false;
3454 }
3455 if (wtoken.clientHidden != ttoken.clientHidden) {
3456 wtoken.clientHidden = ttoken.clientHidden;
3457 wtoken.sendAppVisibilityToClients();
3458 }
3459 if (ttoken.animation != null) {
3460 wtoken.animation = ttoken.animation;
3461 wtoken.animating = ttoken.animating;
3462 wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
3463 ttoken.animation = null;
3464 ttoken.animLayerAdjustment = 0;
3465 wtoken.updateLayers();
3466 ttoken.updateLayers();
3467 }
Romain Guy06882f82009-06-10 13:36:04 -07003468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003469 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 mLayoutNeeded = true;
3471 performLayoutAndPlaceSurfacesLocked();
3472 Binder.restoreCallingIdentity(origId);
3473 return;
3474 } else if (ttoken.startingData != null) {
3475 // The previous app was getting ready to show a
3476 // starting window, but hasn't yet done so. Steal it!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003477 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003478 "Moving pending starting from " + ttoken
3479 + " to " + wtoken);
3480 wtoken.startingData = ttoken.startingData;
3481 ttoken.startingData = null;
3482 ttoken.startingMoved = true;
3483 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3484 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3485 // want to process the message ASAP, before any other queued
3486 // messages.
3487 mH.sendMessageAtFrontOfQueue(m);
3488 return;
3489 }
3490 }
3491 }
3492
3493 // There is no existing starting window, and the caller doesn't
3494 // want us to create one, so that's it!
3495 if (!createIfNeeded) {
3496 return;
3497 }
Romain Guy06882f82009-06-10 13:36:04 -07003498
Dianne Hackborn284ac932009-08-28 10:34:25 -07003499 // If this is a translucent or wallpaper window, then don't
3500 // show a starting window -- the current effect (a full-screen
3501 // opaque starting window that fades away to the real contents
3502 // when it is ready) does not work for this.
3503 if (theme != 0) {
3504 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
3505 com.android.internal.R.styleable.Window);
3506 if (ent.array.getBoolean(
3507 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
3508 return;
3509 }
3510 if (ent.array.getBoolean(
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07003511 com.android.internal.R.styleable.Window_windowIsFloating, false)) {
3512 return;
3513 }
3514 if (ent.array.getBoolean(
Dianne Hackborn284ac932009-08-28 10:34:25 -07003515 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
3516 return;
3517 }
3518 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003519
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003520 mStartingIconInTransition = true;
3521 wtoken.startingData = new StartingData(
3522 pkg, theme, nonLocalizedLabel,
3523 labelRes, icon);
3524 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3525 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3526 // want to process the message ASAP, before any other queued
3527 // messages.
3528 mH.sendMessageAtFrontOfQueue(m);
3529 }
3530 }
3531
3532 public void setAppWillBeHidden(IBinder token) {
3533 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3534 "setAppWillBeHidden()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003535 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003536 }
3537
3538 AppWindowToken wtoken;
3539
3540 synchronized(mWindowMap) {
3541 wtoken = findAppWindowToken(token);
3542 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003543 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 -08003544 return;
3545 }
3546 wtoken.willBeHidden = true;
3547 }
3548 }
Romain Guy06882f82009-06-10 13:36:04 -07003549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003550 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
3551 boolean visible, int transit, boolean performLayout) {
3552 boolean delayed = false;
3553
3554 if (wtoken.clientHidden == visible) {
3555 wtoken.clientHidden = !visible;
3556 wtoken.sendAppVisibilityToClients();
3557 }
Romain Guy06882f82009-06-10 13:36:04 -07003558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003559 wtoken.willBeHidden = false;
3560 if (wtoken.hidden == visible) {
3561 final int N = wtoken.allAppWindows.size();
3562 boolean changed = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003563 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003564 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
3565 + " performLayout=" + performLayout);
Romain Guy06882f82009-06-10 13:36:04 -07003566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003567 boolean runningAppAnimation = false;
Romain Guy06882f82009-06-10 13:36:04 -07003568
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003569 if (transit != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003570 if (wtoken.animation == sDummyAnimation) {
3571 wtoken.animation = null;
3572 }
3573 applyAnimationLocked(wtoken, lp, transit, visible);
3574 changed = true;
3575 if (wtoken.animation != null) {
3576 delayed = runningAppAnimation = true;
3577 }
3578 }
Romain Guy06882f82009-06-10 13:36:04 -07003579
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003580 for (int i=0; i<N; i++) {
3581 WindowState win = wtoken.allAppWindows.get(i);
3582 if (win == wtoken.startingWindow) {
3583 continue;
3584 }
3585
3586 if (win.isAnimating()) {
3587 delayed = true;
3588 }
Romain Guy06882f82009-06-10 13:36:04 -07003589
Joe Onorato8a9b2202010-02-26 18:56:32 -08003590 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003591 //win.dump(" ");
3592 if (visible) {
3593 if (!win.isVisibleNow()) {
3594 if (!runningAppAnimation) {
3595 applyAnimationLocked(win,
3596 WindowManagerPolicy.TRANSIT_ENTER, true);
3597 }
3598 changed = true;
3599 }
3600 } else if (win.isVisibleNow()) {
3601 if (!runningAppAnimation) {
3602 applyAnimationLocked(win,
3603 WindowManagerPolicy.TRANSIT_EXIT, false);
3604 }
3605 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
3606 KeyWaiter.RETURN_NOTHING);
3607 changed = true;
3608 }
3609 }
3610
3611 wtoken.hidden = wtoken.hiddenRequested = !visible;
3612 if (!visible) {
3613 unsetAppFreezingScreenLocked(wtoken, true, true);
3614 } else {
3615 // If we are being set visible, and the starting window is
3616 // not yet displayed, then make sure it doesn't get displayed.
3617 WindowState swin = wtoken.startingWindow;
3618 if (swin != null && (swin.mDrawPending
3619 || swin.mCommitDrawPending)) {
3620 swin.mPolicyVisibility = false;
3621 swin.mPolicyVisibilityAfterAnim = false;
3622 }
3623 }
Romain Guy06882f82009-06-10 13:36:04 -07003624
Joe Onorato8a9b2202010-02-26 18:56:32 -08003625 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003626 + ": hidden=" + wtoken.hidden + " hiddenRequested="
3627 + wtoken.hiddenRequested);
Romain Guy06882f82009-06-10 13:36:04 -07003628
Dianne Hackborn9b52a212009-12-11 14:51:35 -08003629 if (changed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003630 mLayoutNeeded = true;
Dianne Hackborn9b52a212009-12-11 14:51:35 -08003631 if (performLayout) {
3632 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
3633 performLayoutAndPlaceSurfacesLocked();
3634 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003635 }
3636 }
3637
3638 if (wtoken.animation != null) {
3639 delayed = true;
3640 }
Romain Guy06882f82009-06-10 13:36:04 -07003641
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003642 return delayed;
3643 }
3644
3645 public void setAppVisibility(IBinder token, boolean visible) {
3646 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3647 "setAppVisibility()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003648 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003649 }
3650
3651 AppWindowToken wtoken;
3652
3653 synchronized(mWindowMap) {
3654 wtoken = findAppWindowToken(token);
3655 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003656 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003657 return;
3658 }
3659
3660 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08003661 RuntimeException e = null;
3662 if (!HIDE_STACK_CRAWLS) {
3663 e = new RuntimeException();
3664 e.fillInStackTrace();
3665 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003666 Slog.v(TAG, "setAppVisibility(" + token + ", " + visible
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003667 + "): mNextAppTransition=" + mNextAppTransition
3668 + " hidden=" + wtoken.hidden
3669 + " hiddenRequested=" + wtoken.hiddenRequested, e);
3670 }
Romain Guy06882f82009-06-10 13:36:04 -07003671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003672 // If we are preparing an app transition, then delay changing
3673 // the visibility of this token until we execute that transition.
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003674 if (!mDisplayFrozen && mPolicy.isScreenOn()
3675 && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003676 // Already in requested state, don't do anything more.
3677 if (wtoken.hiddenRequested != visible) {
3678 return;
3679 }
3680 wtoken.hiddenRequested = !visible;
Romain Guy06882f82009-06-10 13:36:04 -07003681
Joe Onorato8a9b2202010-02-26 18:56:32 -08003682 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003683 TAG, "Setting dummy animation on: " + wtoken);
3684 wtoken.setDummyAnimation();
3685 mOpeningApps.remove(wtoken);
3686 mClosingApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003687 wtoken.waitingToShow = wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003688 wtoken.inPendingTransaction = true;
3689 if (visible) {
3690 mOpeningApps.add(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003691 wtoken.startingDisplayed = false;
3692 wtoken.startingMoved = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003693
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003694 // If the token is currently hidden (should be the
3695 // common case), then we need to set up to wait for
3696 // its windows to be ready.
3697 if (wtoken.hidden) {
3698 wtoken.allDrawn = false;
3699 wtoken.waitingToShow = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003700
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003701 if (wtoken.clientHidden) {
3702 // In the case where we are making an app visible
3703 // but holding off for a transition, we still need
3704 // to tell the client to make its windows visible so
3705 // they get drawn. Otherwise, we will wait on
3706 // performing the transition until all windows have
3707 // been drawn, they never will be, and we are sad.
3708 wtoken.clientHidden = false;
3709 wtoken.sendAppVisibilityToClients();
3710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003711 }
3712 } else {
3713 mClosingApps.add(wtoken);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003714
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003715 // If the token is currently visible (should be the
3716 // common case), then set up to wait for it to be hidden.
3717 if (!wtoken.hidden) {
3718 wtoken.waitingToHide = true;
3719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003720 }
3721 return;
3722 }
Romain Guy06882f82009-06-10 13:36:04 -07003723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003724 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003725 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003726 wtoken.updateReportedVisibilityLocked();
3727 Binder.restoreCallingIdentity(origId);
3728 }
3729 }
3730
3731 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
3732 boolean unfreezeSurfaceNow, boolean force) {
3733 if (wtoken.freezingScreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003734 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003735 + " force=" + force);
3736 final int N = wtoken.allAppWindows.size();
3737 boolean unfrozeWindows = false;
3738 for (int i=0; i<N; i++) {
3739 WindowState w = wtoken.allAppWindows.get(i);
3740 if (w.mAppFreezing) {
3741 w.mAppFreezing = false;
3742 if (w.mSurface != null && !w.mOrientationChanging) {
3743 w.mOrientationChanging = true;
3744 }
3745 unfrozeWindows = true;
3746 }
3747 }
3748 if (force || unfrozeWindows) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003749 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003750 wtoken.freezingScreen = false;
3751 mAppsFreezingScreen--;
3752 }
3753 if (unfreezeSurfaceNow) {
3754 if (unfrozeWindows) {
3755 mLayoutNeeded = true;
3756 performLayoutAndPlaceSurfacesLocked();
3757 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003758 stopFreezingDisplayLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003759 }
3760 }
3761 }
Romain Guy06882f82009-06-10 13:36:04 -07003762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003763 public void startAppFreezingScreenLocked(AppWindowToken wtoken,
3764 int configChanges) {
3765 if (DEBUG_ORIENTATION) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08003766 RuntimeException e = null;
3767 if (!HIDE_STACK_CRAWLS) {
3768 e = new RuntimeException();
3769 e.fillInStackTrace();
3770 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003771 Slog.i(TAG, "Set freezing of " + wtoken.appToken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003772 + ": hidden=" + wtoken.hidden + " freezing="
3773 + wtoken.freezingScreen, e);
3774 }
3775 if (!wtoken.hiddenRequested) {
3776 if (!wtoken.freezingScreen) {
3777 wtoken.freezingScreen = true;
3778 mAppsFreezingScreen++;
3779 if (mAppsFreezingScreen == 1) {
3780 startFreezingDisplayLocked();
3781 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
3782 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
3783 5000);
3784 }
3785 }
3786 final int N = wtoken.allAppWindows.size();
3787 for (int i=0; i<N; i++) {
3788 WindowState w = wtoken.allAppWindows.get(i);
3789 w.mAppFreezing = true;
3790 }
3791 }
3792 }
Romain Guy06882f82009-06-10 13:36:04 -07003793
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003794 public void startAppFreezingScreen(IBinder token, int configChanges) {
3795 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3796 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003797 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003798 }
3799
3800 synchronized(mWindowMap) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003801 if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOn()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003802 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003803 return;
3804 }
Romain Guy06882f82009-06-10 13:36:04 -07003805
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003806 AppWindowToken wtoken = findAppWindowToken(token);
3807 if (wtoken == null || wtoken.appToken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003808 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003809 return;
3810 }
3811 final long origId = Binder.clearCallingIdentity();
3812 startAppFreezingScreenLocked(wtoken, configChanges);
3813 Binder.restoreCallingIdentity(origId);
3814 }
3815 }
Romain Guy06882f82009-06-10 13:36:04 -07003816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003817 public void stopAppFreezingScreen(IBinder token, boolean force) {
3818 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3819 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003820 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003821 }
3822
3823 synchronized(mWindowMap) {
3824 AppWindowToken wtoken = findAppWindowToken(token);
3825 if (wtoken == null || wtoken.appToken == null) {
3826 return;
3827 }
3828 final long origId = Binder.clearCallingIdentity();
Joe Onorato8a9b2202010-02-26 18:56:32 -08003829 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003830 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
3831 unsetAppFreezingScreenLocked(wtoken, true, force);
3832 Binder.restoreCallingIdentity(origId);
3833 }
3834 }
Romain Guy06882f82009-06-10 13:36:04 -07003835
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003836 public void removeAppToken(IBinder token) {
3837 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3838 "removeAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003839 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003840 }
3841
3842 AppWindowToken wtoken = null;
3843 AppWindowToken startingToken = null;
3844 boolean delayed = false;
3845
3846 final long origId = Binder.clearCallingIdentity();
3847 synchronized(mWindowMap) {
3848 WindowToken basewtoken = mTokenMap.remove(token);
3849 mTokenList.remove(basewtoken);
3850 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003851 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003852 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003853 wtoken.inPendingTransaction = false;
3854 mOpeningApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003855 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003856 if (mClosingApps.contains(wtoken)) {
3857 delayed = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003858 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003859 mClosingApps.add(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003860 wtoken.waitingToHide = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003861 delayed = true;
3862 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003863 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 TAG, "Removing app " + wtoken + " delayed=" + delayed
3865 + " animation=" + wtoken.animation
3866 + " animating=" + wtoken.animating);
3867 if (delayed) {
3868 // set the token aside because it has an active animation to be finished
3869 mExitingAppTokens.add(wtoken);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003870 } else {
3871 // Make sure there is no animation running on this token,
3872 // so any windows associated with it will be removed as
3873 // soon as their animations are complete
3874 wtoken.animation = null;
3875 wtoken.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003876 }
3877 mAppTokens.remove(wtoken);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003878 if (mLastEnterAnimToken == wtoken) {
3879 mLastEnterAnimToken = null;
3880 mLastEnterAnimParams = null;
3881 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003882 wtoken.removed = true;
3883 if (wtoken.startingData != null) {
3884 startingToken = wtoken;
3885 }
3886 unsetAppFreezingScreenLocked(wtoken, true, true);
3887 if (mFocusedApp == wtoken) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003888 if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003889 mFocusedApp = null;
3890 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3891 mKeyWaiter.tickle();
3892 }
3893 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003894 Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003895 }
Romain Guy06882f82009-06-10 13:36:04 -07003896
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003897 if (!delayed && wtoken != null) {
3898 wtoken.updateReportedVisibilityLocked();
3899 }
3900 }
3901 Binder.restoreCallingIdentity(origId);
3902
3903 if (startingToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003904 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003905 + startingToken + ": app token removed");
3906 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
3907 mH.sendMessage(m);
3908 }
3909 }
3910
3911 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
3912 final int NW = token.windows.size();
3913 for (int i=0; i<NW; i++) {
3914 WindowState win = token.windows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003915 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 mWindows.remove(win);
3917 int j = win.mChildWindows.size();
3918 while (j > 0) {
3919 j--;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003920 WindowState cwin = (WindowState)win.mChildWindows.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003921 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003922 "Tmp removing child window " + cwin);
3923 mWindows.remove(cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003924 }
3925 }
3926 return NW > 0;
3927 }
3928
3929 void dumpAppTokensLocked() {
3930 for (int i=mAppTokens.size()-1; i>=0; i--) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003931 Slog.v(TAG, " #" + i + ": " + mAppTokens.get(i).token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003932 }
3933 }
Romain Guy06882f82009-06-10 13:36:04 -07003934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003935 void dumpWindowsLocked() {
3936 for (int i=mWindows.size()-1; i>=0; i--) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003937 Slog.v(TAG, " #" + i + ": " + mWindows.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003938 }
3939 }
Romain Guy06882f82009-06-10 13:36:04 -07003940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003941 private int findWindowOffsetLocked(int tokenPos) {
3942 final int NW = mWindows.size();
3943
3944 if (tokenPos >= mAppTokens.size()) {
3945 int i = NW;
3946 while (i > 0) {
3947 i--;
3948 WindowState win = (WindowState)mWindows.get(i);
3949 if (win.getAppToken() != null) {
3950 return i+1;
3951 }
3952 }
3953 }
3954
3955 while (tokenPos > 0) {
3956 // Find the first app token below the new position that has
3957 // a window displayed.
3958 final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003959 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003960 + tokenPos + " -- " + wtoken.token);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003961 if (wtoken.sendingToBottom) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003962 if (DEBUG_REORDER) Slog.v(TAG,
Dianne Hackborna8f60182009-09-01 19:01:50 -07003963 "Skipping token -- currently sending to bottom");
3964 tokenPos--;
3965 continue;
3966 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003967 int i = wtoken.windows.size();
3968 while (i > 0) {
3969 i--;
3970 WindowState win = wtoken.windows.get(i);
3971 int j = win.mChildWindows.size();
3972 while (j > 0) {
3973 j--;
3974 WindowState cwin = (WindowState)win.mChildWindows.get(j);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003975 if (cwin.mSubLayer >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003976 for (int pos=NW-1; pos>=0; pos--) {
3977 if (mWindows.get(pos) == cwin) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003978 if (DEBUG_REORDER) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003979 "Found child win @" + (pos+1));
3980 return pos+1;
3981 }
3982 }
3983 }
3984 }
3985 for (int pos=NW-1; pos>=0; pos--) {
3986 if (mWindows.get(pos) == win) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003987 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 return pos+1;
3989 }
3990 }
3991 }
3992 tokenPos--;
3993 }
3994
3995 return 0;
3996 }
3997
3998 private final int reAddWindowLocked(int index, WindowState win) {
3999 final int NCW = win.mChildWindows.size();
4000 boolean added = false;
4001 for (int j=0; j<NCW; j++) {
4002 WindowState cwin = (WindowState)win.mChildWindows.get(j);
4003 if (!added && cwin.mSubLayer >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004004 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004005 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004006 mWindows.add(index, win);
4007 index++;
4008 added = true;
4009 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004010 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004011 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004012 mWindows.add(index, cwin);
4013 index++;
4014 }
4015 if (!added) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004016 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004017 + index + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004018 mWindows.add(index, win);
4019 index++;
4020 }
4021 return index;
4022 }
Romain Guy06882f82009-06-10 13:36:04 -07004023
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004024 private final int reAddAppWindowsLocked(int index, WindowToken token) {
4025 final int NW = token.windows.size();
4026 for (int i=0; i<NW; i++) {
4027 index = reAddWindowLocked(index, token.windows.get(i));
4028 }
4029 return index;
4030 }
4031
4032 public void moveAppToken(int index, IBinder token) {
4033 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4034 "moveAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004035 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004036 }
4037
4038 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004039 if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004040 if (DEBUG_REORDER) dumpAppTokensLocked();
4041 final AppWindowToken wtoken = findAppWindowToken(token);
4042 if (wtoken == null || !mAppTokens.remove(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004043 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004044 + token + " (" + wtoken + ")");
4045 return;
4046 }
4047 mAppTokens.add(index, wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004048 if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 if (DEBUG_REORDER) dumpAppTokensLocked();
Romain Guy06882f82009-06-10 13:36:04 -07004050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004051 final long origId = Binder.clearCallingIdentity();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004052 if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004053 if (DEBUG_REORDER) dumpWindowsLocked();
4054 if (tmpRemoveAppWindowsLocked(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004055 if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004056 if (DEBUG_REORDER) dumpWindowsLocked();
4057 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004058 if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004059 if (DEBUG_REORDER) dumpWindowsLocked();
4060 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004061 mLayoutNeeded = true;
4062 performLayoutAndPlaceSurfacesLocked();
4063 }
4064 Binder.restoreCallingIdentity(origId);
4065 }
4066 }
4067
4068 private void removeAppTokensLocked(List<IBinder> tokens) {
4069 // XXX This should be done more efficiently!
4070 // (take advantage of the fact that both lists should be
4071 // ordered in the same way.)
4072 int N = tokens.size();
4073 for (int i=0; i<N; i++) {
4074 IBinder token = tokens.get(i);
4075 final AppWindowToken wtoken = findAppWindowToken(token);
4076 if (!mAppTokens.remove(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004077 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004078 + token + " (" + wtoken + ")");
4079 i--;
4080 N--;
4081 }
4082 }
4083 }
4084
Dianne Hackborna8f60182009-09-01 19:01:50 -07004085 private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos,
4086 boolean updateFocusAndLayout) {
4087 // First remove all of the windows from the list.
4088 tmpRemoveAppWindowsLocked(wtoken);
4089
4090 // Where to start adding?
4091 int pos = findWindowOffsetLocked(tokenPos);
4092
4093 // And now add them back at the correct place.
4094 pos = reAddAppWindowsLocked(pos, wtoken);
4095
4096 if (updateFocusAndLayout) {
4097 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4098 assignLayersLocked();
4099 }
4100 mLayoutNeeded = true;
4101 performLayoutAndPlaceSurfacesLocked();
4102 }
4103 }
4104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004105 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
4106 // First remove all of the windows from the list.
4107 final int N = tokens.size();
4108 int i;
4109 for (i=0; i<N; i++) {
4110 WindowToken token = mTokenMap.get(tokens.get(i));
4111 if (token != null) {
4112 tmpRemoveAppWindowsLocked(token);
4113 }
4114 }
4115
4116 // Where to start adding?
4117 int pos = findWindowOffsetLocked(tokenPos);
4118
4119 // And now add them back at the correct place.
4120 for (i=0; i<N; i++) {
4121 WindowToken token = mTokenMap.get(tokens.get(i));
4122 if (token != null) {
4123 pos = reAddAppWindowsLocked(pos, token);
4124 }
4125 }
4126
Dianne Hackborna8f60182009-09-01 19:01:50 -07004127 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4128 assignLayersLocked();
4129 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 mLayoutNeeded = true;
4131 performLayoutAndPlaceSurfacesLocked();
4132
4133 //dump();
4134 }
4135
4136 public void moveAppTokensToTop(List<IBinder> tokens) {
4137 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4138 "moveAppTokensToTop()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004139 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004140 }
4141
4142 final long origId = Binder.clearCallingIdentity();
4143 synchronized(mWindowMap) {
4144 removeAppTokensLocked(tokens);
4145 final int N = tokens.size();
4146 for (int i=0; i<N; i++) {
4147 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4148 if (wt != null) {
4149 mAppTokens.add(wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004150 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004151 mToTopApps.remove(wt);
4152 mToBottomApps.remove(wt);
4153 mToTopApps.add(wt);
4154 wt.sendingToBottom = false;
4155 wt.sendingToTop = true;
4156 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004157 }
4158 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004159
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004160 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004161 moveAppWindowsLocked(tokens, mAppTokens.size());
4162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004163 }
4164 Binder.restoreCallingIdentity(origId);
4165 }
4166
4167 public void moveAppTokensToBottom(List<IBinder> tokens) {
4168 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4169 "moveAppTokensToBottom()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004170 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004171 }
4172
4173 final long origId = Binder.clearCallingIdentity();
4174 synchronized(mWindowMap) {
4175 removeAppTokensLocked(tokens);
4176 final int N = tokens.size();
4177 int pos = 0;
4178 for (int i=0; i<N; i++) {
4179 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4180 if (wt != null) {
4181 mAppTokens.add(pos, wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004182 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004183 mToTopApps.remove(wt);
4184 mToBottomApps.remove(wt);
4185 mToBottomApps.add(i, wt);
4186 wt.sendingToTop = false;
4187 wt.sendingToBottom = true;
4188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004189 pos++;
4190 }
4191 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004192
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004193 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004194 moveAppWindowsLocked(tokens, 0);
4195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004196 }
4197 Binder.restoreCallingIdentity(origId);
4198 }
4199
4200 // -------------------------------------------------------------
4201 // Misc IWindowSession methods
4202 // -------------------------------------------------------------
Romain Guy06882f82009-06-10 13:36:04 -07004203
Jim Miller284b62e2010-06-08 14:27:42 -07004204 private boolean shouldAllowDisableKeyguard()
Jim Millerd6b57052010-06-07 17:52:42 -07004205 {
Jim Miller284b62e2010-06-08 14:27:42 -07004206 // We fail safe and prevent disabling keyguard in the unlikely event this gets
4207 // called before DevicePolicyManagerService has started.
4208 if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
4209 DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
4210 Context.DEVICE_POLICY_SERVICE);
4211 if (dpm != null) {
4212 mAllowDisableKeyguard = dpm.getPasswordQuality(null)
4213 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
4214 ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
4215 }
Jim Millerd6b57052010-06-07 17:52:42 -07004216 }
Jim Miller284b62e2010-06-08 14:27:42 -07004217 return mAllowDisableKeyguard == ALLOW_DISABLE_YES;
Jim Millerd6b57052010-06-07 17:52:42 -07004218 }
4219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004220 public void disableKeyguard(IBinder token, String tag) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004221 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004222 != PackageManager.PERMISSION_GRANTED) {
4223 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4224 }
Jim Millerd6b57052010-06-07 17:52:42 -07004225
Jim Miller284b62e2010-06-08 14:27:42 -07004226 synchronized (mKeyguardTokenWatcher) {
4227 mKeyguardTokenWatcher.acquire(token, tag);
Mike Lockwooddd884682009-10-11 16:57:08 -04004228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004229 }
4230
4231 public void reenableKeyguard(IBinder token) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004232 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004233 != PackageManager.PERMISSION_GRANTED) {
4234 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004236
Jim Miller284b62e2010-06-08 14:27:42 -07004237 synchronized (mKeyguardTokenWatcher) {
4238 mKeyguardTokenWatcher.release(token);
Jim Millerd6b57052010-06-07 17:52:42 -07004239
Jim Miller284b62e2010-06-08 14:27:42 -07004240 if (!mKeyguardTokenWatcher.isAcquired()) {
4241 // If we are the last one to reenable the keyguard wait until
4242 // we have actually finished reenabling until returning.
4243 // It is possible that reenableKeyguard() can be called before
4244 // the previous disableKeyguard() is handled, in which case
4245 // neither mKeyguardTokenWatcher.acquired() or released() would
4246 // be called. In that case mKeyguardDisabled will be false here
4247 // and we have nothing to wait for.
4248 while (mKeyguardDisabled) {
4249 try {
4250 mKeyguardTokenWatcher.wait();
4251 } catch (InterruptedException e) {
4252 Thread.currentThread().interrupt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004253 }
4254 }
4255 }
4256 }
4257 }
4258
4259 /**
4260 * @see android.app.KeyguardManager#exitKeyguardSecurely
4261 */
4262 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004263 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004264 != PackageManager.PERMISSION_GRANTED) {
4265 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4266 }
4267 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
4268 public void onKeyguardExitResult(boolean success) {
4269 try {
4270 callback.onKeyguardExitResult(success);
4271 } catch (RemoteException e) {
4272 // Client has died, we don't care.
4273 }
4274 }
4275 });
4276 }
4277
4278 public boolean inKeyguardRestrictedInputMode() {
4279 return mPolicy.inKeyguardRestrictedKeyInputMode();
4280 }
Romain Guy06882f82009-06-10 13:36:04 -07004281
Dianne Hackbornffa42482009-09-23 22:20:11 -07004282 public void closeSystemDialogs(String reason) {
4283 synchronized(mWindowMap) {
4284 for (int i=mWindows.size()-1; i>=0; i--) {
4285 WindowState w = (WindowState)mWindows.get(i);
4286 if (w.mSurface != null) {
4287 try {
4288 w.mClient.closeSystemDialogs(reason);
4289 } catch (RemoteException e) {
4290 }
4291 }
4292 }
4293 }
4294 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004296 static float fixScale(float scale) {
4297 if (scale < 0) scale = 0;
4298 else if (scale > 20) scale = 20;
4299 return Math.abs(scale);
4300 }
Romain Guy06882f82009-06-10 13:36:04 -07004301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004302 public void setAnimationScale(int which, float scale) {
4303 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4304 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004305 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004306 }
4307
4308 if (scale < 0) scale = 0;
4309 else if (scale > 20) scale = 20;
4310 scale = Math.abs(scale);
4311 switch (which) {
4312 case 0: mWindowAnimationScale = fixScale(scale); break;
4313 case 1: mTransitionAnimationScale = fixScale(scale); break;
4314 }
Romain Guy06882f82009-06-10 13:36:04 -07004315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004316 // Persist setting
4317 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4318 }
Romain Guy06882f82009-06-10 13:36:04 -07004319
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004320 public void setAnimationScales(float[] scales) {
4321 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4322 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004323 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004324 }
4325
4326 if (scales != null) {
4327 if (scales.length >= 1) {
4328 mWindowAnimationScale = fixScale(scales[0]);
4329 }
4330 if (scales.length >= 2) {
4331 mTransitionAnimationScale = fixScale(scales[1]);
4332 }
4333 }
Romain Guy06882f82009-06-10 13:36:04 -07004334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004335 // Persist setting
4336 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4337 }
Romain Guy06882f82009-06-10 13:36:04 -07004338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 public float getAnimationScale(int which) {
4340 switch (which) {
4341 case 0: return mWindowAnimationScale;
4342 case 1: return mTransitionAnimationScale;
4343 }
4344 return 0;
4345 }
Romain Guy06882f82009-06-10 13:36:04 -07004346
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004347 public float[] getAnimationScales() {
4348 return new float[] { mWindowAnimationScale, mTransitionAnimationScale };
4349 }
Romain Guy06882f82009-06-10 13:36:04 -07004350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004351 public int getSwitchState(int sw) {
4352 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4353 "getSwitchState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004354 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 }
4356 return KeyInputQueue.getSwitchState(sw);
4357 }
Romain Guy06882f82009-06-10 13:36:04 -07004358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004359 public int getSwitchStateForDevice(int devid, int sw) {
4360 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4361 "getSwitchStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004362 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004363 }
4364 return KeyInputQueue.getSwitchState(devid, sw);
4365 }
Romain Guy06882f82009-06-10 13:36:04 -07004366
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004367 public int getScancodeState(int sw) {
4368 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4369 "getScancodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004370 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004371 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004372 return mQueue.getScancodeState(sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004373 }
Romain Guy06882f82009-06-10 13:36:04 -07004374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004375 public int getScancodeStateForDevice(int devid, int sw) {
4376 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4377 "getScancodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004378 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004379 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004380 return mQueue.getScancodeState(devid, sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004381 }
Romain Guy06882f82009-06-10 13:36:04 -07004382
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004383 public int getTrackballScancodeState(int sw) {
4384 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4385 "getTrackballScancodeState()")) {
4386 throw new SecurityException("Requires READ_INPUT_STATE permission");
4387 }
4388 return mQueue.getTrackballScancodeState(sw);
4389 }
4390
4391 public int getDPadScancodeState(int sw) {
4392 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4393 "getDPadScancodeState()")) {
4394 throw new SecurityException("Requires READ_INPUT_STATE permission");
4395 }
4396 return mQueue.getDPadScancodeState(sw);
4397 }
4398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004399 public int getKeycodeState(int sw) {
4400 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4401 "getKeycodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004402 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004404 return mQueue.getKeycodeState(sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004405 }
Romain Guy06882f82009-06-10 13:36:04 -07004406
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004407 public int getKeycodeStateForDevice(int devid, int sw) {
4408 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4409 "getKeycodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004410 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004411 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004412 return mQueue.getKeycodeState(devid, sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 }
Romain Guy06882f82009-06-10 13:36:04 -07004414
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004415 public int getTrackballKeycodeState(int sw) {
4416 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4417 "getTrackballKeycodeState()")) {
4418 throw new SecurityException("Requires READ_INPUT_STATE permission");
4419 }
4420 return mQueue.getTrackballKeycodeState(sw);
4421 }
4422
4423 public int getDPadKeycodeState(int sw) {
4424 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4425 "getDPadKeycodeState()")) {
4426 throw new SecurityException("Requires READ_INPUT_STATE permission");
4427 }
4428 return mQueue.getDPadKeycodeState(sw);
4429 }
4430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
4432 return KeyInputQueue.hasKeys(keycodes, keyExists);
4433 }
Romain Guy06882f82009-06-10 13:36:04 -07004434
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004435 public void enableScreenAfterBoot() {
4436 synchronized(mWindowMap) {
4437 if (mSystemBooted) {
4438 return;
4439 }
4440 mSystemBooted = true;
4441 }
Romain Guy06882f82009-06-10 13:36:04 -07004442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004443 performEnableScreen();
4444 }
Romain Guy06882f82009-06-10 13:36:04 -07004445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004446 public void enableScreenIfNeededLocked() {
4447 if (mDisplayEnabled) {
4448 return;
4449 }
4450 if (!mSystemBooted) {
4451 return;
4452 }
4453 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
4454 }
Romain Guy06882f82009-06-10 13:36:04 -07004455
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004456 public void performEnableScreen() {
4457 synchronized(mWindowMap) {
4458 if (mDisplayEnabled) {
4459 return;
4460 }
4461 if (!mSystemBooted) {
4462 return;
4463 }
Romain Guy06882f82009-06-10 13:36:04 -07004464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004465 // Don't enable the screen until all existing windows
4466 // have been drawn.
4467 final int N = mWindows.size();
4468 for (int i=0; i<N; i++) {
4469 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -08004470 if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004471 return;
4472 }
4473 }
Romain Guy06882f82009-06-10 13:36:04 -07004474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004475 mDisplayEnabled = true;
4476 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004477 Slog.i(TAG, "ENABLING SCREEN!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004478 StringWriter sw = new StringWriter();
4479 PrintWriter pw = new PrintWriter(sw);
4480 this.dump(null, pw, null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004481 Slog.i(TAG, sw.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004482 }
4483 try {
4484 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
4485 if (surfaceFlinger != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004486 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004487 Parcel data = Parcel.obtain();
4488 data.writeInterfaceToken("android.ui.ISurfaceComposer");
4489 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
4490 data, null, 0);
4491 data.recycle();
4492 }
4493 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004494 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004495 }
4496 }
Romain Guy06882f82009-06-10 13:36:04 -07004497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004498 mPolicy.enableScreenAfterBoot();
Romain Guy06882f82009-06-10 13:36:04 -07004499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 // Make sure the last requested orientation has been applied.
Dianne Hackborn321ae682009-03-27 16:16:03 -07004501 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
4502 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004503 }
Romain Guy06882f82009-06-10 13:36:04 -07004504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 public void setInTouchMode(boolean mode) {
4506 synchronized(mWindowMap) {
4507 mInTouchMode = mode;
4508 }
4509 }
4510
Romain Guy06882f82009-06-10 13:36:04 -07004511 public void setRotation(int rotation,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004512 boolean alwaysSendConfiguration, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004513 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004514 "setRotation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004515 throw new SecurityException("Requires SET_ORIENTATION permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004516 }
4517
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004518 setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004519 }
Romain Guy06882f82009-06-10 13:36:04 -07004520
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004521 public void setRotationUnchecked(int rotation,
4522 boolean alwaysSendConfiguration, int animFlags) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004523 if(DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004524 "alwaysSendConfiguration set to "+alwaysSendConfiguration);
Romain Guy06882f82009-06-10 13:36:04 -07004525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004526 long origId = Binder.clearCallingIdentity();
4527 boolean changed;
4528 synchronized(mWindowMap) {
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004529 changed = setRotationUncheckedLocked(rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004530 }
Romain Guy06882f82009-06-10 13:36:04 -07004531
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004532 if (changed || alwaysSendConfiguration) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004533 sendNewConfiguration();
4534 }
Romain Guy06882f82009-06-10 13:36:04 -07004535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004536 Binder.restoreCallingIdentity(origId);
4537 }
Romain Guy06882f82009-06-10 13:36:04 -07004538
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004539 /**
4540 * Apply a new rotation to the screen, respecting the requests of
4541 * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply
4542 * re-evaluate the desired rotation.
4543 *
4544 * Returns null if the rotation has been changed. In this case YOU
4545 * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
4546 */
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004547 public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004548 boolean changed;
4549 if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
4550 rotation = mRequestedRotation;
4551 } else {
4552 mRequestedRotation = rotation;
Dianne Hackborn321ae682009-03-27 16:16:03 -07004553 mLastRotationFlags = animFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004554 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004555 if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation);
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07004556 rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004557 mRotation, mDisplayEnabled);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004558 if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 changed = mDisplayEnabled && mRotation != rotation;
Romain Guy06882f82009-06-10 13:36:04 -07004560
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 if (changed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004562 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004563 "Rotation changed to " + rotation
4564 + " from " + mRotation
4565 + " (forceApp=" + mForcedAppOrientation
4566 + ", req=" + mRequestedRotation + ")");
4567 mRotation = rotation;
4568 mWindowsFreezingScreen = true;
4569 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
4570 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
4571 2000);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004572 mWaitingForConfig = true;
4573 mLayoutNeeded = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004574 startFreezingDisplayLocked();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004575 Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 mQueue.setOrientation(rotation);
4577 if (mDisplayEnabled) {
Dianne Hackborn321ae682009-03-27 16:16:03 -07004578 Surface.setOrientation(0, rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004579 }
4580 for (int i=mWindows.size()-1; i>=0; i--) {
4581 WindowState w = (WindowState)mWindows.get(i);
4582 if (w.mSurface != null) {
4583 w.mOrientationChanging = true;
4584 }
4585 }
4586 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
4587 try {
4588 mRotationWatchers.get(i).onRotationChanged(rotation);
4589 } catch (RemoteException e) {
4590 }
4591 }
4592 } //end if changed
Romain Guy06882f82009-06-10 13:36:04 -07004593
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004594 return changed;
4595 }
Romain Guy06882f82009-06-10 13:36:04 -07004596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004597 public int getRotation() {
4598 return mRotation;
4599 }
4600
4601 public int watchRotation(IRotationWatcher watcher) {
4602 final IBinder watcherBinder = watcher.asBinder();
4603 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4604 public void binderDied() {
4605 synchronized (mWindowMap) {
4606 for (int i=0; i<mRotationWatchers.size(); i++) {
4607 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004608 IRotationWatcher removed = mRotationWatchers.remove(i);
4609 if (removed != null) {
4610 removed.asBinder().unlinkToDeath(this, 0);
4611 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004612 i--;
4613 }
4614 }
4615 }
4616 }
4617 };
Romain Guy06882f82009-06-10 13:36:04 -07004618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004619 synchronized (mWindowMap) {
4620 try {
4621 watcher.asBinder().linkToDeath(dr, 0);
4622 mRotationWatchers.add(watcher);
4623 } catch (RemoteException e) {
4624 // Client died, no cleanup needed.
4625 }
Romain Guy06882f82009-06-10 13:36:04 -07004626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004627 return mRotation;
4628 }
4629 }
4630
4631 /**
4632 * Starts the view server on the specified port.
4633 *
4634 * @param port The port to listener to.
4635 *
4636 * @return True if the server was successfully started, false otherwise.
4637 *
4638 * @see com.android.server.ViewServer
4639 * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT
4640 */
4641 public boolean startViewServer(int port) {
Romain Guy06882f82009-06-10 13:36:04 -07004642 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004643 return false;
4644 }
4645
4646 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4647 return false;
4648 }
4649
4650 if (port < 1024) {
4651 return false;
4652 }
4653
4654 if (mViewServer != null) {
4655 if (!mViewServer.isRunning()) {
4656 try {
4657 return mViewServer.start();
4658 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004659 Slog.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004660 }
4661 }
4662 return false;
4663 }
4664
4665 try {
4666 mViewServer = new ViewServer(this, port);
4667 return mViewServer.start();
4668 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004669 Slog.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004670 }
4671 return false;
4672 }
4673
Romain Guy06882f82009-06-10 13:36:04 -07004674 private boolean isSystemSecure() {
4675 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4676 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4677 }
4678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004679 /**
4680 * Stops the view server if it exists.
4681 *
4682 * @return True if the server stopped, false if it wasn't started or
4683 * couldn't be stopped.
4684 *
4685 * @see com.android.server.ViewServer
4686 */
4687 public boolean stopViewServer() {
Romain Guy06882f82009-06-10 13:36:04 -07004688 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004689 return false;
4690 }
4691
4692 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4693 return false;
4694 }
4695
4696 if (mViewServer != null) {
4697 return mViewServer.stop();
4698 }
4699 return false;
4700 }
4701
4702 /**
4703 * Indicates whether the view server is running.
4704 *
4705 * @return True if the server is running, false otherwise.
4706 *
4707 * @see com.android.server.ViewServer
4708 */
4709 public boolean isViewServerRunning() {
Romain Guy06882f82009-06-10 13:36:04 -07004710 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004711 return false;
4712 }
4713
4714 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4715 return false;
4716 }
4717
4718 return mViewServer != null && mViewServer.isRunning();
4719 }
4720
4721 /**
4722 * Lists all availble windows in the system. The listing is written in the
4723 * specified Socket's output stream with the following syntax:
4724 * windowHashCodeInHexadecimal windowName
4725 * Each line of the ouput represents a different window.
4726 *
4727 * @param client The remote client to send the listing to.
4728 * @return False if an error occured, true otherwise.
4729 */
4730 boolean viewServerListWindows(Socket client) {
Romain Guy06882f82009-06-10 13:36:04 -07004731 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004732 return false;
4733 }
4734
4735 boolean result = true;
4736
4737 Object[] windows;
4738 synchronized (mWindowMap) {
4739 windows = new Object[mWindows.size()];
4740 //noinspection unchecked
4741 windows = mWindows.toArray(windows);
4742 }
4743
4744 BufferedWriter out = null;
4745
4746 // Any uncaught exception will crash the system process
4747 try {
4748 OutputStream clientStream = client.getOutputStream();
4749 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4750
4751 final int count = windows.length;
4752 for (int i = 0; i < count; i++) {
4753 final WindowState w = (WindowState) windows[i];
4754 out.write(Integer.toHexString(System.identityHashCode(w)));
4755 out.write(' ');
4756 out.append(w.mAttrs.getTitle());
4757 out.write('\n');
4758 }
4759
4760 out.write("DONE.\n");
4761 out.flush();
4762 } catch (Exception e) {
4763 result = false;
4764 } finally {
4765 if (out != null) {
4766 try {
4767 out.close();
4768 } catch (IOException e) {
4769 result = false;
4770 }
4771 }
4772 }
4773
4774 return result;
4775 }
4776
4777 /**
4778 * Sends a command to a target window. The result of the command, if any, will be
4779 * written in the output stream of the specified socket.
4780 *
4781 * The parameters must follow this syntax:
4782 * windowHashcode extra
4783 *
4784 * Where XX is the length in characeters of the windowTitle.
4785 *
4786 * The first parameter is the target window. The window with the specified hashcode
4787 * will be the target. If no target can be found, nothing happens. The extra parameters
4788 * will be delivered to the target window and as parameters to the command itself.
4789 *
4790 * @param client The remote client to sent the result, if any, to.
4791 * @param command The command to execute.
4792 * @param parameters The command parameters.
4793 *
4794 * @return True if the command was successfully delivered, false otherwise. This does
4795 * not indicate whether the command itself was successful.
4796 */
4797 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
Romain Guy06882f82009-06-10 13:36:04 -07004798 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004799 return false;
4800 }
4801
4802 boolean success = true;
4803 Parcel data = null;
4804 Parcel reply = null;
4805
4806 // Any uncaught exception will crash the system process
4807 try {
4808 // Find the hashcode of the window
4809 int index = parameters.indexOf(' ');
4810 if (index == -1) {
4811 index = parameters.length();
4812 }
4813 final String code = parameters.substring(0, index);
Romain Guy236092a2009-12-14 15:31:48 -08004814 int hashCode = (int) Long.parseLong(code, 16);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004815
4816 // Extract the command's parameter after the window description
4817 if (index < parameters.length()) {
4818 parameters = parameters.substring(index + 1);
4819 } else {
4820 parameters = "";
4821 }
4822
4823 final WindowManagerService.WindowState window = findWindow(hashCode);
4824 if (window == null) {
4825 return false;
4826 }
4827
4828 data = Parcel.obtain();
4829 data.writeInterfaceToken("android.view.IWindow");
4830 data.writeString(command);
4831 data.writeString(parameters);
4832 data.writeInt(1);
4833 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4834
4835 reply = Parcel.obtain();
4836
4837 final IBinder binder = window.mClient.asBinder();
4838 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4839 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4840
4841 reply.readException();
4842
4843 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004844 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004845 success = false;
4846 } finally {
4847 if (data != null) {
4848 data.recycle();
4849 }
4850 if (reply != null) {
4851 reply.recycle();
4852 }
4853 }
4854
4855 return success;
4856 }
4857
4858 private WindowState findWindow(int hashCode) {
4859 if (hashCode == -1) {
4860 return getFocusedWindow();
4861 }
4862
4863 synchronized (mWindowMap) {
4864 final ArrayList windows = mWindows;
4865 final int count = windows.size();
4866
4867 for (int i = 0; i < count; i++) {
4868 WindowState w = (WindowState) windows.get(i);
4869 if (System.identityHashCode(w) == hashCode) {
4870 return w;
4871 }
4872 }
4873 }
4874
4875 return null;
4876 }
4877
4878 /*
4879 * Instruct the Activity Manager to fetch the current configuration and broadcast
4880 * that to config-changed listeners if appropriate.
4881 */
4882 void sendNewConfiguration() {
4883 try {
4884 mActivityManager.updateConfiguration(null);
4885 } catch (RemoteException e) {
4886 }
4887 }
Romain Guy06882f82009-06-10 13:36:04 -07004888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004889 public Configuration computeNewConfiguration() {
4890 synchronized (mWindowMap) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07004891 return computeNewConfigurationLocked();
4892 }
4893 }
Romain Guy06882f82009-06-10 13:36:04 -07004894
Dianne Hackbornc485a602009-03-24 22:39:49 -07004895 Configuration computeNewConfigurationLocked() {
4896 Configuration config = new Configuration();
4897 if (!computeNewConfigurationLocked(config)) {
4898 return null;
4899 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07004900 return config;
4901 }
Romain Guy06882f82009-06-10 13:36:04 -07004902
Dianne Hackbornc485a602009-03-24 22:39:49 -07004903 boolean computeNewConfigurationLocked(Configuration config) {
4904 if (mDisplay == null) {
4905 return false;
4906 }
4907 mQueue.getInputConfiguration(config);
Christopher Tateb696aee2010-04-02 19:08:30 -07004908
4909 // Use the effective "visual" dimensions based on current rotation
4910 final boolean rotated = (mRotation == Surface.ROTATION_90
4911 || mRotation == Surface.ROTATION_270);
4912 final int dw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth;
4913 final int dh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight;
4914
Dianne Hackbornc485a602009-03-24 22:39:49 -07004915 int orientation = Configuration.ORIENTATION_SQUARE;
4916 if (dw < dh) {
4917 orientation = Configuration.ORIENTATION_PORTRAIT;
4918 } else if (dw > dh) {
4919 orientation = Configuration.ORIENTATION_LANDSCAPE;
4920 }
4921 config.orientation = orientation;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004922
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07004923 DisplayMetrics dm = new DisplayMetrics();
4924 mDisplay.getMetrics(dm);
4925 CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
4926
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004927 if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07004928 // Note we only do this once because at this point we don't
4929 // expect the screen to change in this way at runtime, and want
4930 // to avoid all of this computation for every config change.
Dianne Hackborn723738c2009-06-25 19:48:04 -07004931 int longSize = dw;
4932 int shortSize = dh;
4933 if (longSize < shortSize) {
4934 int tmp = longSize;
4935 longSize = shortSize;
4936 shortSize = tmp;
4937 }
4938 longSize = (int)(longSize/dm.density);
4939 shortSize = (int)(shortSize/dm.density);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07004940
Dianne Hackborn723738c2009-06-25 19:48:04 -07004941 // These semi-magic numbers define our compatibility modes for
4942 // applications with different screens. Don't change unless you
4943 // make sure to test lots and lots of apps!
4944 if (longSize < 470) {
4945 // This is shorter than an HVGA normal density screen (which
4946 // is 480 pixels on its long side).
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004947 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
4948 | Configuration.SCREENLAYOUT_LONG_NO;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004949 } else {
Dianne Hackborn14cee9f2010-04-23 17:51:26 -07004950 // What size is this screen screen?
4951 if (longSize >= 800 && shortSize >= 600) {
4952 // SVGA or larger screens at medium density are the point
4953 // at which we consider it to be an extra large screen.
4954 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE;
4955 } else if (longSize >= 640 && shortSize >= 480) {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004956 // VGA or larger screens at medium density are the point
4957 // at which we consider it to be a large screen.
4958 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
4959 } else {
4960 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004961
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004962 // If this screen is wider than normal HVGA, or taller
4963 // than FWVGA, then for old apps we want to run in size
4964 // compatibility mode.
4965 if (shortSize > 321 || longSize > 570) {
4966 mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
4967 }
4968 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004969
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004970 // Is this a long screen?
4971 if (((longSize*3)/5) >= (shortSize-1)) {
4972 // Anything wider than WVGA (5:3) is considering to be long.
4973 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
4974 } else {
4975 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
4976 }
Dianne Hackborn723738c2009-06-25 19:48:04 -07004977 }
4978 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004979 config.screenLayout = mScreenLayout;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004980
Dianne Hackbornc485a602009-03-24 22:39:49 -07004981 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
4982 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
4983 mPolicy.adjustConfigurationLw(config);
4984 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 }
Romain Guy06882f82009-06-10 13:36:04 -07004986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004987 // -------------------------------------------------------------
4988 // Input Events and Focus Management
4989 // -------------------------------------------------------------
4990
4991 private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
Michael Chane96440f2009-05-06 10:27:36 -07004992 long curTime = SystemClock.uptimeMillis();
4993
Michael Chane10de972009-05-18 11:24:50 -07004994 if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
Michael Chane96440f2009-05-06 10:27:36 -07004995 if (mLastTouchEventType == eventType &&
4996 (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
4997 return;
4998 }
4999 mLastUserActivityCallTime = curTime;
5000 mLastTouchEventType = eventType;
5001 }
5002
5003 if (targetWin == null
5004 || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
5005 mPowerManager.userActivity(curTime, false, eventType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005006 }
5007 }
5008
5009 // tells if it's a cheek event or not -- this function is stateful
5010 private static final int EVENT_NONE = 0;
5011 private static final int EVENT_UNKNOWN = 0;
5012 private static final int EVENT_CHEEK = 0;
5013 private static final int EVENT_IGNORE_DURATION = 300; // ms
5014 private static final float CHEEK_THRESHOLD = 0.6f;
5015 private int mEventState = EVENT_NONE;
5016 private float mEventSize;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005018 private int eventType(MotionEvent ev) {
5019 float size = ev.getSize();
5020 switch (ev.getAction()) {
5021 case MotionEvent.ACTION_DOWN:
5022 mEventSize = size;
5023 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT;
5024 case MotionEvent.ACTION_UP:
5025 if (size > mEventSize) mEventSize = size;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005026 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005027 case MotionEvent.ACTION_MOVE:
5028 final int N = ev.getHistorySize();
5029 if (size > mEventSize) mEventSize = size;
5030 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5031 for (int i=0; i<N; i++) {
5032 size = ev.getHistoricalSize(i);
5033 if (size > mEventSize) mEventSize = size;
5034 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5035 }
5036 if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) {
5037 return TOUCH_EVENT;
5038 } else {
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005039 return LONG_TOUCH_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005040 }
5041 default:
5042 // not good
5043 return OTHER_EVENT;
5044 }
5045 }
5046
5047 /**
5048 * @return Returns true if event was dispatched, false if it was dropped for any reason
5049 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005050 private int dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005051 if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005052 "dispatchPointer " + ev);
5053
Michael Chan53071d62009-05-13 17:29:48 -07005054 if (MEASURE_LATENCY) {
5055 lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
5056 }
5057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005058 Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005059 ev, true, false, pid, uid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005060
Michael Chan53071d62009-05-13 17:29:48 -07005061 if (MEASURE_LATENCY) {
5062 lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
5063 }
5064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 int action = ev.getAction();
Romain Guy06882f82009-06-10 13:36:04 -07005066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005067 if (action == MotionEvent.ACTION_UP) {
5068 // let go of our target
5069 mKeyWaiter.mMotionTarget = null;
5070 mPowerManager.logPointerUpEvent();
5071 } else if (action == MotionEvent.ACTION_DOWN) {
5072 mPowerManager.logPointerDownEvent();
5073 }
5074
5075 if (targetObj == null) {
5076 // In this case we are either dropping the event, or have received
5077 // a move or up without a down. It is common to receive move
5078 // events in such a way, since this means the user is moving the
5079 // pointer without actually pressing down. All other cases should
5080 // be atypical, so let's log them.
Michael Chane96440f2009-05-06 10:27:36 -07005081 if (action != MotionEvent.ACTION_MOVE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005082 Slog.w(TAG, "No window to dispatch pointer action " + ev.getAction());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083 }
Dianne Hackborn6adba242009-11-10 11:10:09 -08005084 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005085 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005086 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005087 if (qev != null) {
5088 mQueue.recycleEvent(qev);
5089 }
5090 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005091 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005092 }
5093 if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborn6adba242009-11-10 11:10:09 -08005094 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005095 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005096 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005097 if (qev != null) {
5098 mQueue.recycleEvent(qev);
5099 }
5100 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005101 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 }
Romain Guy06882f82009-06-10 13:36:04 -07005103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005104 WindowState target = (WindowState)targetObj;
Romain Guy06882f82009-06-10 13:36:04 -07005105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005106 final long eventTime = ev.getEventTime();
Michael Chan53071d62009-05-13 17:29:48 -07005107 final long eventTimeNano = ev.getEventTimeNano();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005108
Joe Onorato8a9b2202010-02-26 18:56:32 -08005109 //Slog.i(TAG, "Sending " + ev + " to " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110
5111 if (uid != 0 && uid != target.mSession.mUid) {
5112 if (mContext.checkPermission(
5113 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5114 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005115 Slog.w(TAG, "Permission denied: injecting pointer event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116 + pid + " uid " + uid + " to window " + target
5117 + " owned by uid " + target.mSession.mUid);
5118 if (qev != null) {
5119 mQueue.recycleEvent(qev);
5120 }
5121 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005122 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005123 }
5124 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005125
Michael Chan53071d62009-05-13 17:29:48 -07005126 if (MEASURE_LATENCY) {
5127 lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano);
5128 }
5129
Romain Guy06882f82009-06-10 13:36:04 -07005130 if ((target.mAttrs.flags &
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005131 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
5132 //target wants to ignore fat touch events
5133 boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev);
5134 //explicit flag to return without processing event further
5135 boolean returnFlag = false;
5136 if((action == MotionEvent.ACTION_DOWN)) {
5137 mFatTouch = false;
5138 if(cheekPress) {
5139 mFatTouch = true;
5140 returnFlag = true;
5141 }
5142 } else {
5143 if(action == MotionEvent.ACTION_UP) {
5144 if(mFatTouch) {
5145 //earlier even was invalid doesnt matter if current up is cheekpress or not
5146 mFatTouch = false;
5147 returnFlag = true;
5148 } else if(cheekPress) {
5149 //cancel the earlier event
5150 ev.setAction(MotionEvent.ACTION_CANCEL);
5151 action = MotionEvent.ACTION_CANCEL;
5152 }
5153 } else if(action == MotionEvent.ACTION_MOVE) {
5154 if(mFatTouch) {
5155 //two cases here
5156 //an invalid down followed by 0 or moves(valid or invalid)
Romain Guy06882f82009-06-10 13:36:04 -07005157 //a valid down, invalid move, more moves. want to ignore till up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005158 returnFlag = true;
5159 } else if(cheekPress) {
5160 //valid down followed by invalid moves
5161 //an invalid move have to cancel earlier action
5162 ev.setAction(MotionEvent.ACTION_CANCEL);
5163 action = MotionEvent.ACTION_CANCEL;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005164 if (DEBUG_INPUT) Slog.v(TAG, "Sending cancel for invalid ACTION_MOVE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005165 //note that the subsequent invalid moves will not get here
5166 mFatTouch = true;
5167 }
5168 }
5169 } //else if action
5170 if(returnFlag) {
5171 //recycle que, ev
5172 if (qev != null) {
5173 mQueue.recycleEvent(qev);
5174 }
5175 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005176 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005177 }
5178 } //end if target
Michael Chane96440f2009-05-06 10:27:36 -07005179
Michael Chan9f028e62009-08-04 17:37:46 -07005180 // Enable this for testing the "right" value
5181 if (false && action == MotionEvent.ACTION_DOWN) {
Michael Chane96440f2009-05-06 10:27:36 -07005182 int max_events_per_sec = 35;
5183 try {
5184 max_events_per_sec = Integer.parseInt(SystemProperties
5185 .get("windowsmgr.max_events_per_sec"));
5186 if (max_events_per_sec < 1) {
5187 max_events_per_sec = 35;
5188 }
5189 } catch (NumberFormatException e) {
5190 }
5191 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
5192 }
5193
5194 /*
5195 * Throttle events to minimize CPU usage when there's a flood of events
5196 * e.g. constant contact with the screen
5197 */
5198 if (action == MotionEvent.ACTION_MOVE) {
5199 long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents;
5200 long now = SystemClock.uptimeMillis();
5201 if (now < nextEventTime) {
5202 try {
5203 Thread.sleep(nextEventTime - now);
5204 } catch (InterruptedException e) {
5205 }
5206 mLastTouchEventTime = nextEventTime;
5207 } else {
5208 mLastTouchEventTime = now;
5209 }
5210 }
5211
Michael Chan53071d62009-05-13 17:29:48 -07005212 if (MEASURE_LATENCY) {
5213 lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano);
5214 }
5215
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005216 synchronized(mWindowMap) {
Dianne Hackborn6adba242009-11-10 11:10:09 -08005217 if (!target.isVisibleLw()) {
5218 // During this motion dispatch, the target window has become
5219 // invisible.
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005220 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), false);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005221 if (qev != null) {
5222 mQueue.recycleEvent(qev);
5223 }
5224 ev.recycle();
5225 return INJECT_SUCCEEDED;
5226 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005228 if (qev != null && action == MotionEvent.ACTION_MOVE) {
5229 mKeyWaiter.bindTargetWindowLocked(target,
5230 KeyWaiter.RETURN_PENDING_POINTER, qev);
5231 ev = null;
5232 } else {
5233 if (action == MotionEvent.ACTION_DOWN) {
5234 WindowState out = mKeyWaiter.mOutsideTouchTargets;
5235 if (out != null) {
5236 MotionEvent oev = MotionEvent.obtain(ev);
Adam Powell47482962010-05-27 15:19:58 -07005237 try {
5238 oev.setAction(MotionEvent.ACTION_OUTSIDE);
5239 do {
5240 final Rect frame = out.mFrame;
5241 oev.offsetLocation(-(float)frame.left, -(float)frame.top);
5242 try {
5243 out.mClient.dispatchPointer(oev, eventTime, false);
5244 } catch (android.os.RemoteException e) {
5245 Slog.i(TAG,
5246 "WINDOW DIED during outside motion dispatch: " + out);
5247 }
5248 oev.offsetLocation((float)frame.left, (float)frame.top);
5249 out = out.mNextOutsideTouch;
5250 } while (out != null);
5251 mKeyWaiter.mOutsideTouchTargets = null;
5252 } finally {
5253 oev.recycle();
5254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005255 }
5256 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005257
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005258 dispatchPointerElsewhereLocked(target, null, ev, ev.getEventTime(), false);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005259
Dianne Hackborn6adba242009-11-10 11:10:09 -08005260 final Rect frame = target.mFrame;
5261 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
5262 mKeyWaiter.bindTargetWindowLocked(target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005263 }
5264 }
Romain Guy06882f82009-06-10 13:36:04 -07005265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005266 // finally offset the event to the target's coordinate system and
5267 // dispatch the event.
5268 try {
5269 if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005270 Slog.v(TAG, "Delivering pointer " + qev + " to " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005271 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005272
Michael Chan53071d62009-05-13 17:29:48 -07005273 if (MEASURE_LATENCY) {
5274 lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
5275 }
5276
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005277 target.mClient.dispatchPointer(ev, eventTime, true);
Michael Chan53071d62009-05-13 17:29:48 -07005278
5279 if (MEASURE_LATENCY) {
5280 lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
5281 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07005282 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005283 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005284 Slog.i(TAG, "WINDOW DIED during motion dispatch: " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005285 mKeyWaiter.mMotionTarget = null;
5286 try {
5287 removeWindow(target.mSession, target.mClient);
5288 } catch (java.util.NoSuchElementException ex) {
5289 // This will happen if the window has already been
5290 // removed.
5291 }
5292 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07005293 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 }
Romain Guy06882f82009-06-10 13:36:04 -07005295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 /**
5297 * @return Returns true if event was dispatched, false if it was dropped for any reason
5298 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005299 private int dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005300 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005301 TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">");
Romain Guy06882f82009-06-10 13:36:04 -07005302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005303 Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005304 ev, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 if (focusObj == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005306 Slog.w(TAG, "No focus window, dropping trackball: " + ev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005307 if (qev != null) {
5308 mQueue.recycleEvent(qev);
5309 }
5310 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005311 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 }
5313 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5314 if (qev != null) {
5315 mQueue.recycleEvent(qev);
5316 }
5317 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005318 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005319 }
Romain Guy06882f82009-06-10 13:36:04 -07005320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07005322
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005323 if (uid != 0 && uid != focus.mSession.mUid) {
5324 if (mContext.checkPermission(
5325 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5326 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005327 Slog.w(TAG, "Permission denied: injecting key event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 + pid + " uid " + uid + " to window " + focus
5329 + " owned by uid " + focus.mSession.mUid);
5330 if (qev != null) {
5331 mQueue.recycleEvent(qev);
5332 }
5333 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005334 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005335 }
5336 }
Romain Guy06882f82009-06-10 13:36:04 -07005337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005338 final long eventTime = ev.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07005339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005340 synchronized(mWindowMap) {
5341 if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) {
5342 mKeyWaiter.bindTargetWindowLocked(focus,
5343 KeyWaiter.RETURN_PENDING_TRACKBALL, qev);
5344 // We don't deliver movement events to the client, we hold
5345 // them and wait for them to call back.
5346 ev = null;
5347 } else {
5348 mKeyWaiter.bindTargetWindowLocked(focus);
5349 }
5350 }
Romain Guy06882f82009-06-10 13:36:04 -07005351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005352 try {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005353 focus.mClient.dispatchTrackball(ev, eventTime, true);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005354 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005355 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005356 Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005357 try {
5358 removeWindow(focus.mSession, focus.mClient);
5359 } catch (java.util.NoSuchElementException ex) {
5360 // This will happen if the window has already been
5361 // removed.
5362 }
5363 }
Romain Guy06882f82009-06-10 13:36:04 -07005364
Dianne Hackborncfaef692009-06-15 14:24:44 -07005365 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005366 }
Romain Guy06882f82009-06-10 13:36:04 -07005367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005368 /**
5369 * @return Returns true if event was dispatched, false if it was dropped for any reason
5370 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005371 private int dispatchKey(KeyEvent event, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005372 if (DEBUG_INPUT) Slog.v(TAG, "Dispatch key: " + event);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005373
5374 Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005375 null, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005376 if (focusObj == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005377 Slog.w(TAG, "No focus window, dropping: " + event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005378 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005379 }
5380 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005381 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005382 }
Romain Guy06882f82009-06-10 13:36:04 -07005383
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07005384 // Okay we have finished waiting for the last event to be processed.
5385 // First off, if this is a repeat event, check to see if there is
5386 // a corresponding up event in the queue. If there is, we will
5387 // just drop the repeat, because it makes no sense to repeat after
5388 // the user has released a key. (This is especially important for
5389 // long presses.)
5390 if (event.getRepeatCount() > 0 && mQueue.hasKeyUpEvent(event)) {
5391 return INJECT_SUCCEEDED;
5392 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005393
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005394 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07005395
Joe Onorato8a9b2202010-02-26 18:56:32 -08005396 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005397 TAG, "Dispatching to " + focus + ": " + event);
5398
5399 if (uid != 0 && uid != focus.mSession.mUid) {
5400 if (mContext.checkPermission(
5401 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5402 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005403 Slog.w(TAG, "Permission denied: injecting key event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005404 + pid + " uid " + uid + " to window " + focus
5405 + " owned by uid " + focus.mSession.mUid);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005406 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005407 }
5408 }
Romain Guy06882f82009-06-10 13:36:04 -07005409
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005410 synchronized(mWindowMap) {
5411 mKeyWaiter.bindTargetWindowLocked(focus);
5412 }
5413
5414 // NOSHIP extra state logging
5415 mKeyWaiter.recordDispatchState(event, focus);
5416 // END NOSHIP
Romain Guy06882f82009-06-10 13:36:04 -07005417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005418 try {
5419 if (DEBUG_INPUT || DEBUG_FOCUS) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005420 Slog.v(TAG, "Delivering key " + event.getKeyCode()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005421 + " to " + focus);
5422 }
5423 focus.mClient.dispatchKey(event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005424 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005425 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005426 Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005427 try {
5428 removeWindow(focus.mSession, focus.mClient);
5429 } catch (java.util.NoSuchElementException ex) {
5430 // This will happen if the window has already been
5431 // removed.
5432 }
5433 }
Romain Guy06882f82009-06-10 13:36:04 -07005434
Dianne Hackborncfaef692009-06-15 14:24:44 -07005435 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005436 }
Romain Guy06882f82009-06-10 13:36:04 -07005437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005438 public void pauseKeyDispatching(IBinder _token) {
5439 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5440 "pauseKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005441 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005442 }
5443
5444 synchronized (mWindowMap) {
5445 WindowToken token = mTokenMap.get(_token);
5446 if (token != null) {
5447 mKeyWaiter.pauseDispatchingLocked(token);
5448 }
5449 }
5450 }
5451
5452 public void resumeKeyDispatching(IBinder _token) {
5453 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5454 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005455 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005456 }
5457
5458 synchronized (mWindowMap) {
5459 WindowToken token = mTokenMap.get(_token);
5460 if (token != null) {
5461 mKeyWaiter.resumeDispatchingLocked(token);
5462 }
5463 }
5464 }
5465
5466 public void setEventDispatching(boolean enabled) {
5467 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5468 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005469 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005470 }
5471
5472 synchronized (mWindowMap) {
5473 mKeyWaiter.setEventDispatchingLocked(enabled);
5474 }
5475 }
Romain Guy06882f82009-06-10 13:36:04 -07005476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005477 /**
5478 * Injects a keystroke event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005479 *
5480 * @param ev A motion event describing the keystroke action. (Be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005481 * {@link SystemClock#uptimeMillis()} as the timebase.)
5482 * @param sync If true, wait for the event to be completed before returning to the caller.
5483 * @return Returns true if event was dispatched, false if it was dropped for any reason
5484 */
5485 public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
5486 long downTime = ev.getDownTime();
5487 long eventTime = ev.getEventTime();
5488
5489 int action = ev.getAction();
5490 int code = ev.getKeyCode();
5491 int repeatCount = ev.getRepeatCount();
5492 int metaState = ev.getMetaState();
5493 int deviceId = ev.getDeviceId();
5494 int scancode = ev.getScanCode();
5495
5496 if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
5497 if (downTime == 0) downTime = eventTime;
5498
5499 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
The Android Open Source Project10592532009-03-18 17:39:46 -07005500 deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005502 final int pid = Binder.getCallingPid();
5503 final int uid = Binder.getCallingUid();
5504 final long ident = Binder.clearCallingIdentity();
5505 final int result = dispatchKey(newEvent, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005506 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005507 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005508 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005509 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005510 switch (result) {
5511 case INJECT_NO_PERMISSION:
5512 throw new SecurityException(
Chander S Pechetty27f3de62010-02-10 22:14:00 +05305513 "Injecting to another application requires INJECT_EVENTS permission");
Dianne Hackborncfaef692009-06-15 14:24:44 -07005514 case INJECT_SUCCEEDED:
5515 return true;
5516 }
5517 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 }
5519
5520 /**
5521 * Inject a pointer (touch) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005522 *
5523 * @param ev A motion event describing the pointer (touch) action. (As noted in
5524 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005525 * {@link SystemClock#uptimeMillis()} as the timebase.)
5526 * @param sync If true, wait for the event to be completed before returning to the caller.
5527 * @return Returns true if event was dispatched, false if it was dropped for any reason
5528 */
5529 public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005530 final int pid = Binder.getCallingPid();
5531 final int uid = Binder.getCallingUid();
5532 final long ident = Binder.clearCallingIdentity();
5533 final int result = dispatchPointer(null, ev, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005534 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005535 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005536 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005537 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005538 switch (result) {
5539 case INJECT_NO_PERMISSION:
5540 throw new SecurityException(
Chander S Pechetty27f3de62010-02-10 22:14:00 +05305541 "Injecting to another application requires INJECT_EVENTS permission");
Dianne Hackborncfaef692009-06-15 14:24:44 -07005542 case INJECT_SUCCEEDED:
5543 return true;
5544 }
5545 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005546 }
Romain Guy06882f82009-06-10 13:36:04 -07005547
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005548 /**
5549 * Inject a trackball (navigation device) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005550 *
5551 * @param ev A motion event describing the trackball action. (As noted in
5552 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005553 * {@link SystemClock#uptimeMillis()} as the timebase.)
5554 * @param sync If true, wait for the event to be completed before returning to the caller.
5555 * @return Returns true if event was dispatched, false if it was dropped for any reason
5556 */
5557 public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005558 final int pid = Binder.getCallingPid();
5559 final int uid = Binder.getCallingUid();
5560 final long ident = Binder.clearCallingIdentity();
5561 final int result = dispatchTrackball(null, ev, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005562 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005563 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005564 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005565 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005566 switch (result) {
5567 case INJECT_NO_PERMISSION:
5568 throw new SecurityException(
Chander S Pechetty27f3de62010-02-10 22:14:00 +05305569 "Injecting to another application requires INJECT_EVENTS permission");
Dianne Hackborncfaef692009-06-15 14:24:44 -07005570 case INJECT_SUCCEEDED:
5571 return true;
5572 }
5573 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005574 }
Romain Guy06882f82009-06-10 13:36:04 -07005575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005576 private WindowState getFocusedWindow() {
5577 synchronized (mWindowMap) {
5578 return getFocusedWindowLocked();
5579 }
5580 }
5581
5582 private WindowState getFocusedWindowLocked() {
5583 return mCurrentFocus;
5584 }
Romain Guy06882f82009-06-10 13:36:04 -07005585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005586 /**
5587 * This class holds the state for dispatching key events. This state
5588 * is protected by the KeyWaiter instance, NOT by the window lock. You
5589 * can be holding the main window lock while acquire the KeyWaiter lock,
5590 * but not the other way around.
5591 */
5592 final class KeyWaiter {
5593 // NOSHIP debugging
5594 public class DispatchState {
5595 private KeyEvent event;
5596 private WindowState focus;
5597 private long time;
5598 private WindowState lastWin;
5599 private IBinder lastBinder;
5600 private boolean finished;
5601 private boolean gotFirstWindow;
5602 private boolean eventDispatching;
5603 private long timeToSwitch;
5604 private boolean wasFrozen;
5605 private boolean focusPaused;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005606 private WindowState curFocus;
Romain Guy06882f82009-06-10 13:36:04 -07005607
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005608 DispatchState(KeyEvent theEvent, WindowState theFocus) {
5609 focus = theFocus;
5610 event = theEvent;
5611 time = System.currentTimeMillis();
5612 // snapshot KeyWaiter state
5613 lastWin = mLastWin;
5614 lastBinder = mLastBinder;
5615 finished = mFinished;
5616 gotFirstWindow = mGotFirstWindow;
5617 eventDispatching = mEventDispatching;
5618 timeToSwitch = mTimeToSwitch;
5619 wasFrozen = mWasFrozen;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005620 curFocus = mCurrentFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005621 // cache the paused state at ctor time as well
5622 if (theFocus == null || theFocus.mToken == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005623 focusPaused = false;
5624 } else {
5625 focusPaused = theFocus.mToken.paused;
5626 }
5627 }
Romain Guy06882f82009-06-10 13:36:04 -07005628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629 public String toString() {
5630 return "{{" + event + " to " + focus + " @ " + time
5631 + " lw=" + lastWin + " lb=" + lastBinder
5632 + " fin=" + finished + " gfw=" + gotFirstWindow
5633 + " ed=" + eventDispatching + " tts=" + timeToSwitch
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005634 + " wf=" + wasFrozen + " fp=" + focusPaused
Christopher Tate46d45252010-02-09 15:48:57 -08005635 + " mcf=" + curFocus + "}}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005636 }
5637 };
5638 private DispatchState mDispatchState = null;
5639 public void recordDispatchState(KeyEvent theEvent, WindowState theFocus) {
5640 mDispatchState = new DispatchState(theEvent, theFocus);
5641 }
5642 // END NOSHIP
5643
5644 public static final int RETURN_NOTHING = 0;
5645 public static final int RETURN_PENDING_POINTER = 1;
5646 public static final int RETURN_PENDING_TRACKBALL = 2;
Romain Guy06882f82009-06-10 13:36:04 -07005647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005648 final Object SKIP_TARGET_TOKEN = new Object();
5649 final Object CONSUMED_EVENT_TOKEN = new Object();
Romain Guy06882f82009-06-10 13:36:04 -07005650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005651 private WindowState mLastWin = null;
5652 private IBinder mLastBinder = null;
5653 private boolean mFinished = true;
5654 private boolean mGotFirstWindow = false;
5655 private boolean mEventDispatching = true;
5656 private long mTimeToSwitch = 0;
5657 /* package */ boolean mWasFrozen = false;
Romain Guy06882f82009-06-10 13:36:04 -07005658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005659 // Target of Motion events
5660 WindowState mMotionTarget;
Romain Guy06882f82009-06-10 13:36:04 -07005661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005662 // Windows above the target who would like to receive an "outside"
5663 // touch event for any down events outside of them.
5664 WindowState mOutsideTouchTargets;
5665
5666 /**
5667 * Wait for the last event dispatch to complete, then find the next
5668 * target that should receive the given event and wait for that one
5669 * to be ready to receive it.
5670 */
5671 Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev,
5672 MotionEvent nextMotion, boolean isPointerEvent,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005673 boolean failIfTimeout, int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005674 long startTime = SystemClock.uptimeMillis();
5675 long keyDispatchingTimeout = 5 * 1000;
5676 long waitedFor = 0;
5677
5678 while (true) {
5679 // Figure out which window we care about. It is either the
5680 // last window we are waiting to have process the event or,
5681 // if none, then the next window we think the event should go
5682 // to. Note: we retrieve mLastWin outside of the lock, so
5683 // it may change before we lock. Thus we must check it again.
5684 WindowState targetWin = mLastWin;
5685 boolean targetIsNew = targetWin == null;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005686 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005687 TAG, "waitForLastKey: mFinished=" + mFinished +
5688 ", mLastWin=" + mLastWin);
5689 if (targetIsNew) {
5690 Object target = findTargetWindow(nextKey, qev, nextMotion,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005691 isPointerEvent, callingPid, callingUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005692 if (target == SKIP_TARGET_TOKEN) {
5693 // The user has pressed a special key, and we are
5694 // dropping all pending events before it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005695 if (DEBUG_INPUT) Slog.v(TAG, "Skipping: " + nextKey
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005696 + " " + nextMotion);
5697 return null;
5698 }
5699 if (target == CONSUMED_EVENT_TOKEN) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005700 if (DEBUG_INPUT) Slog.v(TAG, "Consumed: " + nextKey
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005701 + " " + nextMotion);
5702 return target;
5703 }
5704 targetWin = (WindowState)target;
5705 }
Romain Guy06882f82009-06-10 13:36:04 -07005706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005707 AppWindowToken targetApp = null;
Romain Guy06882f82009-06-10 13:36:04 -07005708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005709 // Now: is it okay to send the next event to this window?
5710 synchronized (this) {
5711 // First: did we come here based on the last window not
5712 // being null, but it changed by the time we got here?
5713 // If so, try again.
5714 if (!targetIsNew && mLastWin == null) {
5715 continue;
5716 }
Romain Guy06882f82009-06-10 13:36:04 -07005717
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005718 // We never dispatch events if not finished with the
5719 // last one, or the display is frozen.
5720 if (mFinished && !mDisplayFrozen) {
5721 // If event dispatching is disabled, then we
5722 // just consume the events.
5723 if (!mEventDispatching) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005724 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005725 "Skipping event; dispatching disabled: "
5726 + nextKey + " " + nextMotion);
5727 return null;
5728 }
5729 if (targetWin != null) {
5730 // If this is a new target, and that target is not
5731 // paused or unresponsive, then all looks good to
5732 // handle the event.
5733 if (targetIsNew && !targetWin.mToken.paused) {
5734 return targetWin;
5735 }
Romain Guy06882f82009-06-10 13:36:04 -07005736
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005737 // If we didn't find a target window, and there is no
5738 // focused app window, then just eat the events.
5739 } else if (mFocusedApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005740 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 "Skipping event; no focused app: "
5742 + nextKey + " " + nextMotion);
5743 return null;
5744 }
5745 }
Romain Guy06882f82009-06-10 13:36:04 -07005746
Joe Onorato8a9b2202010-02-26 18:56:32 -08005747 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005748 TAG, "Waiting for last key in " + mLastBinder
5749 + " target=" + targetWin
5750 + " mFinished=" + mFinished
5751 + " mDisplayFrozen=" + mDisplayFrozen
5752 + " targetIsNew=" + targetIsNew
5753 + " paused="
5754 + (targetWin != null ? targetWin.mToken.paused : false)
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005755 + " mFocusedApp=" + mFocusedApp
5756 + " mCurrentFocus=" + mCurrentFocus);
Romain Guy06882f82009-06-10 13:36:04 -07005757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005758 targetApp = targetWin != null
5759 ? targetWin.mAppToken : mFocusedApp;
Romain Guy06882f82009-06-10 13:36:04 -07005760
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005761 long curTimeout = keyDispatchingTimeout;
5762 if (mTimeToSwitch != 0) {
5763 long now = SystemClock.uptimeMillis();
5764 if (mTimeToSwitch <= now) {
5765 // If an app switch key has been pressed, and we have
5766 // waited too long for the current app to finish
5767 // processing keys, then wait no more!
Christopher Tate136b1f92010-02-11 17:51:24 -08005768 doFinishedKeyLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005769 continue;
5770 }
5771 long switchTimeout = mTimeToSwitch - now;
5772 if (curTimeout > switchTimeout) {
5773 curTimeout = switchTimeout;
5774 }
5775 }
Romain Guy06882f82009-06-10 13:36:04 -07005776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005777 try {
5778 // after that continue
5779 // processing keys, so we don't get stuck.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005780 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005781 TAG, "Waiting for key dispatch: " + curTimeout);
5782 wait(curTimeout);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005783 if (DEBUG_INPUT) Slog.v(TAG, "Finished waiting @"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005784 + SystemClock.uptimeMillis() + " startTime="
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005785 + startTime + " switchTime=" + mTimeToSwitch
5786 + " target=" + targetWin + " mLW=" + mLastWin
5787 + " mLB=" + mLastBinder + " fin=" + mFinished
5788 + " mCurrentFocus=" + mCurrentFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005789 } catch (InterruptedException e) {
5790 }
5791 }
5792
5793 // If we were frozen during configuration change, restart the
5794 // timeout checks from now; otherwise look at whether we timed
5795 // out before awakening.
5796 if (mWasFrozen) {
5797 waitedFor = 0;
5798 mWasFrozen = false;
5799 } else {
5800 waitedFor = SystemClock.uptimeMillis() - startTime;
5801 }
5802
5803 if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) {
5804 IApplicationToken at = null;
5805 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005806 Slog.w(TAG, "Key dispatching timed out sending to " +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005807 (targetWin != null ? targetWin.mAttrs.getTitle()
Ken Shirriff8200b202010-02-04 13:34:37 -08005808 : "<null>: no window ready for key dispatch"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005809 // NOSHIP debugging
Joe Onorato8a9b2202010-02-26 18:56:32 -08005810 Slog.w(TAG, "Previous dispatch state: " + mDispatchState);
5811 Slog.w(TAG, "Current dispatch state: " +
Ken Shirriff8200b202010-02-04 13:34:37 -08005812 new DispatchState(nextKey, targetWin));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005813 // END NOSHIP
5814 //dump();
5815 if (targetWin != null) {
5816 at = targetWin.getAppToken();
5817 } else if (targetApp != null) {
5818 at = targetApp.appToken;
5819 }
5820 }
5821
5822 boolean abort = true;
5823 if (at != null) {
5824 try {
5825 long timeout = at.getKeyDispatchingTimeout();
5826 if (timeout > waitedFor) {
5827 // we did not wait the proper amount of time for this application.
5828 // set the timeout to be the real timeout and wait again.
5829 keyDispatchingTimeout = timeout - waitedFor;
5830 continue;
5831 } else {
5832 abort = at.keyDispatchingTimedOut();
5833 }
5834 } catch (RemoteException ex) {
5835 }
5836 }
5837
5838 synchronized (this) {
5839 if (abort && (mLastWin == targetWin || targetWin == null)) {
5840 mFinished = true;
Romain Guy06882f82009-06-10 13:36:04 -07005841 if (mLastWin != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005842 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005843 "Window " + mLastWin +
5844 " timed out on key input");
5845 if (mLastWin.mToken.paused) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005846 Slog.w(TAG, "Un-pausing dispatching to this window");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005847 mLastWin.mToken.paused = false;
5848 }
5849 }
5850 if (mMotionTarget == targetWin) {
5851 mMotionTarget = null;
5852 }
5853 mLastWin = null;
5854 mLastBinder = null;
5855 if (failIfTimeout || targetWin == null) {
5856 return null;
5857 }
5858 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005859 Slog.w(TAG, "Continuing to wait for key to be dispatched");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 startTime = SystemClock.uptimeMillis();
5861 }
5862 }
5863 }
5864 }
5865 }
Romain Guy06882f82009-06-10 13:36:04 -07005866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005867 Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005868 MotionEvent nextMotion, boolean isPointerEvent,
5869 int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005870 mOutsideTouchTargets = null;
Romain Guy06882f82009-06-10 13:36:04 -07005871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005872 if (nextKey != null) {
5873 // Find the target window for a normal key event.
5874 final int keycode = nextKey.getKeyCode();
5875 final int repeatCount = nextKey.getRepeatCount();
5876 final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP;
5877 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005878
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005879 if (!dispatch) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005880 if (callingUid == 0 ||
5881 mContext.checkPermission(
5882 android.Manifest.permission.INJECT_EVENTS,
5883 callingPid, callingUid)
5884 == PackageManager.PERMISSION_GRANTED) {
5885 mPolicy.interceptKeyTi(null, keycode,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07005886 nextKey.getMetaState(), down, repeatCount,
5887 nextKey.getFlags());
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005888 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005889 Slog.w(TAG, "Event timeout during app switch: dropping "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005890 + nextKey);
5891 return SKIP_TARGET_TOKEN;
5892 }
Romain Guy06882f82009-06-10 13:36:04 -07005893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005894 // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")");
Romain Guy06882f82009-06-10 13:36:04 -07005895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005896 WindowState focus = null;
5897 synchronized(mWindowMap) {
5898 focus = getFocusedWindowLocked();
5899 }
Romain Guy06882f82009-06-10 13:36:04 -07005900
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005901 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
Romain Guy06882f82009-06-10 13:36:04 -07005902
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005903 if (callingUid == 0 ||
5904 (focus != null && callingUid == focus.mSession.mUid) ||
5905 mContext.checkPermission(
5906 android.Manifest.permission.INJECT_EVENTS,
5907 callingPid, callingUid)
5908 == PackageManager.PERMISSION_GRANTED) {
5909 if (mPolicy.interceptKeyTi(focus,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005910 keycode, nextKey.getMetaState(), down, repeatCount,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07005911 nextKey.getFlags())) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005912 return CONSUMED_EVENT_TOKEN;
5913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005914 }
Romain Guy06882f82009-06-10 13:36:04 -07005915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005916 return focus;
Romain Guy06882f82009-06-10 13:36:04 -07005917
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005918 } else if (!isPointerEvent) {
5919 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1);
5920 if (!dispatch) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005921 Slog.w(TAG, "Event timeout during app switch: dropping trackball "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005922 + nextMotion);
5923 return SKIP_TARGET_TOKEN;
5924 }
Romain Guy06882f82009-06-10 13:36:04 -07005925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005926 WindowState focus = null;
5927 synchronized(mWindowMap) {
5928 focus = getFocusedWindowLocked();
5929 }
Romain Guy06882f82009-06-10 13:36:04 -07005930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005931 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
5932 return focus;
5933 }
Romain Guy06882f82009-06-10 13:36:04 -07005934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005935 if (nextMotion == null) {
5936 return SKIP_TARGET_TOKEN;
5937 }
Romain Guy06882f82009-06-10 13:36:04 -07005938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005939 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(
5940 KeyEvent.KEYCODE_UNKNOWN);
5941 if (!dispatch) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005942 Slog.w(TAG, "Event timeout during app switch: dropping pointer "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005943 + nextMotion);
5944 return SKIP_TARGET_TOKEN;
5945 }
Romain Guy06882f82009-06-10 13:36:04 -07005946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005947 // Find the target window for a pointer event.
5948 int action = nextMotion.getAction();
5949 final float xf = nextMotion.getX();
5950 final float yf = nextMotion.getY();
5951 final long eventTime = nextMotion.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07005952
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005953 final boolean screenWasOff = qev != null
5954 && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07005955
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005956 WindowState target = null;
Romain Guy06882f82009-06-10 13:36:04 -07005957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005958 synchronized(mWindowMap) {
5959 synchronized (this) {
5960 if (action == MotionEvent.ACTION_DOWN) {
5961 if (mMotionTarget != null) {
5962 // this is weird, we got a pen down, but we thought it was
5963 // already down!
5964 // XXX: We should probably send an ACTION_UP to the current
5965 // target.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005966 Slog.w(TAG, "Pointer down received while already down in: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005967 + mMotionTarget);
5968 mMotionTarget = null;
5969 }
Romain Guy06882f82009-06-10 13:36:04 -07005970
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005971 // ACTION_DOWN is special, because we need to lock next events to
5972 // the window we'll land onto.
5973 final int x = (int)xf;
5974 final int y = (int)yf;
Romain Guy06882f82009-06-10 13:36:04 -07005975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005976 final ArrayList windows = mWindows;
5977 final int N = windows.size();
5978 WindowState topErrWindow = null;
5979 final Rect tmpRect = mTempRect;
5980 for (int i=N-1; i>=0; i--) {
5981 WindowState child = (WindowState)windows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005982 //Slog.i(TAG, "Checking dispatch to: " + child);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005983 final int flags = child.mAttrs.flags;
5984 if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
5985 if (topErrWindow == null) {
5986 topErrWindow = child;
5987 }
5988 }
5989 if (!child.isVisibleLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005990 //Slog.i(TAG, "Not visible!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005991 continue;
5992 }
5993 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005994 //Slog.i(TAG, "Not touchable!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005995 if ((flags & WindowManager.LayoutParams
5996 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5997 child.mNextOutsideTouch = mOutsideTouchTargets;
5998 mOutsideTouchTargets = child;
5999 }
6000 continue;
6001 }
6002 tmpRect.set(child.mFrame);
6003 if (child.mTouchableInsets == ViewTreeObserver
6004 .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
6005 // The touch is inside of the window if it is
6006 // inside the frame, AND the content part of that
6007 // frame that was given by the application.
6008 tmpRect.left += child.mGivenContentInsets.left;
6009 tmpRect.top += child.mGivenContentInsets.top;
6010 tmpRect.right -= child.mGivenContentInsets.right;
6011 tmpRect.bottom -= child.mGivenContentInsets.bottom;
6012 } else if (child.mTouchableInsets == ViewTreeObserver
6013 .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
6014 // The touch is inside of the window if it is
6015 // inside the frame, AND the visible part of that
6016 // frame that was given by the application.
6017 tmpRect.left += child.mGivenVisibleInsets.left;
6018 tmpRect.top += child.mGivenVisibleInsets.top;
6019 tmpRect.right -= child.mGivenVisibleInsets.right;
6020 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
6021 }
6022 final int touchFlags = flags &
6023 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6024 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
6025 if (tmpRect.contains(x, y) || touchFlags == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006026 //Slog.i(TAG, "Using this target!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006027 if (!screenWasOff || (flags &
6028 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
6029 mMotionTarget = child;
6030 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006031 //Slog.i(TAG, "Waking, skip!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006032 mMotionTarget = null;
6033 }
6034 break;
6035 }
Romain Guy06882f82009-06-10 13:36:04 -07006036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006037 if ((flags & WindowManager.LayoutParams
6038 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
6039 child.mNextOutsideTouch = mOutsideTouchTargets;
6040 mOutsideTouchTargets = child;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006041 //Slog.i(TAG, "Adding to outside target list: " + child);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006042 }
6043 }
6044
6045 // if there's an error window but it's not accepting
6046 // focus (typically because it is not yet visible) just
6047 // wait for it -- any other focused window may in fact
6048 // be in ANR state.
6049 if (topErrWindow != null && mMotionTarget != topErrWindow) {
6050 mMotionTarget = null;
6051 }
6052 }
Romain Guy06882f82009-06-10 13:36:04 -07006053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006054 target = mMotionTarget;
6055 }
6056 }
Romain Guy06882f82009-06-10 13:36:04 -07006057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006058 wakeupIfNeeded(target, eventType(nextMotion));
Romain Guy06882f82009-06-10 13:36:04 -07006059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006060 // Pointer events are a little different -- if there isn't a
6061 // target found for any event, then just drop it.
6062 return target != null ? target : SKIP_TARGET_TOKEN;
6063 }
Romain Guy06882f82009-06-10 13:36:04 -07006064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006065 boolean checkShouldDispatchKey(int keycode) {
6066 synchronized (this) {
6067 if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) {
6068 mTimeToSwitch = 0;
6069 return true;
6070 }
6071 if (mTimeToSwitch != 0
6072 && mTimeToSwitch < SystemClock.uptimeMillis()) {
6073 return false;
6074 }
6075 return true;
6076 }
6077 }
Romain Guy06882f82009-06-10 13:36:04 -07006078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006079 void bindTargetWindowLocked(WindowState win,
6080 int pendingWhat, QueuedEvent pendingMotion) {
6081 synchronized (this) {
6082 bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion);
6083 }
6084 }
Romain Guy06882f82009-06-10 13:36:04 -07006085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006086 void bindTargetWindowLocked(WindowState win) {
6087 synchronized (this) {
6088 bindTargetWindowLockedLocked(win, RETURN_NOTHING, null);
6089 }
6090 }
6091
6092 void bindTargetWindowLockedLocked(WindowState win,
6093 int pendingWhat, QueuedEvent pendingMotion) {
6094 mLastWin = win;
6095 mLastBinder = win.mClient.asBinder();
6096 mFinished = false;
6097 if (pendingMotion != null) {
6098 final Session s = win.mSession;
6099 if (pendingWhat == RETURN_PENDING_POINTER) {
6100 releasePendingPointerLocked(s);
6101 s.mPendingPointerMove = pendingMotion;
6102 s.mPendingPointerWindow = win;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006103 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006104 "bindTargetToWindow " + s.mPendingPointerMove);
6105 } else if (pendingWhat == RETURN_PENDING_TRACKBALL) {
6106 releasePendingTrackballLocked(s);
6107 s.mPendingTrackballMove = pendingMotion;
6108 s.mPendingTrackballWindow = win;
6109 }
6110 }
6111 }
Romain Guy06882f82009-06-10 13:36:04 -07006112
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006113 void releasePendingPointerLocked(Session s) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006114 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 "releasePendingPointer " + s.mPendingPointerMove);
6116 if (s.mPendingPointerMove != null) {
6117 mQueue.recycleEvent(s.mPendingPointerMove);
6118 s.mPendingPointerMove = null;
6119 }
6120 }
Romain Guy06882f82009-06-10 13:36:04 -07006121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006122 void releasePendingTrackballLocked(Session s) {
6123 if (s.mPendingTrackballMove != null) {
6124 mQueue.recycleEvent(s.mPendingTrackballMove);
6125 s.mPendingTrackballMove = null;
6126 }
6127 }
Romain Guy06882f82009-06-10 13:36:04 -07006128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006129 MotionEvent finishedKey(Session session, IWindow client, boolean force,
6130 int returnWhat) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006131 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006132 TAG, "finishedKey: client=" + client + ", force=" + force);
6133
6134 if (client == null) {
6135 return null;
6136 }
6137
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006138 MotionEvent res = null;
6139 QueuedEvent qev = null;
6140 WindowState win = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006142 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006143 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006144 TAG, "finishedKey: client=" + client.asBinder()
6145 + ", force=" + force + ", last=" + mLastBinder
6146 + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
6147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006148 if (returnWhat == RETURN_PENDING_POINTER) {
6149 qev = session.mPendingPointerMove;
6150 win = session.mPendingPointerWindow;
6151 session.mPendingPointerMove = null;
6152 session.mPendingPointerWindow = null;
6153 } else if (returnWhat == RETURN_PENDING_TRACKBALL) {
6154 qev = session.mPendingTrackballMove;
6155 win = session.mPendingTrackballWindow;
6156 session.mPendingTrackballMove = null;
6157 session.mPendingTrackballWindow = null;
6158 }
Romain Guy06882f82009-06-10 13:36:04 -07006159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006160 if (mLastBinder == client.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006161 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006162 TAG, "finishedKey: last paused="
6163 + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
6164 if (mLastWin != null && (!mLastWin.mToken.paused || force
6165 || !mEventDispatching)) {
Christopher Tate136b1f92010-02-11 17:51:24 -08006166 doFinishedKeyLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 } else {
6168 // Make sure to wake up anyone currently waiting to
6169 // dispatch a key, so they can re-evaluate their
6170 // current situation.
6171 mFinished = true;
6172 notifyAll();
6173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006174 }
Romain Guy06882f82009-06-10 13:36:04 -07006175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006176 if (qev != null) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006177 res = (MotionEvent)qev.event;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006178 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006179 "Returning pending motion: " + res);
6180 mQueue.recycleEvent(qev);
6181 if (win != null && returnWhat == RETURN_PENDING_POINTER) {
6182 res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
6183 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006184 }
Christopher Tate2624fbc2009-12-11 12:11:31 -08006185 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006186
Christopher Tate2624fbc2009-12-11 12:11:31 -08006187 if (res != null && returnWhat == RETURN_PENDING_POINTER) {
6188 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08006189 dispatchPointerElsewhereLocked(win, win, res, res.getEventTime(), false);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006190 }
6191 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006192
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006193 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006194 }
6195
6196 void tickle() {
6197 synchronized (this) {
6198 notifyAll();
6199 }
6200 }
Romain Guy06882f82009-06-10 13:36:04 -07006201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006202 void handleNewWindowLocked(WindowState newWindow) {
6203 if (!newWindow.canReceiveKeys()) {
6204 return;
6205 }
6206 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006207 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006208 TAG, "New key dispatch window: win="
6209 + newWindow.mClient.asBinder()
6210 + ", last=" + mLastBinder
6211 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6212 + "), finished=" + mFinished + ", paused="
6213 + newWindow.mToken.paused);
6214
6215 // Displaying a window implicitly causes dispatching to
6216 // be unpaused. (This is to protect against bugs if someone
6217 // pauses dispatching but forgets to resume.)
6218 newWindow.mToken.paused = false;
6219
6220 mGotFirstWindow = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006221
6222 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006223 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006224 "New SYSTEM_ERROR window; resetting state");
6225 mLastWin = null;
6226 mLastBinder = null;
6227 mMotionTarget = null;
6228 mFinished = true;
6229 } else if (mLastWin != null) {
6230 // If the new window is above the window we are
6231 // waiting on, then stop waiting and let key dispatching
6232 // start on the new guy.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006233 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006234 TAG, "Last win layer=" + mLastWin.mLayer
6235 + ", new win layer=" + newWindow.mLayer);
6236 if (newWindow.mLayer >= mLastWin.mLayer) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006237 // The new window is above the old; finish pending input to the last
6238 // window and start directing it to the new one.
6239 mLastWin.mToken.paused = false;
Christopher Tate136b1f92010-02-11 17:51:24 -08006240 doFinishedKeyLocked(false); // does a notifyAll()
6241 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006242 }
6243 }
6244
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006245 // Now that we've put a new window state in place, make the event waiter
6246 // take notice and retarget its attentions.
6247 notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006248 }
6249 }
6250
6251 void pauseDispatchingLocked(WindowToken token) {
6252 synchronized (this)
6253 {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006254 if (DEBUG_INPUT) Slog.v(TAG, "Pausing WindowToken " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006255 token.paused = true;
6256
6257 /*
6258 if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) {
6259 mPaused = true;
6260 } else {
6261 if (mLastWin == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006262 Slog.i(TAG, "Key dispatching not paused: no last window.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006263 } else if (mFinished) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006264 Slog.i(TAG, "Key dispatching not paused: finished last key.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006265 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006266 Slog.i(TAG, "Key dispatching not paused: window in higher layer.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006267 }
6268 }
6269 */
6270 }
6271 }
6272
6273 void resumeDispatchingLocked(WindowToken token) {
6274 synchronized (this) {
6275 if (token.paused) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006276 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006277 TAG, "Resuming WindowToken " + token
6278 + ", last=" + mLastBinder
6279 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6280 + "), finished=" + mFinished + ", paused="
6281 + token.paused);
6282 token.paused = false;
6283 if (mLastWin != null && mLastWin.mToken == token && mFinished) {
Christopher Tate136b1f92010-02-11 17:51:24 -08006284 doFinishedKeyLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006285 } else {
6286 notifyAll();
6287 }
6288 }
6289 }
6290 }
6291
6292 void setEventDispatchingLocked(boolean enabled) {
6293 synchronized (this) {
6294 mEventDispatching = enabled;
6295 notifyAll();
6296 }
6297 }
Romain Guy06882f82009-06-10 13:36:04 -07006298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006299 void appSwitchComing() {
6300 synchronized (this) {
6301 // Don't wait for more than .5 seconds for app to finish
6302 // processing the pending events.
6303 long now = SystemClock.uptimeMillis() + 500;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006304 if (DEBUG_INPUT) Slog.v(TAG, "appSwitchComing: " + now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006305 if (mTimeToSwitch == 0 || now < mTimeToSwitch) {
6306 mTimeToSwitch = now;
6307 }
6308 notifyAll();
6309 }
6310 }
Romain Guy06882f82009-06-10 13:36:04 -07006311
Christopher Tate136b1f92010-02-11 17:51:24 -08006312 private final void doFinishedKeyLocked(boolean force) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006313 if (mLastWin != null) {
6314 releasePendingPointerLocked(mLastWin.mSession);
6315 releasePendingTrackballLocked(mLastWin.mSession);
6316 }
Romain Guy06882f82009-06-10 13:36:04 -07006317
Christopher Tate136b1f92010-02-11 17:51:24 -08006318 if (force || mLastWin == null || !mLastWin.mToken.paused
6319 || !mLastWin.isVisibleLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006320 // If the current window has been paused, we aren't -really-
6321 // finished... so let the waiters still wait.
6322 mLastWin = null;
6323 mLastBinder = null;
6324 }
6325 mFinished = true;
6326 notifyAll();
6327 }
6328 }
6329
6330 private class KeyQ extends KeyInputQueue
6331 implements KeyInputQueue.FilterCallback {
6332 PowerManager.WakeLock mHoldingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07006333
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006334 KeyQ() {
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07006335 super(mContext, WindowManagerService.this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006336 PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
6337 mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
6338 "KEEP_SCREEN_ON_FLAG");
6339 mHoldingScreen.setReferenceCounted(false);
6340 }
6341
6342 @Override
6343 boolean preprocessEvent(InputDevice device, RawInputEvent event) {
6344 if (mPolicy.preprocessInputEventTq(event)) {
6345 return true;
6346 }
Romain Guy06882f82009-06-10 13:36:04 -07006347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006348 switch (event.type) {
6349 case RawInputEvent.EV_KEY: {
6350 // XXX begin hack
6351 if (DEBUG) {
6352 if (event.keycode == KeyEvent.KEYCODE_G) {
6353 if (event.value != 0) {
6354 // G down
6355 mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
6356 }
6357 return false;
6358 }
6359 if (event.keycode == KeyEvent.KEYCODE_D) {
6360 if (event.value != 0) {
6361 //dump();
6362 }
6363 return false;
6364 }
6365 }
6366 // XXX end hack
Romain Guy06882f82009-06-10 13:36:04 -07006367
Charles Mendis322591c2009-10-29 11:06:59 -07006368 boolean screenIsOff = !mPowerManager.isScreenOn();
6369 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006370 int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
Romain Guy06882f82009-06-10 13:36:04 -07006371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006372 if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) {
6373 mPowerManager.goToSleep(event.when);
6374 }
6375
6376 if (screenIsOff) {
6377 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6378 }
6379 if (screenIsDim) {
6380 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6381 }
6382 if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
6383 mPowerManager.userActivity(event.when, false,
Michael Chane96440f2009-05-06 10:27:36 -07006384 LocalPowerManager.BUTTON_EVENT, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006385 }
Romain Guy06882f82009-06-10 13:36:04 -07006386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006387 if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
6388 if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) {
6389 filterQueue(this);
6390 mKeyWaiter.appSwitchComing();
6391 }
6392 return true;
6393 } else {
6394 return false;
6395 }
6396 }
Romain Guy06882f82009-06-10 13:36:04 -07006397
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006398 case RawInputEvent.EV_REL: {
Charles Mendis322591c2009-10-29 11:06:59 -07006399 boolean screenIsOff = !mPowerManager.isScreenOn();
6400 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006401 if (screenIsOff) {
6402 if (!mPolicy.isWakeRelMovementTq(event.deviceId,
6403 device.classes, event)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006404 //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006405 return false;
6406 }
6407 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6408 }
6409 if (screenIsDim) {
6410 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6411 }
6412 return true;
6413 }
Romain Guy06882f82009-06-10 13:36:04 -07006414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006415 case RawInputEvent.EV_ABS: {
Charles Mendis322591c2009-10-29 11:06:59 -07006416 boolean screenIsOff = !mPowerManager.isScreenOn();
6417 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006418 if (screenIsOff) {
6419 if (!mPolicy.isWakeAbsMovementTq(event.deviceId,
6420 device.classes, event)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006421 //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006422 return false;
6423 }
6424 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6425 }
6426 if (screenIsDim) {
6427 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6428 }
6429 return true;
6430 }
Romain Guy06882f82009-06-10 13:36:04 -07006431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006432 default:
6433 return true;
6434 }
6435 }
6436
6437 public int filterEvent(QueuedEvent ev) {
6438 switch (ev.classType) {
6439 case RawInputEvent.CLASS_KEYBOARD:
6440 KeyEvent ke = (KeyEvent)ev.event;
6441 if (mPolicy.isMovementKeyTi(ke.getKeyCode())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006442 Slog.w(TAG, "Dropping movement key during app switch: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006443 + ke.getKeyCode() + ", action=" + ke.getAction());
6444 return FILTER_REMOVE;
6445 }
6446 return FILTER_ABORT;
6447 default:
6448 return FILTER_KEEP;
6449 }
6450 }
Romain Guy06882f82009-06-10 13:36:04 -07006451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006452 /**
6453 * Must be called with the main window manager lock held.
6454 */
6455 void setHoldScreenLocked(boolean holding) {
6456 boolean state = mHoldingScreen.isHeld();
6457 if (holding != state) {
6458 if (holding) {
6459 mHoldingScreen.acquire();
6460 } else {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07006461 mPolicy.screenOnStoppedLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006462 mHoldingScreen.release();
6463 }
6464 }
6465 }
Michael Chan53071d62009-05-13 17:29:48 -07006466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467
6468 public boolean detectSafeMode() {
6469 mSafeMode = mPolicy.detectSafeMode();
6470 return mSafeMode;
6471 }
Romain Guy06882f82009-06-10 13:36:04 -07006472
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006473 public void systemReady() {
6474 mPolicy.systemReady();
6475 }
Romain Guy06882f82009-06-10 13:36:04 -07006476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006477 private final class InputDispatcherThread extends Thread {
6478 // Time to wait when there is nothing to do: 9999 seconds.
6479 static final int LONG_WAIT=9999*1000;
6480
6481 public InputDispatcherThread() {
6482 super("InputDispatcher");
6483 }
Romain Guy06882f82009-06-10 13:36:04 -07006484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006485 @Override
6486 public void run() {
6487 while (true) {
6488 try {
6489 process();
6490 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006491 Slog.e(TAG, "Exception in input dispatcher", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006492 }
6493 }
6494 }
Romain Guy06882f82009-06-10 13:36:04 -07006495
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006496 private void process() {
6497 android.os.Process.setThreadPriority(
6498 android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -07006499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006500 // The last key event we saw
6501 KeyEvent lastKey = null;
6502
6503 // Last keydown time for auto-repeating keys
6504 long lastKeyTime = SystemClock.uptimeMillis();
6505 long nextKeyTime = lastKeyTime+LONG_WAIT;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006506 long downTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006507
Romain Guy06882f82009-06-10 13:36:04 -07006508 // How many successive repeats we generated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006509 int keyRepeatCount = 0;
6510
6511 // Need to report that configuration has changed?
6512 boolean configChanged = false;
Romain Guy06882f82009-06-10 13:36:04 -07006513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006514 while (true) {
6515 long curTime = SystemClock.uptimeMillis();
6516
Joe Onorato8a9b2202010-02-26 18:56:32 -08006517 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006518 TAG, "Waiting for next key: now=" + curTime
6519 + ", repeat @ " + nextKeyTime);
6520
6521 // Retrieve next event, waiting only as long as the next
6522 // repeat timeout. If the configuration has changed, then
6523 // don't wait at all -- we'll report the change as soon as
6524 // we have processed all events.
6525 QueuedEvent ev = mQueue.getEvent(
6526 (int)((!configChanged && curTime < nextKeyTime)
6527 ? (nextKeyTime-curTime) : 0));
6528
Joe Onorato8a9b2202010-02-26 18:56:32 -08006529 if (DEBUG_INPUT && ev != null) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006530 TAG, "Event: type=" + ev.classType + " data=" + ev.event);
6531
Michael Chan53071d62009-05-13 17:29:48 -07006532 if (MEASURE_LATENCY) {
6533 lt.sample("2 got event ", System.nanoTime() - ev.whenNano);
6534 }
6535
Mike Lockwood3d0ea722009-10-21 22:58:29 -04006536 if (lastKey != null && !mPolicy.allowKeyRepeat()) {
6537 // cancel key repeat at the request of the policy.
6538 lastKey = null;
6539 downTime = 0;
6540 lastKeyTime = curTime;
6541 nextKeyTime = curTime + LONG_WAIT;
6542 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006543 try {
6544 if (ev != null) {
Michael Chan53071d62009-05-13 17:29:48 -07006545 curTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006546 int eventType;
6547 if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
6548 eventType = eventType((MotionEvent)ev.event);
6549 } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
6550 ev.classType == RawInputEvent.CLASS_TRACKBALL) {
6551 eventType = LocalPowerManager.BUTTON_EVENT;
6552 } else {
6553 eventType = LocalPowerManager.OTHER_EVENT;
6554 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07006555 try {
Michael Chan53071d62009-05-13 17:29:48 -07006556 if ((curTime - mLastBatteryStatsCallTime)
Michael Chane96440f2009-05-06 10:27:36 -07006557 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
Michael Chan53071d62009-05-13 17:29:48 -07006558 mLastBatteryStatsCallTime = curTime;
Michael Chane96440f2009-05-06 10:27:36 -07006559 mBatteryStats.noteInputEvent();
6560 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07006561 } catch (RemoteException e) {
6562 // Ignore
6563 }
Michael Chane10de972009-05-18 11:24:50 -07006564
Mike Lockwood5db42402009-11-30 14:51:51 -05006565 if (ev.classType == RawInputEvent.CLASS_CONFIGURATION_CHANGED) {
6566 // do not wake screen in this case
6567 } else if (eventType != TOUCH_EVENT
Michael Chane10de972009-05-18 11:24:50 -07006568 && eventType != LONG_TOUCH_EVENT
6569 && eventType != CHEEK_EVENT) {
6570 mPowerManager.userActivity(curTime, false,
6571 eventType, false);
6572 } else if (mLastTouchEventType != eventType
6573 || (curTime - mLastUserActivityCallTime)
6574 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
6575 mLastUserActivityCallTime = curTime;
6576 mLastTouchEventType = eventType;
6577 mPowerManager.userActivity(curTime, false,
6578 eventType, false);
6579 }
6580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006581 switch (ev.classType) {
6582 case RawInputEvent.CLASS_KEYBOARD:
6583 KeyEvent ke = (KeyEvent)ev.event;
6584 if (ke.isDown()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006585 lastKeyTime = curTime;
Kristian Dreher133bfdf2010-02-23 08:50:58 +01006586 if (lastKey != null &&
6587 ke.getKeyCode() == lastKey.getKeyCode()) {
6588 keyRepeatCount++;
6589 // Arbitrary long timeout to block
6590 // repeating here since we know that
6591 // the device driver takes care of it.
6592 nextKeyTime = lastKeyTime + LONG_WAIT;
The Android Open Source Project2a9ae012010-05-12 12:33:35 -07006593 if (DEBUG_INPUT) Slog.v(
Kristian Dreher133bfdf2010-02-23 08:50:58 +01006594 TAG, "Received repeated key down");
6595 } else {
6596 downTime = curTime;
6597 keyRepeatCount = 0;
6598 nextKeyTime = lastKeyTime
6599 + ViewConfiguration.getLongPressTimeout();
The Android Open Source Project2a9ae012010-05-12 12:33:35 -07006600 if (DEBUG_INPUT) Slog.v(
Kristian Dreher133bfdf2010-02-23 08:50:58 +01006601 TAG, "Received key down: first repeat @ "
6602 + nextKeyTime);
6603 }
6604 lastKey = ke;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006605 } else {
6606 lastKey = null;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006607 downTime = 0;
Kristian Dreher133bfdf2010-02-23 08:50:58 +01006608 keyRepeatCount = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006609 // Arbitrary long timeout.
6610 lastKeyTime = curTime;
6611 nextKeyTime = curTime + LONG_WAIT;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006612 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006613 TAG, "Received key up: ignore repeat @ "
6614 + nextKeyTime);
6615 }
Kristian Dreher133bfdf2010-02-23 08:50:58 +01006616 if (keyRepeatCount > 0) {
6617 dispatchKey(KeyEvent.changeTimeRepeat(ke,
6618 ke.getEventTime(), keyRepeatCount), 0, 0);
6619 } else {
6620 dispatchKey(ke, 0, 0);
6621 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006622 mQueue.recycleEvent(ev);
6623 break;
6624 case RawInputEvent.CLASS_TOUCHSCREEN:
Joe Onorato8a9b2202010-02-26 18:56:32 -08006625 //Slog.i(TAG, "Read next event " + ev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006626 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
6627 break;
6628 case RawInputEvent.CLASS_TRACKBALL:
6629 dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
6630 break;
6631 case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
6632 configChanged = true;
6633 break;
6634 default:
6635 mQueue.recycleEvent(ev);
6636 break;
6637 }
Romain Guy06882f82009-06-10 13:36:04 -07006638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006639 } else if (configChanged) {
6640 configChanged = false;
6641 sendNewConfiguration();
Romain Guy06882f82009-06-10 13:36:04 -07006642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006643 } else if (lastKey != null) {
6644 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07006645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006646 // Timeout occurred while key was down. If it is at or
6647 // past the key repeat time, dispatch the repeat.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006648 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006649 TAG, "Key timeout: repeat=" + nextKeyTime
6650 + ", now=" + curTime);
6651 if (curTime < nextKeyTime) {
6652 continue;
6653 }
Romain Guy06882f82009-06-10 13:36:04 -07006654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006655 lastKeyTime = nextKeyTime;
6656 nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY;
6657 keyRepeatCount++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006658 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006659 TAG, "Key repeat: count=" + keyRepeatCount
6660 + ", next @ " + nextKeyTime);
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006661 KeyEvent newEvent;
6662 if (downTime != 0 && (downTime
6663 + ViewConfiguration.getLongPressTimeout())
6664 <= curTime) {
6665 newEvent = KeyEvent.changeTimeRepeat(lastKey,
6666 curTime, keyRepeatCount,
6667 lastKey.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6668 downTime = 0;
6669 } else {
6670 newEvent = KeyEvent.changeTimeRepeat(lastKey,
6671 curTime, keyRepeatCount);
6672 }
6673 dispatchKey(newEvent, 0, 0);
Romain Guy06882f82009-06-10 13:36:04 -07006674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006675 } else {
6676 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07006677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006678 lastKeyTime = curTime;
6679 nextKeyTime = curTime + LONG_WAIT;
6680 }
Romain Guy06882f82009-06-10 13:36:04 -07006681
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006682 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006683 Slog.e(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006684 "Input thread received uncaught exception: " + e, e);
6685 }
6686 }
6687 }
6688 }
6689
6690 // -------------------------------------------------------------
6691 // Client Session State
6692 // -------------------------------------------------------------
6693
6694 private final class Session extends IWindowSession.Stub
6695 implements IBinder.DeathRecipient {
6696 final IInputMethodClient mClient;
6697 final IInputContext mInputContext;
6698 final int mUid;
6699 final int mPid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006700 final String mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006701 SurfaceSession mSurfaceSession;
6702 int mNumWindow = 0;
6703 boolean mClientDead = false;
Romain Guy06882f82009-06-10 13:36:04 -07006704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006705 /**
6706 * Current pointer move event being dispatched to client window... must
6707 * hold key lock to access.
6708 */
6709 QueuedEvent mPendingPointerMove;
6710 WindowState mPendingPointerWindow;
Romain Guy06882f82009-06-10 13:36:04 -07006711
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006712 /**
6713 * Current trackball move event being dispatched to client window... must
6714 * hold key lock to access.
6715 */
6716 QueuedEvent mPendingTrackballMove;
6717 WindowState mPendingTrackballWindow;
6718
6719 public Session(IInputMethodClient client, IInputContext inputContext) {
6720 mClient = client;
6721 mInputContext = inputContext;
6722 mUid = Binder.getCallingUid();
6723 mPid = Binder.getCallingPid();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006724 StringBuilder sb = new StringBuilder();
6725 sb.append("Session{");
6726 sb.append(Integer.toHexString(System.identityHashCode(this)));
6727 sb.append(" uid ");
6728 sb.append(mUid);
6729 sb.append("}");
6730 mStringName = sb.toString();
Romain Guy06882f82009-06-10 13:36:04 -07006731
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006732 synchronized (mWindowMap) {
6733 if (mInputMethodManager == null && mHaveInputMethods) {
6734 IBinder b = ServiceManager.getService(
6735 Context.INPUT_METHOD_SERVICE);
6736 mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
6737 }
6738 }
6739 long ident = Binder.clearCallingIdentity();
6740 try {
6741 // Note: it is safe to call in to the input method manager
6742 // here because we are not holding our lock.
6743 if (mInputMethodManager != null) {
6744 mInputMethodManager.addClient(client, inputContext,
6745 mUid, mPid);
6746 } else {
6747 client.setUsingInputMethod(false);
6748 }
6749 client.asBinder().linkToDeath(this, 0);
6750 } catch (RemoteException e) {
6751 // The caller has died, so we can just forget about this.
6752 try {
6753 if (mInputMethodManager != null) {
6754 mInputMethodManager.removeClient(client);
6755 }
6756 } catch (RemoteException ee) {
6757 }
6758 } finally {
6759 Binder.restoreCallingIdentity(ident);
6760 }
6761 }
Romain Guy06882f82009-06-10 13:36:04 -07006762
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006763 @Override
6764 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
6765 throws RemoteException {
6766 try {
6767 return super.onTransact(code, data, reply, flags);
6768 } catch (RuntimeException e) {
6769 // Log all 'real' exceptions thrown to the caller
6770 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006771 Slog.e(TAG, "Window Session Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006772 }
6773 throw e;
6774 }
6775 }
6776
6777 public void binderDied() {
6778 // Note: it is safe to call in to the input method manager
6779 // here because we are not holding our lock.
6780 try {
6781 if (mInputMethodManager != null) {
6782 mInputMethodManager.removeClient(mClient);
6783 }
6784 } catch (RemoteException e) {
6785 }
6786 synchronized(mWindowMap) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07006787 mClient.asBinder().unlinkToDeath(this, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006788 mClientDead = true;
6789 killSessionLocked();
6790 }
6791 }
6792
6793 public int add(IWindow window, WindowManager.LayoutParams attrs,
6794 int viewVisibility, Rect outContentInsets) {
6795 return addWindow(this, window, attrs, viewVisibility, outContentInsets);
6796 }
Romain Guy06882f82009-06-10 13:36:04 -07006797
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006798 public void remove(IWindow window) {
6799 removeWindow(this, window);
6800 }
Romain Guy06882f82009-06-10 13:36:04 -07006801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006802 public int relayout(IWindow window, WindowManager.LayoutParams attrs,
6803 int requestedWidth, int requestedHeight, int viewFlags,
6804 boolean insetsPending, Rect outFrame, Rect outContentInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07006805 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006806 return relayoutWindow(this, window, attrs,
6807 requestedWidth, requestedHeight, viewFlags, insetsPending,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07006808 outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006809 }
Romain Guy06882f82009-06-10 13:36:04 -07006810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006811 public void setTransparentRegion(IWindow window, Region region) {
6812 setTransparentRegionWindow(this, window, region);
6813 }
Romain Guy06882f82009-06-10 13:36:04 -07006814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006815 public void setInsets(IWindow window, int touchableInsets,
6816 Rect contentInsets, Rect visibleInsets) {
6817 setInsetsWindow(this, window, touchableInsets, contentInsets,
6818 visibleInsets);
6819 }
Romain Guy06882f82009-06-10 13:36:04 -07006820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006821 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
6822 getWindowDisplayFrame(this, window, outDisplayFrame);
6823 }
Romain Guy06882f82009-06-10 13:36:04 -07006824
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006825 public void finishDrawing(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006826 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006827 TAG, "IWindow finishDrawing called for " + window);
6828 finishDrawingWindow(this, window);
6829 }
6830
6831 public void finishKey(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006832 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006833 TAG, "IWindow finishKey called for " + window);
6834 mKeyWaiter.finishedKey(this, window, false,
6835 KeyWaiter.RETURN_NOTHING);
6836 }
6837
6838 public MotionEvent getPendingPointerMove(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006839 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006840 TAG, "IWindow getPendingMotionEvent called for " + window);
6841 return mKeyWaiter.finishedKey(this, window, false,
6842 KeyWaiter.RETURN_PENDING_POINTER);
6843 }
Romain Guy06882f82009-06-10 13:36:04 -07006844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006845 public MotionEvent getPendingTrackballMove(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006846 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006847 TAG, "IWindow getPendingMotionEvent called for " + window);
6848 return mKeyWaiter.finishedKey(this, window, false,
6849 KeyWaiter.RETURN_PENDING_TRACKBALL);
6850 }
6851
6852 public void setInTouchMode(boolean mode) {
6853 synchronized(mWindowMap) {
6854 mInTouchMode = mode;
6855 }
6856 }
6857
6858 public boolean getInTouchMode() {
6859 synchronized(mWindowMap) {
6860 return mInTouchMode;
6861 }
6862 }
6863
6864 public boolean performHapticFeedback(IWindow window, int effectId,
6865 boolean always) {
6866 synchronized(mWindowMap) {
6867 long ident = Binder.clearCallingIdentity();
6868 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07006869 return mPolicy.performHapticFeedbackLw(
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006870 windowForClientLocked(this, window, true),
6871 effectId, always);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006872 } finally {
6873 Binder.restoreCallingIdentity(ident);
6874 }
6875 }
6876 }
Romain Guy06882f82009-06-10 13:36:04 -07006877
Marco Nelissenbf6956b2009-11-09 15:21:13 -08006878 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006879 synchronized(mWindowMap) {
6880 long ident = Binder.clearCallingIdentity();
6881 try {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006882 setWindowWallpaperPositionLocked(
6883 windowForClientLocked(this, window, true),
Marco Nelissenbf6956b2009-11-09 15:21:13 -08006884 x, y, xStep, yStep);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006885 } finally {
6886 Binder.restoreCallingIdentity(ident);
6887 }
6888 }
6889 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006890
Dianne Hackborn19382ac2009-09-11 21:13:37 -07006891 public void wallpaperOffsetsComplete(IBinder window) {
6892 WindowManagerService.this.wallpaperOffsetsComplete(window);
6893 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006894
Dianne Hackborn75804932009-10-20 20:15:20 -07006895 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
6896 int z, Bundle extras, boolean sync) {
6897 synchronized(mWindowMap) {
6898 long ident = Binder.clearCallingIdentity();
6899 try {
6900 return sendWindowWallpaperCommandLocked(
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006901 windowForClientLocked(this, window, true),
Dianne Hackborn75804932009-10-20 20:15:20 -07006902 action, x, y, z, extras, sync);
6903 } finally {
6904 Binder.restoreCallingIdentity(ident);
6905 }
6906 }
6907 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006908
Dianne Hackborn75804932009-10-20 20:15:20 -07006909 public void wallpaperCommandComplete(IBinder window, Bundle result) {
6910 WindowManagerService.this.wallpaperCommandComplete(window, result);
6911 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006913 void windowAddedLocked() {
6914 if (mSurfaceSession == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006915 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006916 TAG, "First window added to " + this + ", creating SurfaceSession");
6917 mSurfaceSession = new SurfaceSession();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006918 if (SHOW_TRANSACTIONS) Slog.i(
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07006919 TAG, " NEW SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006920 mSessions.add(this);
6921 }
6922 mNumWindow++;
6923 }
6924
6925 void windowRemovedLocked() {
6926 mNumWindow--;
6927 killSessionLocked();
6928 }
Romain Guy06882f82009-06-10 13:36:04 -07006929
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006930 void killSessionLocked() {
6931 if (mNumWindow <= 0 && mClientDead) {
6932 mSessions.remove(this);
6933 if (mSurfaceSession != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006934 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006935 TAG, "Last window removed from " + this
6936 + ", destroying " + mSurfaceSession);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006937 if (SHOW_TRANSACTIONS) Slog.i(
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07006938 TAG, " KILL SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006939 try {
6940 mSurfaceSession.kill();
6941 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006942 Slog.w(TAG, "Exception thrown when killing surface session "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006943 + mSurfaceSession + " in session " + this
6944 + ": " + e.toString());
6945 }
6946 mSurfaceSession = null;
6947 }
6948 }
6949 }
Romain Guy06882f82009-06-10 13:36:04 -07006950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006951 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006952 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
6953 pw.print(" mClientDead="); pw.print(mClientDead);
6954 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
6955 if (mPendingPointerWindow != null || mPendingPointerMove != null) {
6956 pw.print(prefix);
6957 pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
6958 pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
6959 }
6960 if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
6961 pw.print(prefix);
6962 pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
6963 pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
6964 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006965 }
6966
6967 @Override
6968 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006969 return mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006970 }
6971 }
6972
6973 // -------------------------------------------------------------
6974 // Client Window State
6975 // -------------------------------------------------------------
6976
6977 private final class WindowState implements WindowManagerPolicy.WindowState {
6978 final Session mSession;
6979 final IWindow mClient;
6980 WindowToken mToken;
The Android Open Source Project10592532009-03-18 17:39:46 -07006981 WindowToken mRootToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006982 AppWindowToken mAppToken;
6983 AppWindowToken mTargetAppToken;
6984 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
6985 final DeathRecipient mDeathRecipient;
6986 final WindowState mAttachedWindow;
6987 final ArrayList mChildWindows = new ArrayList();
6988 final int mBaseLayer;
6989 final int mSubLayer;
6990 final boolean mLayoutAttached;
6991 final boolean mIsImWindow;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006992 final boolean mIsWallpaper;
6993 final boolean mIsFloatingLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006994 int mViewVisibility;
6995 boolean mPolicyVisibility = true;
6996 boolean mPolicyVisibilityAfterAnim = true;
6997 boolean mAppFreezing;
6998 Surface mSurface;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07006999 boolean mReportDestroySurface;
7000 boolean mSurfacePendingDestroy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007001 boolean mAttachedHidden; // is our parent window hidden?
7002 boolean mLastHidden; // was this window last hidden?
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007003 boolean mWallpaperVisible; // for wallpaper, what was last vis report?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007004 int mRequestedWidth;
7005 int mRequestedHeight;
7006 int mLastRequestedWidth;
7007 int mLastRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007008 int mLayer;
7009 int mAnimLayer;
7010 int mLastLayer;
7011 boolean mHaveFrame;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007012 boolean mObscured;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07007013 boolean mTurnOnScreen;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007014
7015 WindowState mNextOutsideTouch;
Romain Guy06882f82009-06-10 13:36:04 -07007016
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007017 int mLayoutSeq = -1;
7018
7019 Configuration mConfiguration = null;
7020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007021 // Actual frame shown on-screen (may be modified by animation)
7022 final Rect mShownFrame = new Rect();
7023 final Rect mLastShownFrame = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007025 /**
Dianne Hackbornac3587d2010-03-11 11:12:11 -08007026 * Set when we have changed the size of the surface, to know that
7027 * we must tell them application to resize (and thus redraw itself).
7028 */
7029 boolean mSurfaceResized;
7030
7031 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007032 * Insets that determine the actually visible area
7033 */
7034 final Rect mVisibleInsets = new Rect();
7035 final Rect mLastVisibleInsets = new Rect();
7036 boolean mVisibleInsetsChanged;
7037
7038 /**
7039 * Insets that are covered by system windows
7040 */
7041 final Rect mContentInsets = new Rect();
7042 final Rect mLastContentInsets = new Rect();
7043 boolean mContentInsetsChanged;
7044
7045 /**
7046 * Set to true if we are waiting for this window to receive its
7047 * given internal insets before laying out other windows based on it.
7048 */
7049 boolean mGivenInsetsPending;
Romain Guy06882f82009-06-10 13:36:04 -07007050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007051 /**
7052 * These are the content insets that were given during layout for
7053 * this window, to be applied to windows behind it.
7054 */
7055 final Rect mGivenContentInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007057 /**
7058 * These are the visible insets that were given during layout for
7059 * this window, to be applied to windows behind it.
7060 */
7061 final Rect mGivenVisibleInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007063 /**
7064 * Flag indicating whether the touchable region should be adjusted by
7065 * the visible insets; if false the area outside the visible insets is
7066 * NOT touchable, so we must use those to adjust the frame during hit
7067 * tests.
7068 */
7069 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
Romain Guy06882f82009-06-10 13:36:04 -07007070
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007071 // Current transformation being applied.
7072 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
7073 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
7074 float mHScale=1, mVScale=1;
7075 float mLastHScale=1, mLastVScale=1;
7076 final Matrix mTmpMatrix = new Matrix();
7077
7078 // "Real" frame that the application sees.
7079 final Rect mFrame = new Rect();
7080 final Rect mLastFrame = new Rect();
7081
7082 final Rect mContainingFrame = new Rect();
7083 final Rect mDisplayFrame = new Rect();
7084 final Rect mContentFrame = new Rect();
7085 final Rect mVisibleFrame = new Rect();
7086
7087 float mShownAlpha = 1;
7088 float mAlpha = 1;
7089 float mLastAlpha = 1;
7090
7091 // Set to true if, when the window gets displayed, it should perform
7092 // an enter animation.
7093 boolean mEnterAnimationPending;
7094
7095 // Currently running animation.
7096 boolean mAnimating;
7097 boolean mLocalAnimating;
7098 Animation mAnimation;
7099 boolean mAnimationIsEntrance;
7100 boolean mHasTransformation;
7101 boolean mHasLocalTransformation;
7102 final Transformation mTransformation = new Transformation();
7103
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007104 // If a window showing a wallpaper: the requested offset for the
7105 // wallpaper; if a wallpaper window: the currently applied offset.
7106 float mWallpaperX = -1;
7107 float mWallpaperY = -1;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08007108
7109 // If a window showing a wallpaper: what fraction of the offset
7110 // range corresponds to a full virtual screen.
7111 float mWallpaperXStep = -1;
7112 float mWallpaperYStep = -1;
7113
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007114 // Wallpaper windows: pixels offset based on above variables.
7115 int mXOffset;
7116 int mYOffset;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007118 // This is set after IWindowSession.relayout() has been called at
7119 // least once for the window. It allows us to detect the situation
7120 // where we don't yet have a surface, but should have one soon, so
7121 // we can give the window focus before waiting for the relayout.
7122 boolean mRelayoutCalled;
Romain Guy06882f82009-06-10 13:36:04 -07007123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007124 // This is set after the Surface has been created but before the
7125 // window has been drawn. During this time the surface is hidden.
7126 boolean mDrawPending;
7127
7128 // This is set after the window has finished drawing for the first
7129 // time but before its surface is shown. The surface will be
7130 // displayed when the next layout is run.
7131 boolean mCommitDrawPending;
7132
7133 // This is set during the time after the window's drawing has been
7134 // committed, and before its surface is actually shown. It is used
7135 // to delay showing the surface until all windows in a token are ready
7136 // to be shown.
7137 boolean mReadyToShow;
Romain Guy06882f82009-06-10 13:36:04 -07007138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007139 // Set when the window has been shown in the screen the first time.
7140 boolean mHasDrawn;
7141
7142 // Currently running an exit animation?
7143 boolean mExiting;
7144
7145 // Currently on the mDestroySurface list?
7146 boolean mDestroying;
Romain Guy06882f82009-06-10 13:36:04 -07007147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007148 // Completely remove from window manager after exit animation?
7149 boolean mRemoveOnExit;
7150
7151 // Set when the orientation is changing and this window has not yet
7152 // been updated for the new orientation.
7153 boolean mOrientationChanging;
Romain Guy06882f82009-06-10 13:36:04 -07007154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007155 // Is this window now (or just being) removed?
7156 boolean mRemoved;
Romain Guy06882f82009-06-10 13:36:04 -07007157
Dianne Hackborn16064f92010-03-25 00:47:24 -07007158 // For debugging, this is the last information given to the surface flinger.
7159 boolean mSurfaceShown;
7160 int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
7161 int mSurfaceLayer;
7162 float mSurfaceAlpha;
7163
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007164 WindowState(Session s, IWindow c, WindowToken token,
7165 WindowState attachedWindow, WindowManager.LayoutParams a,
7166 int viewVisibility) {
7167 mSession = s;
7168 mClient = c;
7169 mToken = token;
7170 mAttrs.copyFrom(a);
7171 mViewVisibility = viewVisibility;
7172 DeathRecipient deathRecipient = new DeathRecipient();
7173 mAlpha = a.alpha;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007174 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007175 TAG, "Window " + this + " client=" + c.asBinder()
7176 + " token=" + token + " (" + mAttrs.token + ")");
7177 try {
7178 c.asBinder().linkToDeath(deathRecipient, 0);
7179 } catch (RemoteException e) {
7180 mDeathRecipient = null;
7181 mAttachedWindow = null;
7182 mLayoutAttached = false;
7183 mIsImWindow = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007184 mIsWallpaper = false;
7185 mIsFloatingLayer = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007186 mBaseLayer = 0;
7187 mSubLayer = 0;
7188 return;
7189 }
7190 mDeathRecipient = deathRecipient;
Romain Guy06882f82009-06-10 13:36:04 -07007191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007192 if ((mAttrs.type >= FIRST_SUB_WINDOW &&
7193 mAttrs.type <= LAST_SUB_WINDOW)) {
7194 // The multiplier here is to reserve space for multiple
7195 // windows in the same type layer.
7196 mBaseLayer = mPolicy.windowTypeToLayerLw(
7197 attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
7198 + TYPE_LAYER_OFFSET;
7199 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
7200 mAttachedWindow = attachedWindow;
7201 mAttachedWindow.mChildWindows.add(this);
7202 mLayoutAttached = mAttrs.type !=
7203 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
7204 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
7205 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007206 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
7207 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007208 } else {
7209 // The multiplier here is to reserve space for multiple
7210 // windows in the same type layer.
7211 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
7212 * TYPE_LAYER_MULTIPLIER
7213 + TYPE_LAYER_OFFSET;
7214 mSubLayer = 0;
7215 mAttachedWindow = null;
7216 mLayoutAttached = false;
7217 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
7218 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007219 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
7220 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007221 }
7222
7223 WindowState appWin = this;
7224 while (appWin.mAttachedWindow != null) {
7225 appWin = mAttachedWindow;
7226 }
7227 WindowToken appToken = appWin.mToken;
7228 while (appToken.appWindowToken == null) {
7229 WindowToken parent = mTokenMap.get(appToken.token);
7230 if (parent == null || appToken == parent) {
7231 break;
7232 }
7233 appToken = parent;
7234 }
The Android Open Source Project10592532009-03-18 17:39:46 -07007235 mRootToken = appToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007236 mAppToken = appToken.appWindowToken;
7237
7238 mSurface = null;
7239 mRequestedWidth = 0;
7240 mRequestedHeight = 0;
7241 mLastRequestedWidth = 0;
7242 mLastRequestedHeight = 0;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007243 mXOffset = 0;
7244 mYOffset = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007245 mLayer = 0;
7246 mAnimLayer = 0;
7247 mLastLayer = 0;
7248 }
7249
7250 void attach() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007251 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007252 TAG, "Attaching " + this + " token=" + mToken
7253 + ", list=" + mToken.windows);
7254 mSession.windowAddedLocked();
7255 }
7256
7257 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
7258 mHaveFrame = true;
7259
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007260 final Rect container = mContainingFrame;
7261 container.set(pf);
7262
7263 final Rect display = mDisplayFrame;
7264 display.set(df);
7265
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07007266 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007267 container.intersect(mCompatibleScreenFrame);
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007268 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
7269 display.intersect(mCompatibleScreenFrame);
7270 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007271 }
7272
7273 final int pw = container.right - container.left;
7274 final int ph = container.bottom - container.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007275
7276 int w,h;
7277 if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
7278 w = mAttrs.width < 0 ? pw : mAttrs.width;
7279 h = mAttrs.height< 0 ? ph : mAttrs.height;
7280 } else {
Romain Guy980a9382010-01-08 15:06:28 -08007281 w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
7282 h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007283 }
Romain Guy06882f82009-06-10 13:36:04 -07007284
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007285 final Rect content = mContentFrame;
7286 content.set(cf);
Romain Guy06882f82009-06-10 13:36:04 -07007287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007288 final Rect visible = mVisibleFrame;
7289 visible.set(vf);
Romain Guy06882f82009-06-10 13:36:04 -07007290
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007291 final Rect frame = mFrame;
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07007292 final int fw = frame.width();
7293 final int fh = frame.height();
Romain Guy06882f82009-06-10 13:36:04 -07007294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007295 //System.out.println("In: w=" + w + " h=" + h + " container=" +
7296 // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
7297
7298 Gravity.apply(mAttrs.gravity, w, h, container,
7299 (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
7300 (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
7301
7302 //System.out.println("Out: " + mFrame);
7303
7304 // Now make sure the window fits in the overall display.
7305 Gravity.applyDisplay(mAttrs.gravity, df, frame);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007307 // Make sure the content and visible frames are inside of the
7308 // final window frame.
7309 if (content.left < frame.left) content.left = frame.left;
7310 if (content.top < frame.top) content.top = frame.top;
7311 if (content.right > frame.right) content.right = frame.right;
7312 if (content.bottom > frame.bottom) content.bottom = frame.bottom;
7313 if (visible.left < frame.left) visible.left = frame.left;
7314 if (visible.top < frame.top) visible.top = frame.top;
7315 if (visible.right > frame.right) visible.right = frame.right;
7316 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007317
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007318 final Rect contentInsets = mContentInsets;
7319 contentInsets.left = content.left-frame.left;
7320 contentInsets.top = content.top-frame.top;
7321 contentInsets.right = frame.right-content.right;
7322 contentInsets.bottom = frame.bottom-content.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 final Rect visibleInsets = mVisibleInsets;
7325 visibleInsets.left = visible.left-frame.left;
7326 visibleInsets.top = visible.top-frame.top;
7327 visibleInsets.right = frame.right-visible.right;
7328 visibleInsets.bottom = frame.bottom-visible.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007329
Dianne Hackborn284ac932009-08-28 10:34:25 -07007330 if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
7331 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07007332 mDisplay.getHeight(), false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07007333 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007334
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007335 if (localLOGV) {
7336 //if ("com.google.android.youtube".equals(mAttrs.packageName)
7337 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007338 Slog.v(TAG, "Resolving (mRequestedWidth="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007339 + mRequestedWidth + ", mRequestedheight="
7340 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
7341 + "): frame=" + mFrame.toShortString()
7342 + " ci=" + contentInsets.toShortString()
7343 + " vi=" + visibleInsets.toShortString());
7344 //}
7345 }
7346 }
Romain Guy06882f82009-06-10 13:36:04 -07007347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007348 public Rect getFrameLw() {
7349 return mFrame;
7350 }
7351
7352 public Rect getShownFrameLw() {
7353 return mShownFrame;
7354 }
7355
7356 public Rect getDisplayFrameLw() {
7357 return mDisplayFrame;
7358 }
7359
7360 public Rect getContentFrameLw() {
7361 return mContentFrame;
7362 }
7363
7364 public Rect getVisibleFrameLw() {
7365 return mVisibleFrame;
7366 }
7367
7368 public boolean getGivenInsetsPendingLw() {
7369 return mGivenInsetsPending;
7370 }
7371
7372 public Rect getGivenContentInsetsLw() {
7373 return mGivenContentInsets;
7374 }
Romain Guy06882f82009-06-10 13:36:04 -07007375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007376 public Rect getGivenVisibleInsetsLw() {
7377 return mGivenVisibleInsets;
7378 }
Romain Guy06882f82009-06-10 13:36:04 -07007379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007380 public WindowManager.LayoutParams getAttrs() {
7381 return mAttrs;
7382 }
7383
7384 public int getSurfaceLayer() {
7385 return mLayer;
7386 }
Romain Guy06882f82009-06-10 13:36:04 -07007387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 public IApplicationToken getAppToken() {
7389 return mAppToken != null ? mAppToken.appToken : null;
7390 }
7391
7392 public boolean hasAppShownWindows() {
7393 return mAppToken != null ? mAppToken.firstWindowDrawn : false;
7394 }
7395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007396 public void setAnimation(Animation anim) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007397 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007398 TAG, "Setting animation in " + this + ": " + anim);
7399 mAnimating = false;
7400 mLocalAnimating = false;
7401 mAnimation = anim;
7402 mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
7403 mAnimation.scaleCurrentDuration(mWindowAnimationScale);
7404 }
7405
7406 public void clearAnimation() {
7407 if (mAnimation != null) {
7408 mAnimating = true;
7409 mLocalAnimating = false;
7410 mAnimation = null;
7411 }
7412 }
Romain Guy06882f82009-06-10 13:36:04 -07007413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007414 Surface createSurfaceLocked() {
7415 if (mSurface == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007416 mReportDestroySurface = false;
7417 mSurfacePendingDestroy = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007418 mDrawPending = true;
7419 mCommitDrawPending = false;
7420 mReadyToShow = false;
7421 if (mAppToken != null) {
7422 mAppToken.allDrawn = false;
7423 }
7424
7425 int flags = 0;
Mathias Agopian317a6282009-08-13 17:29:02 -07007426 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 flags |= Surface.PUSH_BUFFERS;
7428 }
7429
7430 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
7431 flags |= Surface.SECURE;
7432 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007433 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434 TAG, "Creating surface in session "
7435 + mSession.mSurfaceSession + " window " + this
7436 + " w=" + mFrame.width()
7437 + " h=" + mFrame.height() + " format="
7438 + mAttrs.format + " flags=" + flags);
7439
7440 int w = mFrame.width();
7441 int h = mFrame.height();
7442 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
7443 // for a scaled surface, we always want the requested
7444 // size.
7445 w = mRequestedWidth;
7446 h = mRequestedHeight;
7447 }
7448
Romain Guy9825ec62009-10-01 00:58:09 -07007449 // Something is wrong and SurfaceFlinger will not like this,
7450 // try to revert to sane values
7451 if (w <= 0) w = 1;
7452 if (h <= 0) h = 1;
7453
Dianne Hackborn16064f92010-03-25 00:47:24 -07007454 mSurfaceShown = false;
7455 mSurfaceLayer = 0;
7456 mSurfaceAlpha = 1;
7457 mSurfaceX = 0;
7458 mSurfaceY = 0;
7459 mSurfaceW = w;
7460 mSurfaceH = h;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007461 try {
7462 mSurface = new Surface(
Romain Guy06882f82009-06-10 13:36:04 -07007463 mSession.mSurfaceSession, mSession.mPid,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -08007464 mAttrs.getTitle().toString(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007465 0, w, h, mAttrs.format, flags);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007466 if (SHOW_TRANSACTIONS) Slog.i(TAG, " CREATE SURFACE "
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007467 + mSurface + " IN SESSION "
7468 + mSession.mSurfaceSession
7469 + ": pid=" + mSession.mPid + " format="
7470 + mAttrs.format + " flags=0x"
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007471 + Integer.toHexString(flags)
7472 + " / " + this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007473 } catch (Surface.OutOfResourcesException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007474 Slog.w(TAG, "OutOfResourcesException creating surface");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007475 reclaimSomeSurfaceMemoryLocked(this, "create");
7476 return null;
7477 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007478 Slog.e(TAG, "Exception creating surface", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007479 return null;
7480 }
Romain Guy06882f82009-06-10 13:36:04 -07007481
Joe Onorato8a9b2202010-02-26 18:56:32 -08007482 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007483 TAG, "Got surface: " + mSurface
7484 + ", set left=" + mFrame.left + " top=" + mFrame.top
7485 + ", animLayer=" + mAnimLayer);
7486 if (SHOW_TRANSACTIONS) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007487 Slog.i(TAG, ">>> OPEN TRANSACTION");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007488 if (SHOW_TRANSACTIONS) logSurface(this,
7489 "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
7490 mFrame.width() + "x" + mFrame.height() + "), layer=" +
7491 mAnimLayer + " HIDE", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007492 }
7493 Surface.openTransaction();
7494 try {
7495 try {
Dianne Hackborn16064f92010-03-25 00:47:24 -07007496 mSurfaceX = mFrame.left + mXOffset;
Dianne Hackborn529bef62010-03-25 11:48:43 -07007497 mSurfaceY = mFrame.top + mYOffset;
Dianne Hackborn16064f92010-03-25 00:47:24 -07007498 mSurface.setPosition(mSurfaceX, mSurfaceY);
7499 mSurfaceLayer = mAnimLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007500 mSurface.setLayer(mAnimLayer);
Dianne Hackborn16064f92010-03-25 00:47:24 -07007501 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007502 mSurface.hide();
7503 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007504 if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007505 mSurface.setFlags(Surface.SURFACE_DITHER,
7506 Surface.SURFACE_DITHER);
7507 }
7508 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007509 Slog.w(TAG, "Error creating surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007510 reclaimSomeSurfaceMemoryLocked(this, "create-init");
7511 }
7512 mLastHidden = true;
7513 } finally {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007514 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007515 Surface.closeTransaction();
7516 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007517 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007518 TAG, "Created surface " + this);
7519 }
7520 return mSurface;
7521 }
Romain Guy06882f82009-06-10 13:36:04 -07007522
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007523 void destroySurfaceLocked() {
7524 // Window is no longer on-screen, so can no longer receive
7525 // key events... if we were waiting for it to finish
7526 // handling a key event, the wait is over!
7527 mKeyWaiter.finishedKey(mSession, mClient, true,
7528 KeyWaiter.RETURN_NOTHING);
7529 mKeyWaiter.releasePendingPointerLocked(mSession);
7530 mKeyWaiter.releasePendingTrackballLocked(mSession);
7531
7532 if (mAppToken != null && this == mAppToken.startingWindow) {
7533 mAppToken.startingDisplayed = false;
7534 }
Romain Guy06882f82009-06-10 13:36:04 -07007535
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007536 if (mSurface != null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007537 mDrawPending = false;
7538 mCommitDrawPending = false;
7539 mReadyToShow = false;
7540
7541 int i = mChildWindows.size();
7542 while (i > 0) {
7543 i--;
7544 WindowState c = (WindowState)mChildWindows.get(i);
7545 c.mAttachedHidden = true;
7546 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007547
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007548 if (mReportDestroySurface) {
7549 mReportDestroySurface = false;
7550 mSurfacePendingDestroy = true;
7551 try {
7552 mClient.dispatchGetNewSurface();
7553 // We'll really destroy on the next time around.
7554 return;
7555 } catch (RemoteException e) {
7556 }
7557 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007559 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007560 if (DEBUG_VISIBILITY) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007561 RuntimeException e = null;
7562 if (!HIDE_STACK_CRAWLS) {
7563 e = new RuntimeException();
7564 e.fillInStackTrace();
7565 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007566 Slog.w(TAG, "Window " + this + " destroying surface "
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007567 + mSurface + ", session " + mSession, e);
7568 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007569 if (SHOW_TRANSACTIONS) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007570 RuntimeException e = null;
7571 if (!HIDE_STACK_CRAWLS) {
7572 e = new RuntimeException();
7573 e.fillInStackTrace();
7574 }
7575 if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007576 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007577 mSurface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007578 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007579 Slog.w(TAG, "Exception thrown when destroying Window " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007580 + " surface " + mSurface + " session " + mSession
7581 + ": " + e.toString());
7582 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007583
Dianne Hackborn16064f92010-03-25 00:47:24 -07007584 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007585 mSurface = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007586 }
7587 }
7588
7589 boolean finishDrawingLocked() {
7590 if (mDrawPending) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007591 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007592 TAG, "finishDrawingLocked: " + mSurface);
7593 mCommitDrawPending = true;
7594 mDrawPending = false;
7595 return true;
7596 }
7597 return false;
7598 }
7599
7600 // This must be called while inside a transaction.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007601 boolean commitFinishDrawingLocked(long currentTime) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007602 //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 if (!mCommitDrawPending) {
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007604 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007605 }
7606 mCommitDrawPending = false;
7607 mReadyToShow = true;
7608 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
7609 final AppWindowToken atoken = mAppToken;
7610 if (atoken == null || atoken.allDrawn || starting) {
7611 performShowLocked();
7612 }
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007613 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007614 }
7615
7616 // This must be called while inside a transaction.
7617 boolean performShowLocked() {
7618 if (DEBUG_VISIBILITY) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007619 RuntimeException e = null;
7620 if (!HIDE_STACK_CRAWLS) {
7621 e = new RuntimeException();
7622 e.fillInStackTrace();
7623 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007624 Slog.v(TAG, "performShow on " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007625 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
7626 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
7627 }
7628 if (mReadyToShow && isReadyForDisplay()) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007629 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this,
7630 "SHOW (performShowLocked)", null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007631 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007632 + " during animation: policyVis=" + mPolicyVisibility
7633 + " attHidden=" + mAttachedHidden
7634 + " tok.hiddenRequested="
7635 + (mAppToken != null ? mAppToken.hiddenRequested : false)
Dianne Hackborn248b1882009-09-16 16:46:44 -07007636 + " tok.hidden="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007637 + (mAppToken != null ? mAppToken.hidden : false)
7638 + " animating=" + mAnimating
7639 + " tok animating="
7640 + (mAppToken != null ? mAppToken.animating : false));
7641 if (!showSurfaceRobustlyLocked(this)) {
7642 return false;
7643 }
7644 mLastAlpha = -1;
7645 mHasDrawn = true;
7646 mLastHidden = false;
7647 mReadyToShow = false;
7648 enableScreenIfNeededLocked();
7649
7650 applyEnterAnimationLocked(this);
Romain Guy06882f82009-06-10 13:36:04 -07007651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007652 int i = mChildWindows.size();
7653 while (i > 0) {
7654 i--;
7655 WindowState c = (WindowState)mChildWindows.get(i);
Dianne Hackbornf09c1a22010-04-22 15:59:21 -07007656 if (c.mAttachedHidden) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007657 c.mAttachedHidden = false;
Dianne Hackbornf09c1a22010-04-22 15:59:21 -07007658 if (c.mSurface != null) {
7659 c.performShowLocked();
7660 // It hadn't been shown, which means layout not
7661 // performed on it, so now we want to make sure to
7662 // do a layout. If called from within the transaction
7663 // loop, this will cause it to restart with a new
7664 // layout.
7665 mLayoutNeeded = true;
7666 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007667 }
7668 }
Romain Guy06882f82009-06-10 13:36:04 -07007669
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007670 if (mAttrs.type != TYPE_APPLICATION_STARTING
7671 && mAppToken != null) {
7672 mAppToken.firstWindowDrawn = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007673
Dianne Hackborn248b1882009-09-16 16:46:44 -07007674 if (mAppToken.startingData != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007675 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG,
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007676 "Finish starting " + mToken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007677 + ": first real window is shown, no animation");
Dianne Hackborn248b1882009-09-16 16:46:44 -07007678 // If this initial window is animating, stop it -- we
7679 // will do an animation to reveal it from behind the
7680 // starting window, so there is no need for it to also
7681 // be doing its own stuff.
7682 if (mAnimation != null) {
7683 mAnimation = null;
7684 // Make sure we clean up the animation.
7685 mAnimating = true;
7686 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007687 mFinishedStarting.add(mAppToken);
7688 mH.sendEmptyMessage(H.FINISHED_STARTING);
7689 }
7690 mAppToken.updateReportedVisibilityLocked();
7691 }
7692 }
7693 return true;
7694 }
Romain Guy06882f82009-06-10 13:36:04 -07007695
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007696 // This must be called while inside a transaction. Returns true if
7697 // there is more animation to run.
7698 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -08007699 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007700 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07007701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
7703 mHasTransformation = true;
7704 mHasLocalTransformation = true;
7705 if (!mLocalAnimating) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007706 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007707 TAG, "Starting animation in " + this +
7708 " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
7709 " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
7710 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
7711 mAnimation.setStartTime(currentTime);
7712 mLocalAnimating = true;
7713 mAnimating = true;
7714 }
7715 mTransformation.clear();
7716 final boolean more = mAnimation.getTransformation(
7717 currentTime, mTransformation);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007718 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007719 TAG, "Stepped animation in " + this +
7720 ": more=" + more + ", xform=" + mTransformation);
7721 if (more) {
7722 // we're not done!
7723 return true;
7724 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007725 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007726 TAG, "Finished animation in " + this +
7727 " @ " + currentTime);
7728 mAnimation = null;
7729 //WindowManagerService.this.dump();
7730 }
7731 mHasLocalTransformation = false;
7732 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007733 && mAppToken.animation != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007734 // When our app token is animating, we kind-of pretend like
7735 // we are as well. Note the mLocalAnimating mAnimationIsEntrance
7736 // part of this check means that we will only do this if
7737 // our window is not currently exiting, or it is not
7738 // locally animating itself. The idea being that one that
7739 // is exiting and doing a local animation should be removed
7740 // once that animation is done.
7741 mAnimating = true;
7742 mHasTransformation = true;
7743 mTransformation.clear();
7744 return false;
7745 } else if (mHasTransformation) {
7746 // Little trick to get through the path below to act like
7747 // we have finished an animation.
7748 mAnimating = true;
7749 } else if (isAnimating()) {
7750 mAnimating = true;
7751 }
7752 } else if (mAnimation != null) {
7753 // If the display is frozen, and there is a pending animation,
7754 // clear it and make sure we run the cleanup code.
7755 mAnimating = true;
7756 mLocalAnimating = true;
7757 mAnimation = null;
7758 }
Romain Guy06882f82009-06-10 13:36:04 -07007759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007760 if (!mAnimating && !mLocalAnimating) {
7761 return false;
7762 }
7763
Joe Onorato8a9b2202010-02-26 18:56:32 -08007764 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007765 TAG, "Animation done in " + this + ": exiting=" + mExiting
7766 + ", reportedVisible="
7767 + (mAppToken != null ? mAppToken.reportedVisible : false));
Romain Guy06882f82009-06-10 13:36:04 -07007768
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007769 mAnimating = false;
7770 mLocalAnimating = false;
7771 mAnimation = null;
7772 mAnimLayer = mLayer;
7773 if (mIsImWindow) {
7774 mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007775 } else if (mIsWallpaper) {
7776 mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007777 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007778 if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007779 + " anim layer: " + mAnimLayer);
7780 mHasTransformation = false;
7781 mHasLocalTransformation = false;
Dianne Hackbornb601ce12010-03-01 23:36:02 -08007782 if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
7783 if (DEBUG_VISIBILITY) {
7784 Slog.v(TAG, "Policy visibility changing after anim in " + this + ": "
7785 + mPolicyVisibilityAfterAnim);
7786 }
7787 mPolicyVisibility = mPolicyVisibilityAfterAnim;
7788 if (!mPolicyVisibility) {
7789 if (mCurrentFocus == this) {
7790 mFocusMayChange = true;
7791 }
7792 // Window is no longer visible -- make sure if we were waiting
7793 // for it to be displayed before enabling the display, that
7794 // we allow the display to be enabled now.
7795 enableScreenIfNeededLocked();
7796 }
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -08007797 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007798 mTransformation.clear();
7799 if (mHasDrawn
7800 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
7801 && mAppToken != null
7802 && mAppToken.firstWindowDrawn
7803 && mAppToken.startingData != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007804 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007805 + mToken + ": first real window done animating");
7806 mFinishedStarting.add(mAppToken);
7807 mH.sendEmptyMessage(H.FINISHED_STARTING);
7808 }
Romain Guy06882f82009-06-10 13:36:04 -07007809
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007810 finishExit();
7811
7812 if (mAppToken != null) {
7813 mAppToken.updateReportedVisibilityLocked();
7814 }
7815
7816 return false;
7817 }
7818
7819 void finishExit() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007820 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007821 TAG, "finishExit in " + this
7822 + ": exiting=" + mExiting
7823 + " remove=" + mRemoveOnExit
7824 + " windowAnimating=" + isWindowAnimating());
Romain Guy06882f82009-06-10 13:36:04 -07007825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007826 final int N = mChildWindows.size();
7827 for (int i=0; i<N; i++) {
7828 ((WindowState)mChildWindows.get(i)).finishExit();
7829 }
Romain Guy06882f82009-06-10 13:36:04 -07007830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007831 if (!mExiting) {
7832 return;
7833 }
Romain Guy06882f82009-06-10 13:36:04 -07007834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007835 if (isWindowAnimating()) {
7836 return;
7837 }
7838
Joe Onorato8a9b2202010-02-26 18:56:32 -08007839 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007840 TAG, "Exit animation finished in " + this
7841 + ": remove=" + mRemoveOnExit);
7842 if (mSurface != null) {
7843 mDestroySurface.add(this);
7844 mDestroying = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007845 if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null);
Dianne Hackborn16064f92010-03-25 00:47:24 -07007846 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007847 try {
7848 mSurface.hide();
7849 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007850 Slog.w(TAG, "Error hiding surface in " + this, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007851 }
7852 mLastHidden = true;
7853 mKeyWaiter.releasePendingPointerLocked(mSession);
7854 }
7855 mExiting = false;
7856 if (mRemoveOnExit) {
7857 mPendingRemove.add(this);
7858 mRemoveOnExit = false;
7859 }
7860 }
Romain Guy06882f82009-06-10 13:36:04 -07007861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007862 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
7863 if (dsdx < .99999f || dsdx > 1.00001f) return false;
7864 if (dtdy < .99999f || dtdy > 1.00001f) return false;
7865 if (dtdx < -.000001f || dtdx > .000001f) return false;
7866 if (dsdy < -.000001f || dsdy > .000001f) return false;
7867 return true;
7868 }
Romain Guy06882f82009-06-10 13:36:04 -07007869
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007870 void computeShownFrameLocked() {
7871 final boolean selfTransformation = mHasLocalTransformation;
7872 Transformation attachedTransformation =
7873 (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
7874 ? mAttachedWindow.mTransformation : null;
7875 Transformation appTransformation =
7876 (mAppToken != null && mAppToken.hasTransformation)
7877 ? mAppToken.transformation : null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007878
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007879 // Wallpapers are animated based on the "real" window they
7880 // are currently targeting.
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007881 if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07007882 && mWallpaperTarget != null) {
Dianne Hackborn5baba162009-09-23 17:01:12 -07007883 if (mWallpaperTarget.mHasLocalTransformation &&
7884 mWallpaperTarget.mAnimation != null &&
7885 !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007886 attachedTransformation = mWallpaperTarget.mTransformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07007887 if (DEBUG_WALLPAPER && attachedTransformation != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007888 Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
Dianne Hackborn5baba162009-09-23 17:01:12 -07007889 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007890 }
7891 if (mWallpaperTarget.mAppToken != null &&
Dianne Hackborn5baba162009-09-23 17:01:12 -07007892 mWallpaperTarget.mAppToken.hasTransformation &&
7893 mWallpaperTarget.mAppToken.animation != null &&
7894 !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007895 appTransformation = mWallpaperTarget.mAppToken.transformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07007896 if (DEBUG_WALLPAPER && appTransformation != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007897 Slog.v(TAG, "WP target app xform: " + appTransformation);
Dianne Hackborn5baba162009-09-23 17:01:12 -07007898 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007899 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007900 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007902 if (selfTransformation || attachedTransformation != null
7903 || appTransformation != null) {
Romain Guy06882f82009-06-10 13:36:04 -07007904 // cache often used attributes locally
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007905 final Rect frame = mFrame;
7906 final float tmpFloats[] = mTmpFloats;
7907 final Matrix tmpMatrix = mTmpMatrix;
7908
7909 // Compute the desired transformation.
Dianne Hackborn65c23872009-09-18 17:47:02 -07007910 tmpMatrix.setTranslate(0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911 if (selfTransformation) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007912 tmpMatrix.postConcat(mTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007913 }
Dianne Hackborn65c23872009-09-18 17:47:02 -07007914 tmpMatrix.postTranslate(frame.left, frame.top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007915 if (attachedTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007916 tmpMatrix.postConcat(attachedTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007917 }
7918 if (appTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007919 tmpMatrix.postConcat(appTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007920 }
7921
7922 // "convert" it into SurfaceFlinger's format
7923 // (a 2x2 matrix + an offset)
7924 // Here we must not transform the position of the surface
7925 // since it is already included in the transformation.
Joe Onorato8a9b2202010-02-26 18:56:32 -08007926 //Slog.i(TAG, "Transform: " + matrix);
Romain Guy06882f82009-06-10 13:36:04 -07007927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007928 tmpMatrix.getValues(tmpFloats);
7929 mDsDx = tmpFloats[Matrix.MSCALE_X];
7930 mDtDx = tmpFloats[Matrix.MSKEW_X];
7931 mDsDy = tmpFloats[Matrix.MSKEW_Y];
7932 mDtDy = tmpFloats[Matrix.MSCALE_Y];
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007933 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
7934 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 int w = frame.width();
7936 int h = frame.height();
7937 mShownFrame.set(x, y, x+w, y+h);
7938
7939 // Now set the alpha... but because our current hardware
7940 // can't do alpha transformation on a non-opaque surface,
7941 // turn it off if we are running an animation that is also
7942 // transforming since it is more important to have that
7943 // animation be smooth.
7944 mShownAlpha = mAlpha;
7945 if (!mLimitedAlphaCompositing
7946 || (!PixelFormat.formatHasAlpha(mAttrs.format)
7947 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
7948 && x == frame.left && y == frame.top))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007949 //Slog.i(TAG, "Applying alpha transform");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007950 if (selfTransformation) {
7951 mShownAlpha *= mTransformation.getAlpha();
7952 }
7953 if (attachedTransformation != null) {
7954 mShownAlpha *= attachedTransformation.getAlpha();
7955 }
7956 if (appTransformation != null) {
7957 mShownAlpha *= appTransformation.getAlpha();
7958 }
7959 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007960 //Slog.i(TAG, "Not applying alpha transform");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007961 }
Romain Guy06882f82009-06-10 13:36:04 -07007962
Joe Onorato8a9b2202010-02-26 18:56:32 -08007963 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007964 TAG, "Continuing animation in " + this +
7965 ": " + mShownFrame +
7966 ", alpha=" + mTransformation.getAlpha());
7967 return;
7968 }
Romain Guy06882f82009-06-10 13:36:04 -07007969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007970 mShownFrame.set(mFrame);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007971 if (mXOffset != 0 || mYOffset != 0) {
7972 mShownFrame.offset(mXOffset, mYOffset);
7973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007974 mShownAlpha = mAlpha;
7975 mDsDx = 1;
7976 mDtDx = 0;
7977 mDsDy = 0;
7978 mDtDy = 1;
7979 }
Romain Guy06882f82009-06-10 13:36:04 -07007980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007981 /**
7982 * Is this window visible? It is not visible if there is no
7983 * surface, or we are in the process of running an exit animation
7984 * that will remove the surface, or its app token has been hidden.
7985 */
7986 public boolean isVisibleLw() {
7987 final AppWindowToken atoken = mAppToken;
7988 return mSurface != null && mPolicyVisibility && !mAttachedHidden
7989 && (atoken == null || !atoken.hiddenRequested)
7990 && !mExiting && !mDestroying;
7991 }
7992
7993 /**
Dianne Hackborn3d163f072009-10-07 21:26:57 -07007994 * Like {@link #isVisibleLw}, but also counts a window that is currently
7995 * "hidden" behind the keyguard as visible. This allows us to apply
7996 * things like window flags that impact the keyguard.
7997 * XXX I am starting to think we need to have ANOTHER visibility flag
7998 * for this "hidden behind keyguard" state rather than overloading
7999 * mPolicyVisibility. Ungh.
8000 */
8001 public boolean isVisibleOrBehindKeyguardLw() {
8002 final AppWindowToken atoken = mAppToken;
8003 return mSurface != null && !mAttachedHidden
8004 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008005 && !mDrawPending && !mCommitDrawPending
Dianne Hackborn3d163f072009-10-07 21:26:57 -07008006 && !mExiting && !mDestroying;
8007 }
8008
8009 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008010 * Is this window visible, ignoring its app token? It is not visible
8011 * if there is no surface, or we are in the process of running an exit animation
8012 * that will remove the surface.
8013 */
8014 public boolean isWinVisibleLw() {
8015 final AppWindowToken atoken = mAppToken;
8016 return mSurface != null && mPolicyVisibility && !mAttachedHidden
8017 && (atoken == null || !atoken.hiddenRequested || atoken.animating)
8018 && !mExiting && !mDestroying;
8019 }
8020
8021 /**
8022 * The same as isVisible(), but follows the current hidden state of
8023 * the associated app token, not the pending requested hidden state.
8024 */
8025 boolean isVisibleNow() {
8026 return mSurface != null && mPolicyVisibility && !mAttachedHidden
The Android Open Source Project10592532009-03-18 17:39:46 -07008027 && !mRootToken.hidden && !mExiting && !mDestroying;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008028 }
8029
8030 /**
8031 * Same as isVisible(), but we also count it as visible between the
8032 * call to IWindowSession.add() and the first relayout().
8033 */
8034 boolean isVisibleOrAdding() {
8035 final AppWindowToken atoken = mAppToken;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008036 return ((mSurface != null && !mReportDestroySurface)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008037 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
8038 && mPolicyVisibility && !mAttachedHidden
8039 && (atoken == null || !atoken.hiddenRequested)
8040 && !mExiting && !mDestroying;
8041 }
8042
8043 /**
8044 * Is this window currently on-screen? It is on-screen either if it
8045 * is visible or it is currently running an animation before no longer
8046 * being visible.
8047 */
8048 boolean isOnScreen() {
8049 final AppWindowToken atoken = mAppToken;
8050 if (atoken != null) {
8051 return mSurface != null && mPolicyVisibility && !mDestroying
8052 && ((!mAttachedHidden && !atoken.hiddenRequested)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008053 || mAnimation != null || atoken.animation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008054 } else {
8055 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008056 && (!mAttachedHidden || mAnimation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008057 }
8058 }
Romain Guy06882f82009-06-10 13:36:04 -07008059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008060 /**
8061 * Like isOnScreen(), but we don't return true if the window is part
8062 * of a transition that has not yet been started.
8063 */
8064 boolean isReadyForDisplay() {
Dianne Hackborna8f60182009-09-01 19:01:50 -07008065 if (mRootToken.waitingToShow &&
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07008066 mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07008067 return false;
8068 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008069 final AppWindowToken atoken = mAppToken;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008070 final boolean animating = atoken != null
8071 ? (atoken.animation != null) : false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008072 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008073 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
8074 && !mRootToken.hidden)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008075 || mAnimation != null || animating);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008076 }
8077
8078 /** Is the window or its container currently animating? */
8079 boolean isAnimating() {
8080 final WindowState attached = mAttachedWindow;
8081 final AppWindowToken atoken = mAppToken;
8082 return mAnimation != null
8083 || (attached != null && attached.mAnimation != null)
Romain Guy06882f82009-06-10 13:36:04 -07008084 || (atoken != null &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008085 (atoken.animation != null
8086 || atoken.inPendingTransaction));
8087 }
8088
8089 /** Is this window currently animating? */
8090 boolean isWindowAnimating() {
8091 return mAnimation != null;
8092 }
8093
8094 /**
8095 * Like isOnScreen, but returns false if the surface hasn't yet
8096 * been drawn.
8097 */
8098 public boolean isDisplayedLw() {
8099 final AppWindowToken atoken = mAppToken;
8100 return mSurface != null && mPolicyVisibility && !mDestroying
8101 && !mDrawPending && !mCommitDrawPending
8102 && ((!mAttachedHidden &&
8103 (atoken == null || !atoken.hiddenRequested))
8104 || mAnimating);
8105 }
8106
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008107 /**
8108 * Returns true if the window has a surface that it has drawn a
8109 * complete UI in to.
8110 */
8111 public boolean isDrawnLw() {
8112 final AppWindowToken atoken = mAppToken;
8113 return mSurface != null && !mDestroying
8114 && !mDrawPending && !mCommitDrawPending;
8115 }
8116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117 public boolean fillsScreenLw(int screenWidth, int screenHeight,
8118 boolean shownFrame, boolean onlyOpaque) {
8119 if (mSurface == null) {
8120 return false;
8121 }
8122 if (mAppToken != null && !mAppToken.appFullscreen) {
8123 return false;
8124 }
8125 if (onlyOpaque && mAttrs.format != PixelFormat.OPAQUE) {
8126 return false;
8127 }
8128 final Rect frame = shownFrame ? mShownFrame : mFrame;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008129
8130 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
8131 return frame.left <= mCompatibleScreenFrame.left &&
8132 frame.top <= mCompatibleScreenFrame.top &&
8133 frame.right >= mCompatibleScreenFrame.right &&
8134 frame.bottom >= mCompatibleScreenFrame.bottom;
8135 } else {
8136 return frame.left <= 0 && frame.top <= 0
8137 && frame.right >= screenWidth
8138 && frame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008139 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008140 }
Romain Guy06882f82009-06-10 13:36:04 -07008141
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008142 /**
Dianne Hackborn25994b42009-09-04 14:21:19 -07008143 * Return true if the window is opaque and fully drawn. This indicates
8144 * it may obscure windows behind it.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008145 */
8146 boolean isOpaqueDrawn() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07008147 return (mAttrs.format == PixelFormat.OPAQUE
8148 || mAttrs.type == TYPE_WALLPAPER)
8149 && mSurface != null && mAnimation == null
8150 && (mAppToken == null || mAppToken.animation == null)
8151 && !mDrawPending && !mCommitDrawPending;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008152 }
8153
8154 boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
8155 return
8156 // only if the application is requesting compatible window
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008157 (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
8158 // only if it's visible
8159 mHasDrawn && mViewVisibility == View.VISIBLE &&
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008160 // and only if the application fills the compatible screen
8161 mFrame.left <= mCompatibleScreenFrame.left &&
8162 mFrame.top <= mCompatibleScreenFrame.top &&
8163 mFrame.right >= mCompatibleScreenFrame.right &&
8164 mFrame.bottom >= mCompatibleScreenFrame.bottom &&
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008165 // and starting window do not need background filler
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008166 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008167 }
8168
8169 boolean isFullscreen(int screenWidth, int screenHeight) {
8170 return mFrame.left <= 0 && mFrame.top <= 0 &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07008171 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008172 }
8173
8174 void removeLocked() {
8175 if (mAttachedWindow != null) {
8176 mAttachedWindow.mChildWindows.remove(this);
8177 }
8178 destroySurfaceLocked();
8179 mSession.windowRemovedLocked();
8180 try {
8181 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
8182 } catch (RuntimeException e) {
8183 // Ignore if it has already been removed (usually because
8184 // we are doing this as part of processing a death note.)
8185 }
8186 }
8187
8188 private class DeathRecipient implements IBinder.DeathRecipient {
8189 public void binderDied() {
8190 try {
8191 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008192 WindowState win = windowForClientLocked(mSession, mClient, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008193 Slog.i(TAG, "WIN DEATH: " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008194 if (win != null) {
8195 removeWindowLocked(mSession, win);
8196 }
8197 }
8198 } catch (IllegalArgumentException ex) {
8199 // This will happen if the window has already been
8200 // removed.
8201 }
8202 }
8203 }
8204
8205 /** Returns true if this window desires key events. */
8206 public final boolean canReceiveKeys() {
8207 return isVisibleOrAdding()
8208 && (mViewVisibility == View.VISIBLE)
8209 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
8210 }
8211
8212 public boolean hasDrawnLw() {
8213 return mHasDrawn;
8214 }
8215
8216 public boolean showLw(boolean doAnimation) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008217 return showLw(doAnimation, true);
8218 }
8219
8220 boolean showLw(boolean doAnimation, boolean requestAnim) {
8221 if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
8222 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008223 }
Dianne Hackbornb601ce12010-03-01 23:36:02 -08008224 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008225 if (doAnimation) {
8226 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
8227 + mPolicyVisibility + " mAnimation=" + mAnimation);
8228 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8229 doAnimation = false;
8230 } else if (mPolicyVisibility && mAnimation == null) {
8231 // Check for the case where we are currently visible and
8232 // not animating; we do not want to do animation at such a
8233 // point to become visible when we already are.
8234 doAnimation = false;
8235 }
8236 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008237 mPolicyVisibility = true;
8238 mPolicyVisibilityAfterAnim = true;
8239 if (doAnimation) {
8240 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
8241 }
8242 if (requestAnim) {
8243 requestAnimationLocked(0);
8244 }
8245 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008246 }
8247
8248 public boolean hideLw(boolean doAnimation) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008249 return hideLw(doAnimation, true);
8250 }
8251
8252 boolean hideLw(boolean doAnimation, boolean requestAnim) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008253 if (doAnimation) {
8254 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8255 doAnimation = false;
8256 }
8257 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008258 boolean current = doAnimation ? mPolicyVisibilityAfterAnim
8259 : mPolicyVisibility;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008260 if (!current) {
8261 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008262 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008263 if (doAnimation) {
8264 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
8265 if (mAnimation == null) {
8266 doAnimation = false;
8267 }
8268 }
8269 if (doAnimation) {
8270 mPolicyVisibilityAfterAnim = false;
8271 } else {
Dianne Hackbornb601ce12010-03-01 23:36:02 -08008272 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008273 mPolicyVisibilityAfterAnim = false;
8274 mPolicyVisibility = false;
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -08008275 // Window is no longer visible -- make sure if we were waiting
8276 // for it to be displayed before enabling the display, that
8277 // we allow the display to be enabled now.
8278 enableScreenIfNeededLocked();
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008279 if (mCurrentFocus == this) {
8280 mFocusMayChange = true;
8281 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008282 }
8283 if (requestAnim) {
8284 requestAnimationLocked(0);
8285 }
8286 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008287 }
8288
8289 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008290 pw.print(prefix); pw.print("mSession="); pw.print(mSession);
8291 pw.print(" mClient="); pw.println(mClient.asBinder());
8292 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
8293 if (mAttachedWindow != null || mLayoutAttached) {
8294 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
8295 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
8296 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07008297 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
8298 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
8299 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008300 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
8301 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008302 }
8303 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
8304 pw.print(" mSubLayer="); pw.print(mSubLayer);
8305 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
8306 pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
8307 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
8308 pw.print("="); pw.print(mAnimLayer);
8309 pw.print(" mLastLayer="); pw.println(mLastLayer);
8310 if (mSurface != null) {
8311 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
Dianne Hackborn16064f92010-03-25 00:47:24 -07008312 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
8313 pw.print(" layer="); pw.print(mSurfaceLayer);
8314 pw.print(" alpha="); pw.print(mSurfaceAlpha);
8315 pw.print(" rect=("); pw.print(mSurfaceX);
8316 pw.print(","); pw.print(mSurfaceY);
8317 pw.print(") "); pw.print(mSurfaceW);
8318 pw.print(" x "); pw.println(mSurfaceH);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008319 }
8320 pw.print(prefix); pw.print("mToken="); pw.println(mToken);
8321 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
8322 if (mAppToken != null) {
8323 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
8324 }
8325 if (mTargetAppToken != null) {
8326 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
8327 }
8328 pw.print(prefix); pw.print("mViewVisibility=0x");
8329 pw.print(Integer.toHexString(mViewVisibility));
8330 pw.print(" mLastHidden="); pw.print(mLastHidden);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008331 pw.print(" mHaveFrame="); pw.print(mHaveFrame);
8332 pw.print(" mObscured="); pw.println(mObscured);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008333 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
8334 pw.print(prefix); pw.print("mPolicyVisibility=");
8335 pw.print(mPolicyVisibility);
8336 pw.print(" mPolicyVisibilityAfterAnim=");
8337 pw.print(mPolicyVisibilityAfterAnim);
8338 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
8339 }
Dianne Hackborn9b52a212009-12-11 14:51:35 -08008340 if (!mRelayoutCalled) {
8341 pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
8342 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008343 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008344 pw.print(" h="); pw.print(mRequestedHeight);
8345 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008346 if (mXOffset != 0 || mYOffset != 0) {
8347 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
8348 pw.print(" y="); pw.println(mYOffset);
8349 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008350 pw.print(prefix); pw.print("mGivenContentInsets=");
8351 mGivenContentInsets.printShortString(pw);
8352 pw.print(" mGivenVisibleInsets=");
8353 mGivenVisibleInsets.printShortString(pw);
8354 pw.println();
8355 if (mTouchableInsets != 0 || mGivenInsetsPending) {
8356 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
8357 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
8358 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008359 pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008360 pw.print(prefix); pw.print("mShownFrame=");
8361 mShownFrame.printShortString(pw);
8362 pw.print(" last="); mLastShownFrame.printShortString(pw);
8363 pw.println();
8364 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
8365 pw.print(" last="); mLastFrame.printShortString(pw);
8366 pw.println();
8367 pw.print(prefix); pw.print("mContainingFrame=");
8368 mContainingFrame.printShortString(pw);
8369 pw.print(" mDisplayFrame=");
8370 mDisplayFrame.printShortString(pw);
8371 pw.println();
8372 pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
8373 pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
8374 pw.println();
8375 pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
8376 pw.print(" last="); mLastContentInsets.printShortString(pw);
8377 pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
8378 pw.print(" last="); mLastVisibleInsets.printShortString(pw);
8379 pw.println();
8380 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
8381 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
8382 pw.print(" mAlpha="); pw.print(mAlpha);
8383 pw.print(" mLastAlpha="); pw.println(mLastAlpha);
8384 }
8385 if (mAnimating || mLocalAnimating || mAnimationIsEntrance
8386 || mAnimation != null) {
8387 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
8388 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
8389 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
8390 pw.print(" mAnimation="); pw.println(mAnimation);
8391 }
8392 if (mHasTransformation || mHasLocalTransformation) {
8393 pw.print(prefix); pw.print("XForm: has=");
8394 pw.print(mHasTransformation);
8395 pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
8396 pw.print(" "); mTransformation.printShortString(pw);
8397 pw.println();
8398 }
8399 pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
8400 pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
8401 pw.print(" mReadyToShow="); pw.print(mReadyToShow);
8402 pw.print(" mHasDrawn="); pw.println(mHasDrawn);
8403 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
8404 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
8405 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
8406 pw.print(" mDestroying="); pw.print(mDestroying);
8407 pw.print(" mRemoved="); pw.println(mRemoved);
8408 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07008409 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008410 pw.print(prefix); pw.print("mOrientationChanging=");
8411 pw.print(mOrientationChanging);
Dianne Hackborn93e462b2009-09-15 22:50:40 -07008412 pw.print(" mAppFreezing="); pw.print(mAppFreezing);
8413 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008414 }
Mitsuru Oshima589cebe2009-07-22 20:38:58 -07008415 if (mHScale != 1 || mVScale != 1) {
8416 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
8417 pw.print(" mVScale="); pw.println(mVScale);
8418 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07008419 if (mWallpaperX != -1 || mWallpaperY != -1) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008420 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
8421 pw.print(" mWallpaperY="); pw.println(mWallpaperY);
8422 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08008423 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
8424 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
8425 pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
8426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008427 }
8428
8429 @Override
8430 public String toString() {
8431 return "Window{"
8432 + Integer.toHexString(System.identityHashCode(this))
8433 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
8434 }
8435 }
Romain Guy06882f82009-06-10 13:36:04 -07008436
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008437 // -------------------------------------------------------------
8438 // Window Token State
8439 // -------------------------------------------------------------
8440
8441 class WindowToken {
8442 // The actual token.
8443 final IBinder token;
8444
8445 // The type of window this token is for, as per WindowManager.LayoutParams.
8446 final int windowType;
Romain Guy06882f82009-06-10 13:36:04 -07008447
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008448 // Set if this token was explicitly added by a client, so should
8449 // not be removed when all windows are removed.
8450 final boolean explicit;
Romain Guy06882f82009-06-10 13:36:04 -07008451
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008452 // For printing.
8453 String stringName;
Romain Guy06882f82009-06-10 13:36:04 -07008454
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008455 // If this is an AppWindowToken, this is non-null.
8456 AppWindowToken appWindowToken;
Romain Guy06882f82009-06-10 13:36:04 -07008457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008458 // All of the windows associated with this token.
8459 final ArrayList<WindowState> windows = new ArrayList<WindowState>();
8460
8461 // Is key dispatching paused for this token?
8462 boolean paused = false;
8463
8464 // Should this token's windows be hidden?
8465 boolean hidden;
8466
8467 // Temporary for finding which tokens no longer have visible windows.
8468 boolean hasVisible;
8469
Dianne Hackborna8f60182009-09-01 19:01:50 -07008470 // Set to true when this token is in a pending transaction where it
8471 // will be shown.
8472 boolean waitingToShow;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008473
Dianne Hackborna8f60182009-09-01 19:01:50 -07008474 // Set to true when this token is in a pending transaction where it
8475 // will be hidden.
8476 boolean waitingToHide;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008477
Dianne Hackborna8f60182009-09-01 19:01:50 -07008478 // Set to true when this token is in a pending transaction where its
8479 // windows will be put to the bottom of the list.
8480 boolean sendingToBottom;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008481
Dianne Hackborna8f60182009-09-01 19:01:50 -07008482 // Set to true when this token is in a pending transaction where its
8483 // windows will be put to the top of the list.
8484 boolean sendingToTop;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008485
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008486 WindowToken(IBinder _token, int type, boolean _explicit) {
8487 token = _token;
8488 windowType = type;
8489 explicit = _explicit;
8490 }
8491
8492 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008493 pw.print(prefix); pw.print("token="); pw.println(token);
8494 pw.print(prefix); pw.print("windows="); pw.println(windows);
8495 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
8496 pw.print(" hidden="); pw.print(hidden);
8497 pw.print(" hasVisible="); pw.println(hasVisible);
Dianne Hackborna8f60182009-09-01 19:01:50 -07008498 if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
8499 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
8500 pw.print(" waitingToHide="); pw.print(waitingToHide);
8501 pw.print(" sendingToBottom="); pw.print(sendingToBottom);
8502 pw.print(" sendingToTop="); pw.println(sendingToTop);
8503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008504 }
8505
8506 @Override
8507 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008508 if (stringName == null) {
8509 StringBuilder sb = new StringBuilder();
8510 sb.append("WindowToken{");
8511 sb.append(Integer.toHexString(System.identityHashCode(this)));
8512 sb.append(" token="); sb.append(token); sb.append('}');
8513 stringName = sb.toString();
8514 }
8515 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008516 }
8517 };
8518
8519 class AppWindowToken extends WindowToken {
8520 // Non-null only for application tokens.
8521 final IApplicationToken appToken;
8522
8523 // All of the windows and child windows that are included in this
8524 // application token. Note this list is NOT sorted!
8525 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
8526
8527 int groupId = -1;
8528 boolean appFullscreen;
8529 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Romain Guy06882f82009-06-10 13:36:04 -07008530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531 // These are used for determining when all windows associated with
8532 // an activity have been drawn, so they can be made visible together
8533 // at the same time.
8534 int lastTransactionSequence = mTransactionSequence-1;
8535 int numInterestingWindows;
8536 int numDrawnWindows;
8537 boolean inPendingTransaction;
8538 boolean allDrawn;
Romain Guy06882f82009-06-10 13:36:04 -07008539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 // Is this token going to be hidden in a little while? If so, it
8541 // won't be taken into account for setting the screen orientation.
8542 boolean willBeHidden;
Romain Guy06882f82009-06-10 13:36:04 -07008543
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008544 // Is this window's surface needed? This is almost like hidden, except
8545 // it will sometimes be true a little earlier: when the token has
8546 // been shown, but is still waiting for its app transition to execute
8547 // before making its windows shown.
8548 boolean hiddenRequested;
Romain Guy06882f82009-06-10 13:36:04 -07008549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008550 // Have we told the window clients to hide themselves?
8551 boolean clientHidden;
Romain Guy06882f82009-06-10 13:36:04 -07008552
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008553 // Last visibility state we reported to the app token.
8554 boolean reportedVisible;
8555
8556 // Set to true when the token has been removed from the window mgr.
8557 boolean removed;
8558
8559 // Have we been asked to have this token keep the screen frozen?
8560 boolean freezingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07008561
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008562 boolean animating;
8563 Animation animation;
8564 boolean hasTransformation;
8565 final Transformation transformation = new Transformation();
Romain Guy06882f82009-06-10 13:36:04 -07008566
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008567 // Offset to the window of all layers in the token, for use by
8568 // AppWindowToken animations.
8569 int animLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -07008570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008571 // Information about an application starting window if displayed.
8572 StartingData startingData;
8573 WindowState startingWindow;
8574 View startingView;
8575 boolean startingDisplayed;
8576 boolean startingMoved;
8577 boolean firstWindowDrawn;
8578
8579 AppWindowToken(IApplicationToken _token) {
8580 super(_token.asBinder(),
8581 WindowManager.LayoutParams.TYPE_APPLICATION, true);
8582 appWindowToken = this;
8583 appToken = _token;
8584 }
Romain Guy06882f82009-06-10 13:36:04 -07008585
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008586 public void setAnimation(Animation anim) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008587 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008588 TAG, "Setting animation in " + this + ": " + anim);
8589 animation = anim;
8590 animating = false;
8591 anim.restrictDuration(MAX_ANIMATION_DURATION);
8592 anim.scaleCurrentDuration(mTransitionAnimationScale);
8593 int zorder = anim.getZAdjustment();
8594 int adj = 0;
8595 if (zorder == Animation.ZORDER_TOP) {
8596 adj = TYPE_LAYER_OFFSET;
8597 } else if (zorder == Animation.ZORDER_BOTTOM) {
8598 adj = -TYPE_LAYER_OFFSET;
8599 }
Romain Guy06882f82009-06-10 13:36:04 -07008600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008601 if (animLayerAdjustment != adj) {
8602 animLayerAdjustment = adj;
8603 updateLayers();
8604 }
8605 }
Romain Guy06882f82009-06-10 13:36:04 -07008606
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008607 public void setDummyAnimation() {
8608 if (animation == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008609 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008610 TAG, "Setting dummy animation in " + this);
8611 animation = sDummyAnimation;
8612 }
8613 }
8614
8615 public void clearAnimation() {
8616 if (animation != null) {
8617 animation = null;
8618 animating = true;
8619 }
8620 }
Romain Guy06882f82009-06-10 13:36:04 -07008621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008622 void updateLayers() {
8623 final int N = allAppWindows.size();
8624 final int adj = animLayerAdjustment;
8625 for (int i=0; i<N; i++) {
8626 WindowState w = allAppWindows.get(i);
8627 w.mAnimLayer = w.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008628 if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008629 + w.mAnimLayer);
8630 if (w == mInputMethodTarget) {
8631 setInputMethodAnimLayerAdjustment(adj);
8632 }
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008633 if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008634 setWallpaperAnimLayerAdjustmentLocked(adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008636 }
8637 }
Romain Guy06882f82009-06-10 13:36:04 -07008638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 void sendAppVisibilityToClients() {
8640 final int N = allAppWindows.size();
8641 for (int i=0; i<N; i++) {
8642 WindowState win = allAppWindows.get(i);
8643 if (win == startingWindow && clientHidden) {
8644 // Don't hide the starting window.
8645 continue;
8646 }
8647 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008648 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 "Setting visibility of " + win + ": " + (!clientHidden));
8650 win.mClient.dispatchAppVisibility(!clientHidden);
8651 } catch (RemoteException e) {
8652 }
8653 }
8654 }
Romain Guy06882f82009-06-10 13:36:04 -07008655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008656 void showAllWindowsLocked() {
8657 final int NW = allAppWindows.size();
8658 for (int i=0; i<NW; i++) {
8659 WindowState w = allAppWindows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008660 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008661 "performing show on: " + w);
8662 w.performShowLocked();
8663 }
8664 }
Romain Guy06882f82009-06-10 13:36:04 -07008665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008666 // This must be called while inside a transaction.
8667 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -08008668 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008669 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07008670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008671 if (animation == sDummyAnimation) {
8672 // This guy is going to animate, but not yet. For now count
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008673 // it as not animating for purposes of scheduling transactions;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008674 // when it is really time to animate, this will be set to
8675 // a real animation and the next call will execute normally.
8676 return false;
8677 }
Romain Guy06882f82009-06-10 13:36:04 -07008678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008679 if ((allDrawn || animating || startingDisplayed) && animation != null) {
8680 if (!animating) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008681 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008682 TAG, "Starting animation in " + this +
8683 " @ " + currentTime + ": dw=" + dw + " dh=" + dh
8684 + " scale=" + mTransitionAnimationScale
8685 + " allDrawn=" + allDrawn + " animating=" + animating);
8686 animation.initialize(dw, dh, dw, dh);
8687 animation.setStartTime(currentTime);
8688 animating = true;
8689 }
8690 transformation.clear();
8691 final boolean more = animation.getTransformation(
8692 currentTime, transformation);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008693 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008694 TAG, "Stepped animation in " + this +
8695 ": more=" + more + ", xform=" + transformation);
8696 if (more) {
8697 // we're done!
8698 hasTransformation = true;
8699 return true;
8700 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008701 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008702 TAG, "Finished animation in " + this +
8703 " @ " + currentTime);
8704 animation = null;
8705 }
8706 } else if (animation != null) {
8707 // If the display is frozen, and there is a pending animation,
8708 // clear it and make sure we run the cleanup code.
8709 animating = true;
8710 animation = null;
8711 }
8712
8713 hasTransformation = false;
Romain Guy06882f82009-06-10 13:36:04 -07008714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008715 if (!animating) {
8716 return false;
8717 }
8718
8719 clearAnimation();
8720 animating = false;
8721 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
8722 moveInputMethodWindowsIfNeededLocked(true);
8723 }
Romain Guy06882f82009-06-10 13:36:04 -07008724
Joe Onorato8a9b2202010-02-26 18:56:32 -08008725 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008726 TAG, "Animation done in " + this
8727 + ": reportedVisible=" + reportedVisible);
8728
8729 transformation.clear();
8730 if (animLayerAdjustment != 0) {
8731 animLayerAdjustment = 0;
8732 updateLayers();
8733 }
Romain Guy06882f82009-06-10 13:36:04 -07008734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008735 final int N = windows.size();
8736 for (int i=0; i<N; i++) {
8737 ((WindowState)windows.get(i)).finishExit();
8738 }
8739 updateReportedVisibilityLocked();
Romain Guy06882f82009-06-10 13:36:04 -07008740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008741 return false;
8742 }
8743
8744 void updateReportedVisibilityLocked() {
8745 if (appToken == null) {
8746 return;
8747 }
Romain Guy06882f82009-06-10 13:36:04 -07008748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008749 int numInteresting = 0;
8750 int numVisible = 0;
8751 boolean nowGone = true;
Romain Guy06882f82009-06-10 13:36:04 -07008752
Joe Onorato8a9b2202010-02-26 18:56:32 -08008753 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008754 final int N = allAppWindows.size();
8755 for (int i=0; i<N; i++) {
8756 WindowState win = allAppWindows.get(i);
Dianne Hackborn6cf67fa2009-12-21 16:46:34 -08008757 if (win == startingWindow || win.mAppFreezing
The Android Open Source Project727cec02010-04-08 11:35:37 -07008758 || win.mViewVisibility != View.VISIBLE
8759 || win.mAttrs.type == TYPE_APPLICATION_STARTING) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008760 continue;
8761 }
8762 if (DEBUG_VISIBILITY) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008763 Slog.v(TAG, "Win " + win + ": isDrawn="
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008764 + win.isDrawnLw()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008765 + ", isAnimating=" + win.isAnimating());
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008766 if (!win.isDrawnLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008767 Slog.v(TAG, "Not displayed: s=" + win.mSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008768 + " pv=" + win.mPolicyVisibility
8769 + " dp=" + win.mDrawPending
8770 + " cdp=" + win.mCommitDrawPending
8771 + " ah=" + win.mAttachedHidden
8772 + " th="
8773 + (win.mAppToken != null
8774 ? win.mAppToken.hiddenRequested : false)
8775 + " a=" + win.mAnimating);
8776 }
8777 }
8778 numInteresting++;
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008779 if (win.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008780 if (!win.isAnimating()) {
8781 numVisible++;
8782 }
8783 nowGone = false;
8784 } else if (win.isAnimating()) {
8785 nowGone = false;
8786 }
8787 }
Romain Guy06882f82009-06-10 13:36:04 -07008788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008789 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008790 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008791 + numInteresting + " visible=" + numVisible);
8792 if (nowVisible != reportedVisible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008793 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008794 TAG, "Visibility changed in " + this
8795 + ": vis=" + nowVisible);
8796 reportedVisible = nowVisible;
8797 Message m = mH.obtainMessage(
8798 H.REPORT_APPLICATION_TOKEN_WINDOWS,
8799 nowVisible ? 1 : 0,
8800 nowGone ? 1 : 0,
8801 this);
8802 mH.sendMessage(m);
8803 }
8804 }
Romain Guy06882f82009-06-10 13:36:04 -07008805
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07008806 WindowState findMainWindow() {
8807 int j = windows.size();
8808 while (j > 0) {
8809 j--;
8810 WindowState win = windows.get(j);
8811 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
8812 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
8813 return win;
8814 }
8815 }
8816 return null;
8817 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008819 void dump(PrintWriter pw, String prefix) {
8820 super.dump(pw, prefix);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008821 if (appToken != null) {
8822 pw.print(prefix); pw.println("app=true");
8823 }
8824 if (allAppWindows.size() > 0) {
8825 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
8826 }
8827 pw.print(prefix); pw.print("groupId="); pw.print(groupId);
Dianne Hackborna8f60182009-09-01 19:01:50 -07008828 pw.print(" appFullscreen="); pw.print(appFullscreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008829 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
8830 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
8831 pw.print(" clientHidden="); pw.print(clientHidden);
8832 pw.print(" willBeHidden="); pw.print(willBeHidden);
8833 pw.print(" reportedVisible="); pw.println(reportedVisible);
8834 if (paused || freezingScreen) {
8835 pw.print(prefix); pw.print("paused="); pw.print(paused);
8836 pw.print(" freezingScreen="); pw.println(freezingScreen);
8837 }
8838 if (numInterestingWindows != 0 || numDrawnWindows != 0
8839 || inPendingTransaction || allDrawn) {
8840 pw.print(prefix); pw.print("numInterestingWindows=");
8841 pw.print(numInterestingWindows);
8842 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
8843 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
8844 pw.print(" allDrawn="); pw.println(allDrawn);
8845 }
8846 if (animating || animation != null) {
8847 pw.print(prefix); pw.print("animating="); pw.print(animating);
8848 pw.print(" animation="); pw.println(animation);
8849 }
8850 if (animLayerAdjustment != 0) {
8851 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
8852 }
8853 if (hasTransformation) {
8854 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
8855 pw.print(" transformation="); transformation.printShortString(pw);
8856 pw.println();
8857 }
8858 if (startingData != null || removed || firstWindowDrawn) {
8859 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
8860 pw.print(" removed="); pw.print(removed);
8861 pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
8862 }
8863 if (startingWindow != null || startingView != null
8864 || startingDisplayed || startingMoved) {
8865 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
8866 pw.print(" startingView="); pw.print(startingView);
8867 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
8868 pw.print(" startingMoved"); pw.println(startingMoved);
8869 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008870 }
8871
8872 @Override
8873 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008874 if (stringName == null) {
8875 StringBuilder sb = new StringBuilder();
8876 sb.append("AppWindowToken{");
8877 sb.append(Integer.toHexString(System.identityHashCode(this)));
8878 sb.append(" token="); sb.append(token); sb.append('}');
8879 stringName = sb.toString();
8880 }
8881 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008882 }
8883 }
Romain Guy06882f82009-06-10 13:36:04 -07008884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008885 // -------------------------------------------------------------
8886 // DummyAnimation
8887 // -------------------------------------------------------------
8888
8889 // This is an animation that does nothing: it just immediately finishes
8890 // itself every time it is called. It is used as a stub animation in cases
8891 // where we want to synchronize multiple things that may be animating.
8892 static final class DummyAnimation extends Animation {
8893 public boolean getTransformation(long currentTime, Transformation outTransformation) {
8894 return false;
8895 }
8896 }
8897 static final Animation sDummyAnimation = new DummyAnimation();
Romain Guy06882f82009-06-10 13:36:04 -07008898
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008899 // -------------------------------------------------------------
8900 // Async Handler
8901 // -------------------------------------------------------------
8902
8903 static final class StartingData {
8904 final String pkg;
8905 final int theme;
8906 final CharSequence nonLocalizedLabel;
8907 final int labelRes;
8908 final int icon;
Romain Guy06882f82009-06-10 13:36:04 -07008909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008910 StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
8911 int _labelRes, int _icon) {
8912 pkg = _pkg;
8913 theme = _theme;
8914 nonLocalizedLabel = _nonLocalizedLabel;
8915 labelRes = _labelRes;
8916 icon = _icon;
8917 }
8918 }
8919
8920 private final class H extends Handler {
8921 public static final int REPORT_FOCUS_CHANGE = 2;
8922 public static final int REPORT_LOSING_FOCUS = 3;
8923 public static final int ANIMATE = 4;
8924 public static final int ADD_STARTING = 5;
8925 public static final int REMOVE_STARTING = 6;
8926 public static final int FINISHED_STARTING = 7;
8927 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008928 public static final int WINDOW_FREEZE_TIMEOUT = 11;
8929 public static final int HOLD_SCREEN_CHANGED = 12;
8930 public static final int APP_TRANSITION_TIMEOUT = 13;
8931 public static final int PERSIST_ANIMATION_SCALE = 14;
8932 public static final int FORCE_GC = 15;
8933 public static final int ENABLE_SCREEN = 16;
8934 public static final int APP_FREEZE_TIMEOUT = 17;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008935 public static final int SEND_NEW_CONFIGURATION = 18;
Romain Guy06882f82009-06-10 13:36:04 -07008936
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008937 private Session mLastReportedHold;
Romain Guy06882f82009-06-10 13:36:04 -07008938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008939 public H() {
8940 }
Romain Guy06882f82009-06-10 13:36:04 -07008941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008942 @Override
8943 public void handleMessage(Message msg) {
8944 switch (msg.what) {
8945 case REPORT_FOCUS_CHANGE: {
8946 WindowState lastFocus;
8947 WindowState newFocus;
Romain Guy06882f82009-06-10 13:36:04 -07008948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008949 synchronized(mWindowMap) {
8950 lastFocus = mLastFocus;
8951 newFocus = mCurrentFocus;
8952 if (lastFocus == newFocus) {
8953 // Focus is not changing, so nothing to do.
8954 return;
8955 }
8956 mLastFocus = newFocus;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008957 //Slog.i(TAG, "Focus moving from " + lastFocus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008958 // + " to " + newFocus);
8959 if (newFocus != null && lastFocus != null
8960 && !newFocus.isDisplayedLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008961 //Slog.i(TAG, "Delaying loss of focus...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008962 mLosingFocus.add(lastFocus);
8963 lastFocus = null;
8964 }
8965 }
8966
8967 if (lastFocus != newFocus) {
8968 //System.out.println("Changing focus from " + lastFocus
8969 // + " to " + newFocus);
8970 if (newFocus != null) {
8971 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008972 //Slog.i(TAG, "Gaining focus: " + newFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008973 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
8974 } catch (RemoteException e) {
8975 // Ignore if process has died.
8976 }
8977 }
8978
8979 if (lastFocus != null) {
8980 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008981 //Slog.i(TAG, "Losing focus: " + lastFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008982 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
8983 } catch (RemoteException e) {
8984 // Ignore if process has died.
8985 }
8986 }
8987 }
8988 } break;
8989
8990 case REPORT_LOSING_FOCUS: {
8991 ArrayList<WindowState> losers;
Romain Guy06882f82009-06-10 13:36:04 -07008992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008993 synchronized(mWindowMap) {
8994 losers = mLosingFocus;
8995 mLosingFocus = new ArrayList<WindowState>();
8996 }
8997
8998 final int N = losers.size();
8999 for (int i=0; i<N; i++) {
9000 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009001 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009002 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
9003 } catch (RemoteException e) {
9004 // Ignore if process has died.
9005 }
9006 }
9007 } break;
9008
9009 case ANIMATE: {
9010 synchronized(mWindowMap) {
9011 mAnimationPending = false;
9012 performLayoutAndPlaceSurfacesLocked();
9013 }
9014 } break;
9015
9016 case ADD_STARTING: {
9017 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9018 final StartingData sd = wtoken.startingData;
9019
9020 if (sd == null) {
9021 // Animation has been canceled... do nothing.
9022 return;
9023 }
Romain Guy06882f82009-06-10 13:36:04 -07009024
Joe Onorato8a9b2202010-02-26 18:56:32 -08009025 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009026 + wtoken + ": pkg=" + sd.pkg);
Romain Guy06882f82009-06-10 13:36:04 -07009027
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009028 View view = null;
9029 try {
9030 view = mPolicy.addStartingWindow(
9031 wtoken.token, sd.pkg,
9032 sd.theme, sd.nonLocalizedLabel, sd.labelRes,
9033 sd.icon);
9034 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009035 Slog.w(TAG, "Exception when adding starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009036 }
9037
9038 if (view != null) {
9039 boolean abort = false;
9040
9041 synchronized(mWindowMap) {
9042 if (wtoken.removed || wtoken.startingData == null) {
9043 // If the window was successfully added, then
9044 // we need to remove it.
9045 if (wtoken.startingWindow != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009046 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009047 "Aborted starting " + wtoken
9048 + ": removed=" + wtoken.removed
9049 + " startingData=" + wtoken.startingData);
9050 wtoken.startingWindow = null;
9051 wtoken.startingData = null;
9052 abort = true;
9053 }
9054 } else {
9055 wtoken.startingView = view;
9056 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009057 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009058 "Added starting " + wtoken
9059 + ": startingWindow="
9060 + wtoken.startingWindow + " startingView="
9061 + wtoken.startingView);
9062 }
9063
9064 if (abort) {
9065 try {
9066 mPolicy.removeStartingWindow(wtoken.token, view);
9067 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009068 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009069 }
9070 }
9071 }
9072 } break;
9073
9074 case REMOVE_STARTING: {
9075 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9076 IBinder token = null;
9077 View view = null;
9078 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009079 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009080 + wtoken + ": startingWindow="
9081 + wtoken.startingWindow + " startingView="
9082 + wtoken.startingView);
9083 if (wtoken.startingWindow != null) {
9084 view = wtoken.startingView;
9085 token = wtoken.token;
9086 wtoken.startingData = null;
9087 wtoken.startingView = null;
9088 wtoken.startingWindow = null;
9089 }
9090 }
9091 if (view != null) {
9092 try {
9093 mPolicy.removeStartingWindow(token, view);
9094 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009095 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009096 }
9097 }
9098 } break;
9099
9100 case FINISHED_STARTING: {
9101 IBinder token = null;
9102 View view = null;
9103 while (true) {
9104 synchronized (mWindowMap) {
9105 final int N = mFinishedStarting.size();
9106 if (N <= 0) {
9107 break;
9108 }
9109 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
9110
Joe Onorato8a9b2202010-02-26 18:56:32 -08009111 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009112 "Finished starting " + wtoken
9113 + ": startingWindow=" + wtoken.startingWindow
9114 + " startingView=" + wtoken.startingView);
9115
9116 if (wtoken.startingWindow == null) {
9117 continue;
9118 }
9119
9120 view = wtoken.startingView;
9121 token = wtoken.token;
9122 wtoken.startingData = null;
9123 wtoken.startingView = null;
9124 wtoken.startingWindow = null;
9125 }
9126
9127 try {
9128 mPolicy.removeStartingWindow(token, view);
9129 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009130 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009131 }
9132 }
9133 } break;
9134
9135 case REPORT_APPLICATION_TOKEN_WINDOWS: {
9136 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9137
9138 boolean nowVisible = msg.arg1 != 0;
9139 boolean nowGone = msg.arg2 != 0;
9140
9141 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009142 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009143 TAG, "Reporting visible in " + wtoken
9144 + " visible=" + nowVisible
9145 + " gone=" + nowGone);
9146 if (nowVisible) {
9147 wtoken.appToken.windowsVisible();
9148 } else {
9149 wtoken.appToken.windowsGone();
9150 }
9151 } catch (RemoteException ex) {
9152 }
9153 } break;
Romain Guy06882f82009-06-10 13:36:04 -07009154
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009155 case WINDOW_FREEZE_TIMEOUT: {
9156 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009157 Slog.w(TAG, "Window freeze timeout expired.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 int i = mWindows.size();
9159 while (i > 0) {
9160 i--;
9161 WindowState w = (WindowState)mWindows.get(i);
9162 if (w.mOrientationChanging) {
9163 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009164 Slog.w(TAG, "Force clearing orientation change: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009165 }
9166 }
9167 performLayoutAndPlaceSurfacesLocked();
9168 }
9169 break;
9170 }
Romain Guy06882f82009-06-10 13:36:04 -07009171
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009172 case HOLD_SCREEN_CHANGED: {
9173 Session oldHold;
9174 Session newHold;
9175 synchronized (mWindowMap) {
9176 oldHold = mLastReportedHold;
9177 newHold = (Session)msg.obj;
9178 mLastReportedHold = newHold;
9179 }
Romain Guy06882f82009-06-10 13:36:04 -07009180
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009181 if (oldHold != newHold) {
9182 try {
9183 if (oldHold != null) {
9184 mBatteryStats.noteStopWakelock(oldHold.mUid,
9185 "window",
9186 BatteryStats.WAKE_TYPE_WINDOW);
9187 }
9188 if (newHold != null) {
9189 mBatteryStats.noteStartWakelock(newHold.mUid,
9190 "window",
9191 BatteryStats.WAKE_TYPE_WINDOW);
9192 }
9193 } catch (RemoteException e) {
9194 }
9195 }
9196 break;
9197 }
Romain Guy06882f82009-06-10 13:36:04 -07009198
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009199 case APP_TRANSITION_TIMEOUT: {
9200 synchronized (mWindowMap) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009201 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009202 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009203 "*** APP TRANSITION TIMEOUT");
9204 mAppTransitionReady = true;
9205 mAppTransitionTimeout = true;
9206 performLayoutAndPlaceSurfacesLocked();
9207 }
9208 }
9209 break;
9210 }
Romain Guy06882f82009-06-10 13:36:04 -07009211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009212 case PERSIST_ANIMATION_SCALE: {
9213 Settings.System.putFloat(mContext.getContentResolver(),
9214 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
9215 Settings.System.putFloat(mContext.getContentResolver(),
9216 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
9217 break;
9218 }
Romain Guy06882f82009-06-10 13:36:04 -07009219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220 case FORCE_GC: {
9221 synchronized(mWindowMap) {
9222 if (mAnimationPending) {
9223 // If we are animating, don't do the gc now but
9224 // delay a bit so we don't interrupt the animation.
9225 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
9226 2000);
9227 return;
9228 }
9229 // If we are currently rotating the display, it will
9230 // schedule a new message when done.
9231 if (mDisplayFrozen) {
9232 return;
9233 }
9234 mFreezeGcPending = 0;
9235 }
9236 Runtime.getRuntime().gc();
9237 break;
9238 }
Romain Guy06882f82009-06-10 13:36:04 -07009239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009240 case ENABLE_SCREEN: {
9241 performEnableScreen();
9242 break;
9243 }
Romain Guy06882f82009-06-10 13:36:04 -07009244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009245 case APP_FREEZE_TIMEOUT: {
9246 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009247 Slog.w(TAG, "App freeze timeout expired.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009248 int i = mAppTokens.size();
9249 while (i > 0) {
9250 i--;
9251 AppWindowToken tok = mAppTokens.get(i);
9252 if (tok.freezingScreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009253 Slog.w(TAG, "Force clearing freeze: " + tok);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009254 unsetAppFreezingScreenLocked(tok, true, true);
9255 }
9256 }
9257 }
9258 break;
9259 }
Romain Guy06882f82009-06-10 13:36:04 -07009260
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009261 case SEND_NEW_CONFIGURATION: {
9262 removeMessages(SEND_NEW_CONFIGURATION);
9263 sendNewConfiguration();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07009264 break;
9265 }
Romain Guy06882f82009-06-10 13:36:04 -07009266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009267 }
9268 }
9269 }
9270
9271 // -------------------------------------------------------------
9272 // IWindowManager API
9273 // -------------------------------------------------------------
9274
9275 public IWindowSession openSession(IInputMethodClient client,
9276 IInputContext inputContext) {
9277 if (client == null) throw new IllegalArgumentException("null client");
9278 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
9279 return new Session(client, inputContext);
9280 }
9281
9282 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
9283 synchronized (mWindowMap) {
9284 // The focus for the client is the window immediately below
9285 // where we would place the input method window.
9286 int idx = findDesiredInputMethodWindowIndexLocked(false);
9287 WindowState imFocus;
9288 if (idx > 0) {
9289 imFocus = (WindowState)mWindows.get(idx-1);
9290 if (imFocus != null) {
9291 if (imFocus.mSession.mClient != null &&
9292 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
9293 return true;
9294 }
9295 }
9296 }
9297 }
9298 return false;
9299 }
Romain Guy06882f82009-06-10 13:36:04 -07009300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009301 // -------------------------------------------------------------
9302 // Internals
9303 // -------------------------------------------------------------
9304
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009305 final WindowState windowForClientLocked(Session session, IWindow client,
9306 boolean throwOnError) {
9307 return windowForClientLocked(session, client.asBinder(), throwOnError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009308 }
Romain Guy06882f82009-06-10 13:36:04 -07009309
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009310 final WindowState windowForClientLocked(Session session, IBinder client,
9311 boolean throwOnError) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009312 WindowState win = mWindowMap.get(client);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009313 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009314 TAG, "Looking up client " + client + ": " + win);
9315 if (win == null) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009316 RuntimeException ex = new IllegalArgumentException(
9317 "Requested window " + client + " does not exist");
9318 if (throwOnError) {
9319 throw ex;
9320 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009321 Slog.w(TAG, "Failed looking up window", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009322 return null;
9323 }
9324 if (session != null && win.mSession != session) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009325 RuntimeException ex = new IllegalArgumentException(
9326 "Requested window " + client + " is in session " +
9327 win.mSession + ", not " + session);
9328 if (throwOnError) {
9329 throw ex;
9330 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009331 Slog.w(TAG, "Failed looking up window", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009332 return null;
9333 }
9334
9335 return win;
9336 }
9337
Dianne Hackborna8f60182009-09-01 19:01:50 -07009338 final void rebuildAppWindowListLocked() {
9339 int NW = mWindows.size();
9340 int i;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009341 int lastWallpaper = -1;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009342 int numRemoved = 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009343
Dianne Hackborna8f60182009-09-01 19:01:50 -07009344 // First remove all existing app windows.
9345 i=0;
9346 while (i < NW) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009347 WindowState w = (WindowState)mWindows.get(i);
9348 if (w.mAppToken != null) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009349 WindowState win = (WindowState)mWindows.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009350 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009351 "Rebuild removing window: " + win);
Dianne Hackborna8f60182009-09-01 19:01:50 -07009352 NW--;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009353 numRemoved++;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009354 continue;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009355 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
9356 && lastWallpaper == i-1) {
9357 lastWallpaper = i;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009358 }
9359 i++;
9360 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009361
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009362 // The wallpaper window(s) typically live at the bottom of the stack,
9363 // so skip them before adding app tokens.
9364 lastWallpaper++;
9365 i = lastWallpaper;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009366
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009367 // First add all of the exiting app tokens... these are no longer
9368 // in the main app list, but still have windows shown. We put them
9369 // in the back because now that the animation is over we no longer
9370 // will care about them.
9371 int NT = mExitingAppTokens.size();
Dianne Hackborna8f60182009-09-01 19:01:50 -07009372 for (int j=0; j<NT; j++) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009373 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
9374 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009375
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009376 // And add in the still active app tokens in Z order.
9377 NT = mAppTokens.size();
9378 for (int j=0; j<NT; j++) {
9379 i = reAddAppWindowsLocked(i, mAppTokens.get(j));
Dianne Hackborna8f60182009-09-01 19:01:50 -07009380 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009381
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009382 i -= lastWallpaper;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009383 if (i != numRemoved) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009384 Slog.w(TAG, "Rebuild removed " + numRemoved
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009385 + " windows but added " + i);
9386 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07009387 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009388
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009389 private final void assignLayersLocked() {
9390 int N = mWindows.size();
9391 int curBaseLayer = 0;
9392 int curLayer = 0;
9393 int i;
Romain Guy06882f82009-06-10 13:36:04 -07009394
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009395 for (i=0; i<N; i++) {
9396 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009397 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
9398 || (i > 0 && w.mIsWallpaper)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009399 curLayer += WINDOW_LAYER_MULTIPLIER;
9400 w.mLayer = curLayer;
9401 } else {
9402 curBaseLayer = curLayer = w.mBaseLayer;
9403 w.mLayer = curLayer;
9404 }
9405 if (w.mTargetAppToken != null) {
9406 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
9407 } else if (w.mAppToken != null) {
9408 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
9409 } else {
9410 w.mAnimLayer = w.mLayer;
9411 }
9412 if (w.mIsImWindow) {
9413 w.mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07009414 } else if (w.mIsWallpaper) {
9415 w.mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009416 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009417 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009418 + w.mAnimLayer);
9419 //System.out.println(
9420 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
9421 }
9422 }
9423
9424 private boolean mInLayout = false;
9425 private final void performLayoutAndPlaceSurfacesLocked() {
9426 if (mInLayout) {
Dave Bortcfe65242009-04-09 14:51:04 -07009427 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009428 throw new RuntimeException("Recursive call!");
9429 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009430 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009431 return;
9432 }
9433
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009434 if (mWaitingForConfig) {
9435 // Our configuration has changed (most likely rotation), but we
9436 // don't yet have the complete configuration to report to
9437 // applications. Don't do any window layout until we have it.
9438 return;
9439 }
9440
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009441 boolean recoveringMemory = false;
9442 if (mForceRemoves != null) {
9443 recoveringMemory = true;
9444 // Wait a little it for things to settle down, and off we go.
9445 for (int i=0; i<mForceRemoves.size(); i++) {
9446 WindowState ws = mForceRemoves.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009447 Slog.i(TAG, "Force removing: " + ws);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009448 removeWindowInnerLocked(ws.mSession, ws);
9449 }
9450 mForceRemoves = null;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009451 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009452 Object tmp = new Object();
9453 synchronized (tmp) {
9454 try {
9455 tmp.wait(250);
9456 } catch (InterruptedException e) {
9457 }
9458 }
9459 }
Romain Guy06882f82009-06-10 13:36:04 -07009460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009461 mInLayout = true;
9462 try {
9463 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
Romain Guy06882f82009-06-10 13:36:04 -07009464
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 int i = mPendingRemove.size()-1;
9466 if (i >= 0) {
9467 while (i >= 0) {
9468 WindowState w = mPendingRemove.get(i);
9469 removeWindowInnerLocked(w.mSession, w);
9470 i--;
9471 }
9472 mPendingRemove.clear();
9473
9474 mInLayout = false;
9475 assignLayersLocked();
9476 mLayoutNeeded = true;
9477 performLayoutAndPlaceSurfacesLocked();
9478
9479 } else {
9480 mInLayout = false;
9481 if (mLayoutNeeded) {
9482 requestAnimationLocked(0);
9483 }
9484 }
9485 } catch (RuntimeException e) {
9486 mInLayout = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009487 Slog.e(TAG, "Unhandled exception while layout out windows", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009488 }
9489 }
9490
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009491 private final int performLayoutLockedInner() {
9492 if (!mLayoutNeeded) {
9493 return 0;
9494 }
9495
9496 mLayoutNeeded = false;
9497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009498 final int dw = mDisplay.getWidth();
9499 final int dh = mDisplay.getHeight();
9500
9501 final int N = mWindows.size();
9502 int i;
9503
Joe Onorato8a9b2202010-02-26 18:56:32 -08009504 if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed="
Dianne Hackborn9b52a212009-12-11 14:51:35 -08009505 + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
9506
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009507 mPolicy.beginLayoutLw(dw, dh);
Romain Guy06882f82009-06-10 13:36:04 -07009508
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009509 int seq = mLayoutSeq+1;
9510 if (seq < 0) seq = 0;
9511 mLayoutSeq = seq;
9512
9513 // First perform layout of any root windows (not attached
9514 // to another window).
9515 int topAttached = -1;
9516 for (i = N-1; i >= 0; i--) {
9517 WindowState win = (WindowState) mWindows.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009518
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009519 // Don't do layout of a window if it is not visible, or
9520 // soon won't be visible, to avoid wasting time and funky
9521 // changes while a window is animating away.
9522 final AppWindowToken atoken = win.mAppToken;
9523 final boolean gone = win.mViewVisibility == View.GONE
9524 || !win.mRelayoutCalled
9525 || win.mRootToken.hidden
9526 || (atoken != null && atoken.hiddenRequested)
9527 || win.mAttachedHidden
9528 || win.mExiting || win.mDestroying;
9529
9530 if (!win.mLayoutAttached) {
9531 if (DEBUG_LAYOUT) Slog.v(TAG, "First pass " + win
9532 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
9533 + " mLayoutAttached=" + win.mLayoutAttached);
9534 if (DEBUG_LAYOUT && gone) Slog.v(TAG, " (mViewVisibility="
9535 + win.mViewVisibility + " mRelayoutCalled="
9536 + win.mRelayoutCalled + " hidden="
9537 + win.mRootToken.hidden + " hiddenRequested="
9538 + (atoken != null && atoken.hiddenRequested)
9539 + " mAttachedHidden=" + win.mAttachedHidden);
9540 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009541
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009542 // If this view is GONE, then skip it -- keep the current
9543 // frame, and let the caller know so they can ignore it
9544 // if they want. (We do the normal layout for INVISIBLE
9545 // windows, since that means "perform layout as normal,
9546 // just don't display").
9547 if (!gone || !win.mHaveFrame) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009548 if (!win.mLayoutAttached) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009549 mPolicy.layoutWindowLw(win, win.mAttrs, null);
9550 win.mLayoutSeq = seq;
9551 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
9552 + win.mFrame + " mContainingFrame="
9553 + win.mContainingFrame + " mDisplayFrame="
9554 + win.mDisplayFrame);
9555 } else {
9556 if (topAttached < 0) topAttached = i;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009557 }
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07009558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009559 }
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009560
9561 // Now perform layout of attached windows, which usually
9562 // depend on the position of the window they are attached to.
9563 // XXX does not deal with windows that are attached to windows
9564 // that are themselves attached.
9565 for (i = topAttached; i >= 0; i--) {
9566 WindowState win = (WindowState) mWindows.get(i);
9567
9568 // If this view is GONE, then skip it -- keep the current
9569 // frame, and let the caller know so they can ignore it
9570 // if they want. (We do the normal layout for INVISIBLE
9571 // windows, since that means "perform layout as normal,
9572 // just don't display").
9573 if (win.mLayoutAttached) {
9574 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win
9575 + " mHaveFrame=" + win.mHaveFrame
9576 + " mViewVisibility=" + win.mViewVisibility
9577 + " mRelayoutCalled=" + win.mRelayoutCalled);
9578 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
9579 || !win.mHaveFrame) {
9580 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
9581 win.mLayoutSeq = seq;
9582 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
9583 + win.mFrame + " mContainingFrame="
9584 + win.mContainingFrame + " mDisplayFrame="
9585 + win.mDisplayFrame);
9586 }
9587 }
9588 }
9589
9590 return mPolicy.finishLayoutLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009591 }
Romain Guy06882f82009-06-10 13:36:04 -07009592
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009593 private final void performLayoutAndPlaceSurfacesLockedInner(
9594 boolean recoveringMemory) {
9595 final long currentTime = SystemClock.uptimeMillis();
9596 final int dw = mDisplay.getWidth();
9597 final int dh = mDisplay.getHeight();
9598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009599 int i;
9600
Dianne Hackbornb601ce12010-03-01 23:36:02 -08009601 if (mFocusMayChange) {
9602 mFocusMayChange = false;
9603 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
9604 }
9605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009606 if (mFxSession == null) {
9607 mFxSession = new SurfaceSession();
9608 }
Romain Guy06882f82009-06-10 13:36:04 -07009609
Joe Onorato8a9b2202010-02-26 18:56:32 -08009610 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009611
9612 // Initialize state of exiting tokens.
9613 for (i=mExitingTokens.size()-1; i>=0; i--) {
9614 mExitingTokens.get(i).hasVisible = false;
9615 }
9616
9617 // Initialize state of exiting applications.
9618 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
9619 mExitingAppTokens.get(i).hasVisible = false;
9620 }
9621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009622 boolean orientationChangeComplete = true;
9623 Session holdScreen = null;
9624 float screenBrightness = -1;
Mike Lockwoodfb73f792009-11-20 11:31:18 -05009625 float buttonBrightness = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009626 boolean focusDisplayed = false;
9627 boolean animating = false;
9628
9629 Surface.openTransaction();
9630 try {
Dianne Hackbornde2606d2009-12-18 16:53:55 -08009631 boolean wallpaperForceHidingChanged = false;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009632 int repeats = 0;
9633 int changes = 0;
9634
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009635 do {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009636 repeats++;
9637 if (repeats > 6) {
9638 Slog.w(TAG, "Animation repeat aborted after too many iterations");
9639 mLayoutNeeded = false;
9640 break;
9641 }
9642
9643 if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER
9644 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG
9645 | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) {
9646 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
9647 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9648 assignLayersLocked();
9649 mLayoutNeeded = true;
9650 }
9651 }
9652 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9653 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9654 if (updateOrientationFromAppTokensLocked()) {
9655 mLayoutNeeded = true;
9656 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9657 }
9658 }
9659 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9660 mLayoutNeeded = true;
9661 }
9662 }
9663
9664 // FIRST LOOP: Perform a layout, if needed.
9665 if (repeats < 4) {
9666 changes = performLayoutLockedInner();
9667 if (changes != 0) {
9668 continue;
9669 }
9670 } else {
9671 Slog.w(TAG, "Layout repeat skipped after too many iterations");
9672 changes = 0;
9673 }
9674
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009675 final int transactionSequence = ++mTransactionSequence;
9676
9677 // Update animations of all applications, including those
9678 // associated with exiting/removed apps
9679 boolean tokensAnimating = false;
9680 final int NAT = mAppTokens.size();
9681 for (i=0; i<NAT; i++) {
9682 if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
9683 tokensAnimating = true;
9684 }
9685 }
9686 final int NEAT = mExitingAppTokens.size();
9687 for (i=0; i<NEAT; i++) {
9688 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
9689 tokensAnimating = true;
9690 }
9691 }
9692
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009693 // SECOND LOOP: Execute animations and update visibility of windows.
9694
Joe Onorato8a9b2202010-02-26 18:56:32 -08009695 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
Dianne Hackbornde2606d2009-12-18 16:53:55 -08009696 + transactionSequence + " tokensAnimating="
9697 + tokensAnimating);
9698
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009699 animating = tokensAnimating;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009700
9701 boolean tokenMayBeDrawn = false;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009702 boolean wallpaperMayChange = false;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009703 boolean forceHiding = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009704
9705 mPolicy.beginAnimationLw(dw, dh);
9706
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009707 final int N = mWindows.size();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009708
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009709 for (i=N-1; i>=0; i--) {
9710 WindowState w = (WindowState)mWindows.get(i);
9711
9712 final WindowManager.LayoutParams attrs = w.mAttrs;
9713
9714 if (w.mSurface != null) {
9715 // Execute animation.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009716 if (w.commitFinishDrawingLocked(currentTime)) {
9717 if ((w.mAttrs.flags
9718 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009719 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009720 "First draw done in potential wallpaper target " + w);
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009721 wallpaperMayChange = true;
9722 }
9723 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009724
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009725 boolean wasAnimating = w.mAnimating;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009726 if (w.stepAnimationLocked(currentTime, dw, dh)) {
9727 animating = true;
9728 //w.dump(" ");
9729 }
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009730 if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
9731 wallpaperMayChange = true;
9732 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009733
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009734 if (mPolicy.doesForceHide(w, attrs)) {
9735 if (!wasAnimating && animating) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08009736 if (DEBUG_VISIBILITY) Slog.v(TAG,
9737 "Animation done that could impact force hide: "
9738 + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009739 wallpaperForceHidingChanged = true;
Dianne Hackbornb601ce12010-03-01 23:36:02 -08009740 mFocusMayChange = true;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009741 } else if (w.isReadyForDisplay() && w.mAnimation == null) {
9742 forceHiding = true;
9743 }
9744 } else if (mPolicy.canBeForceHidden(w, attrs)) {
9745 boolean changed;
9746 if (forceHiding) {
9747 changed = w.hideLw(false, false);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08009748 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
9749 "Now policy hidden: " + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009750 } else {
9751 changed = w.showLw(false, false);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08009752 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
9753 "Now policy shown: " + w);
9754 if (changed) {
9755 if (wallpaperForceHidingChanged
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009756 && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08009757 // Assume we will need to animate. If
9758 // we don't (because the wallpaper will
9759 // stay with the lock screen), then we will
9760 // clean up later.
9761 Animation a = mPolicy.createForceHideEnterAnimation();
9762 if (a != null) {
9763 w.setAnimation(a);
9764 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009765 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08009766 if (mCurrentFocus == null ||
9767 mCurrentFocus.mLayer < w.mLayer) {
9768 // We are showing on to of the current
9769 // focus, so re-evaluate focus to make
9770 // sure it is correct.
9771 mFocusMayChange = true;
9772 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009773 }
9774 }
9775 if (changed && (attrs.flags
9776 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
9777 wallpaperMayChange = true;
9778 }
9779 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009781 mPolicy.animatingWindowLw(w, attrs);
9782 }
9783
9784 final AppWindowToken atoken = w.mAppToken;
9785 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
9786 if (atoken.lastTransactionSequence != transactionSequence) {
9787 atoken.lastTransactionSequence = transactionSequence;
9788 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9789 atoken.startingDisplayed = false;
9790 }
9791 if ((w.isOnScreen() || w.mAttrs.type
9792 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
9793 && !w.mExiting && !w.mDestroying) {
9794 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009795 Slog.v(TAG, "Eval win " + w + ": isDrawn="
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009796 + w.isDrawnLw()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009797 + ", isAnimating=" + w.isAnimating());
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009798 if (!w.isDrawnLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009799 Slog.v(TAG, "Not displayed: s=" + w.mSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009800 + " pv=" + w.mPolicyVisibility
9801 + " dp=" + w.mDrawPending
9802 + " cdp=" + w.mCommitDrawPending
9803 + " ah=" + w.mAttachedHidden
9804 + " th=" + atoken.hiddenRequested
9805 + " a=" + w.mAnimating);
9806 }
9807 }
9808 if (w != atoken.startingWindow) {
9809 if (!atoken.freezingScreen || !w.mAppFreezing) {
9810 atoken.numInterestingWindows++;
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009811 if (w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009812 atoken.numDrawnWindows++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009813 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009814 "tokenMayBeDrawn: " + atoken
9815 + " freezingScreen=" + atoken.freezingScreen
9816 + " mAppFreezing=" + w.mAppFreezing);
9817 tokenMayBeDrawn = true;
9818 }
9819 }
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009820 } else if (w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 atoken.startingDisplayed = true;
9822 }
9823 }
9824 } else if (w.mReadyToShow) {
9825 w.performShowLocked();
9826 }
9827 }
9828
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009829 changes |= mPolicy.finishAnimationLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009830
9831 if (tokenMayBeDrawn) {
9832 // See if any windows have been drawn, so they (and others
9833 // associated with them) can now be shown.
9834 final int NT = mTokenList.size();
9835 for (i=0; i<NT; i++) {
9836 AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
9837 if (wtoken == null) {
9838 continue;
9839 }
9840 if (wtoken.freezingScreen) {
9841 int numInteresting = wtoken.numInterestingWindows;
9842 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009843 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009844 "allDrawn: " + wtoken
9845 + " interesting=" + numInteresting
9846 + " drawn=" + wtoken.numDrawnWindows);
9847 wtoken.showAllWindowsLocked();
9848 unsetAppFreezingScreenLocked(wtoken, false, true);
9849 orientationChangeComplete = true;
9850 }
9851 } else if (!wtoken.allDrawn) {
9852 int numInteresting = wtoken.numInterestingWindows;
9853 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009854 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009855 "allDrawn: " + wtoken
9856 + " interesting=" + numInteresting
9857 + " drawn=" + wtoken.numDrawnWindows);
9858 wtoken.allDrawn = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009859 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009860
9861 // We can now show all of the drawn windows!
9862 if (!mOpeningApps.contains(wtoken)) {
9863 wtoken.showAllWindowsLocked();
9864 }
9865 }
9866 }
9867 }
9868 }
9869
9870 // If we are ready to perform an app transition, check through
9871 // all of the app tokens to be shown and see if they are ready
9872 // to go.
9873 if (mAppTransitionReady) {
9874 int NN = mOpeningApps.size();
9875 boolean goodToGo = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009876 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009877 "Checking " + NN + " opening apps (frozen="
9878 + mDisplayFrozen + " timeout="
9879 + mAppTransitionTimeout + ")...");
9880 if (!mDisplayFrozen && !mAppTransitionTimeout) {
9881 // If the display isn't frozen, wait to do anything until
9882 // all of the apps are ready. Otherwise just go because
9883 // we'll unfreeze the display when everyone is ready.
9884 for (i=0; i<NN && goodToGo; i++) {
9885 AppWindowToken wtoken = mOpeningApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009886 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009887 "Check opening app" + wtoken + ": allDrawn="
9888 + wtoken.allDrawn + " startingDisplayed="
9889 + wtoken.startingDisplayed);
9890 if (!wtoken.allDrawn && !wtoken.startingDisplayed
9891 && !wtoken.startingMoved) {
9892 goodToGo = false;
9893 }
9894 }
9895 }
9896 if (goodToGo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009897 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009898 int transit = mNextAppTransition;
9899 if (mSkipAppTransitionAnimation) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009900 transit = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009901 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009902 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009903 mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009904 mAppTransitionRunning = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009905 mAppTransitionTimeout = false;
9906 mStartingIconInTransition = false;
9907 mSkipAppTransitionAnimation = false;
9908
9909 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
9910
Dianne Hackborna8f60182009-09-01 19:01:50 -07009911 // If there are applications waiting to come to the
9912 // top of the stack, now is the time to move their windows.
9913 // (Note that we don't do apps going to the bottom
9914 // here -- we want to keep their windows in the old
9915 // Z-order until the animation completes.)
9916 if (mToTopApps.size() > 0) {
9917 NN = mAppTokens.size();
9918 for (i=0; i<NN; i++) {
9919 AppWindowToken wtoken = mAppTokens.get(i);
9920 if (wtoken.sendingToTop) {
9921 wtoken.sendingToTop = false;
9922 moveAppWindowsLocked(wtoken, NN, false);
9923 }
9924 }
9925 mToTopApps.clear();
9926 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009927
Dianne Hackborn25994b42009-09-04 14:21:19 -07009928 WindowState oldWallpaper = mWallpaperTarget;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009929
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009930 adjustWallpaperWindowsLocked();
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009931 wallpaperMayChange = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009932
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009933 // The top-most window will supply the layout params,
9934 // and we will determine it below.
9935 LayoutParams animLp = null;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009936 AppWindowToken animToken = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009937 int bestAnimLayer = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009938
Joe Onorato8a9b2202010-02-26 18:56:32 -08009939 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009940 "New wallpaper target=" + mWallpaperTarget
9941 + ", lower target=" + mLowerWallpaperTarget
9942 + ", upper target=" + mUpperWallpaperTarget);
Dianne Hackborn25994b42009-09-04 14:21:19 -07009943 int foundWallpapers = 0;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009944 // Do a first pass through the tokens for two
9945 // things:
9946 // (1) Determine if both the closing and opening
9947 // app token sets are wallpaper targets, in which
9948 // case special animations are needed
9949 // (since the wallpaper needs to stay static
9950 // behind them).
9951 // (2) Find the layout params of the top-most
9952 // application window in the tokens, which is
9953 // what will control the animation theme.
9954 final int NC = mClosingApps.size();
9955 NN = NC + mOpeningApps.size();
9956 for (i=0; i<NN; i++) {
9957 AppWindowToken wtoken;
9958 int mode;
9959 if (i < NC) {
9960 wtoken = mClosingApps.get(i);
9961 mode = 1;
9962 } else {
9963 wtoken = mOpeningApps.get(i-NC);
9964 mode = 2;
9965 }
9966 if (mLowerWallpaperTarget != null) {
9967 if (mLowerWallpaperTarget.mAppToken == wtoken
9968 || mUpperWallpaperTarget.mAppToken == wtoken) {
9969 foundWallpapers |= mode;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07009970 }
9971 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009972 if (wtoken.appFullscreen) {
9973 WindowState ws = wtoken.findMainWindow();
9974 if (ws != null) {
9975 // If this is a compatibility mode
9976 // window, we will always use its anim.
9977 if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
9978 animLp = ws.mAttrs;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009979 animToken = ws.mAppToken;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009980 bestAnimLayer = Integer.MAX_VALUE;
9981 } else if (ws.mLayer > bestAnimLayer) {
9982 animLp = ws.mAttrs;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009983 animToken = ws.mAppToken;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009984 bestAnimLayer = ws.mLayer;
9985 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07009986 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07009987 }
9988 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009989
Dianne Hackborn25994b42009-09-04 14:21:19 -07009990 if (foundWallpapers == 3) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009991 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07009992 "Wallpaper animation!");
9993 switch (transit) {
9994 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
9995 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
9996 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
9997 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN;
9998 break;
9999 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
10000 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
10001 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
10002 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE;
10003 break;
10004 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010005 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010006 "New transit: " + transit);
10007 } else if (oldWallpaper != null) {
10008 // We are transitioning from an activity with
10009 // a wallpaper to one without.
10010 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010011 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010012 "New transit away from wallpaper: " + transit);
10013 } else if (mWallpaperTarget != null) {
10014 // We are transitioning from an activity without
10015 // a wallpaper to now showing the wallpaper
10016 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010017 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -070010018 "New transit into wallpaper: " + transit);
10019 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010020
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010021 if ((transit&WindowManagerPolicy.TRANSIT_ENTER_MASK) != 0) {
10022 mLastEnterAnimToken = animToken;
10023 mLastEnterAnimParams = animLp;
10024 } else if (mLastEnterAnimParams != null) {
10025 animLp = mLastEnterAnimParams;
10026 mLastEnterAnimToken = null;
10027 mLastEnterAnimParams = null;
10028 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010029
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010030 // If all closing windows are obscured, then there is
10031 // no need to do an animation. This is the case, for
10032 // example, when this transition is being done behind
10033 // the lock screen.
10034 if (!mPolicy.allowAppAnimationsLw()) {
10035 animLp = null;
10036 }
10037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038 NN = mOpeningApps.size();
10039 for (i=0; i<NN; i++) {
10040 AppWindowToken wtoken = mOpeningApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010041 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010042 "Now opening app" + wtoken);
10043 wtoken.reportedVisible = false;
10044 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -070010045 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010046 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010047 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070010048 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010049 wtoken.showAllWindowsLocked();
10050 }
10051 NN = mClosingApps.size();
10052 for (i=0; i<NN; i++) {
10053 AppWindowToken wtoken = mClosingApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010054 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 "Now closing app" + wtoken);
10056 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -070010057 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010058 setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010059 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070010060 wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010061 // Force the allDrawn flag, because we want to start
10062 // this guy's animations regardless of whether it's
10063 // gotten drawn.
10064 wtoken.allDrawn = true;
10065 }
10066
Dianne Hackborn8b571a82009-09-25 16:09:43 -070010067 mNextAppTransitionPackage = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010068
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010069 mOpeningApps.clear();
10070 mClosingApps.clear();
10071
10072 // This has changed the visibility of windows, so perform
10073 // a new layout to get them all up-to-date.
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010074 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010075 mLayoutNeeded = true;
Dianne Hackborn20583ff2009-07-27 21:51:05 -070010076 if (!moveInputMethodWindowsIfNeededLocked(true)) {
10077 assignLayersLocked();
10078 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010079 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010080 mFocusMayChange = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010081 }
10082 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010083
Dianne Hackborn16064f92010-03-25 00:47:24 -070010084 int adjResult = 0;
10085
Dianne Hackborna8f60182009-09-01 19:01:50 -070010086 if (!animating && mAppTransitionRunning) {
10087 // We have finished the animation of an app transition. To do
10088 // this, we have delayed a lot of operations like showing and
10089 // hiding apps, moving apps in Z-order, etc. The app token list
10090 // reflects the correct Z-order, but the window list may now
10091 // be out of sync with it. So here we will just rebuild the
10092 // entire app window list. Fun!
10093 mAppTransitionRunning = false;
10094 // Clear information about apps that were moving.
10095 mToBottomApps.clear();
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010096
Dianne Hackborna8f60182009-09-01 19:01:50 -070010097 rebuildAppWindowListLocked();
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010098 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn16064f92010-03-25 00:47:24 -070010099 adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED;
Dianne Hackborna8f60182009-09-01 19:01:50 -070010100 moveInputMethodWindowsIfNeededLocked(false);
10101 wallpaperMayChange = true;
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -080010102 // Since the window list has been rebuilt, focus might
10103 // have to be recomputed since the actual order of windows
10104 // might have changed again.
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010105 mFocusMayChange = true;
Dianne Hackborna8f60182009-09-01 19:01:50 -070010106 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010107
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010108 if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010109 // At this point, there was a window with a wallpaper that
10110 // was force hiding other windows behind it, but now it
10111 // is going away. This may be simple -- just animate
10112 // away the wallpaper and its window -- or it may be
10113 // hard -- the wallpaper now needs to be shown behind
10114 // something that was hidden.
10115 WindowState oldWallpaper = mWallpaperTarget;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010116 if (mLowerWallpaperTarget != null
10117 && mLowerWallpaperTarget.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010118 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010119 "wallpaperForceHiding changed with lower="
10120 + mLowerWallpaperTarget);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010121 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010122 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden +
10123 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested);
10124 if (mLowerWallpaperTarget.mAppToken.hidden) {
10125 // The lower target has become hidden before we
10126 // actually started the animation... let's completely
10127 // re-evaluate everything.
10128 mLowerWallpaperTarget = mUpperWallpaperTarget = null;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010129 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010130 }
10131 }
Dianne Hackborn16064f92010-03-25 00:47:24 -070010132 adjResult |= adjustWallpaperWindowsLocked();
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010133 wallpaperMayChange = false;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010134 wallpaperForceHidingChanged = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010135 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010136 + " NEW: " + mWallpaperTarget
10137 + " LOWER: " + mLowerWallpaperTarget);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010138 if (mLowerWallpaperTarget == null) {
10139 // Whoops, we don't need a special wallpaper animation.
10140 // Clear them out.
10141 forceHiding = false;
10142 for (i=N-1; i>=0; i--) {
10143 WindowState w = (WindowState)mWindows.get(i);
10144 if (w.mSurface != null) {
10145 final WindowManager.LayoutParams attrs = w.mAttrs;
Suchi Amalapurapuc03d28b2009-10-28 14:32:05 -070010146 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010147 if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010148 forceHiding = true;
10149 } else if (mPolicy.canBeForceHidden(w, attrs)) {
10150 if (!w.mAnimating) {
10151 // We set the animation above so it
10152 // is not yet running.
10153 w.clearAnimation();
10154 }
10155 }
10156 }
10157 }
10158 }
10159 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010160
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010161 if (wallpaperMayChange) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010162 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010163 "Wallpaper may change! Adjusting");
Dianne Hackborn16064f92010-03-25 00:47:24 -070010164 adjResult |= adjustWallpaperWindowsLocked();
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010165 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010166
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010167 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010168 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010169 "Wallpaper layer changed: assigning layers + relayout");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010170 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010171 assignLayersLocked();
10172 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010173 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010174 "Wallpaper visibility changed: relayout");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010175 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010176 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010177
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010178 if (mFocusMayChange) {
10179 mFocusMayChange = false;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010180 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010181 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010182 adjResult = 0;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010183 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010184 }
10185
10186 if (mLayoutNeeded) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010187 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010188 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010189
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010190 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
10191 + Integer.toHexString(changes));
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010192
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010193 } while (changes != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010194
10195 // THIRD LOOP: Update the surfaces of all windows.
10196
10197 final boolean someoneLosingFocus = mLosingFocus.size() != 0;
10198
10199 boolean obscured = false;
10200 boolean blurring = false;
10201 boolean dimming = false;
10202 boolean covered = false;
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070010203 boolean syswin = false;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010204 boolean backgroundFillerShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010205
Dianne Hackbornbdd52b22009-09-02 21:46:19 -070010206 final int N = mWindows.size();
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010208 for (i=N-1; i>=0; i--) {
10209 WindowState w = (WindowState)mWindows.get(i);
10210
10211 boolean displayed = false;
10212 final WindowManager.LayoutParams attrs = w.mAttrs;
10213 final int attrFlags = attrs.flags;
10214
10215 if (w.mSurface != null) {
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010216 // XXX NOTE: The logic here could be improved. We have
10217 // the decision about whether to resize a window separated
10218 // from whether to hide the surface. This can cause us to
10219 // resize a surface even if we are going to hide it. You
10220 // can see this by (1) holding device in landscape mode on
10221 // home screen; (2) tapping browser icon (device will rotate
10222 // to landscape; (3) tap home. The wallpaper will be resized
10223 // in step 2 but then immediately hidden, causing us to
10224 // have to resize and then redraw it again in step 3. It
10225 // would be nice to figure out how to avoid this, but it is
10226 // difficult because we do need to resize surfaces in some
10227 // cases while they are hidden such as when first showing a
10228 // window.
10229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010230 w.computeShownFrameLocked();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010231 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010232 TAG, "Placing surface #" + i + " " + w.mSurface
10233 + ": new=" + w.mShownFrame + ", old="
10234 + w.mLastShownFrame);
10235
10236 boolean resize;
10237 int width, height;
10238 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
10239 resize = w.mLastRequestedWidth != w.mRequestedWidth ||
10240 w.mLastRequestedHeight != w.mRequestedHeight;
10241 // for a scaled surface, we just want to use
10242 // the requested size.
10243 width = w.mRequestedWidth;
10244 height = w.mRequestedHeight;
10245 w.mLastRequestedWidth = width;
10246 w.mLastRequestedHeight = height;
10247 w.mLastShownFrame.set(w.mShownFrame);
10248 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010249 if (SHOW_TRANSACTIONS) logSurface(w,
10250 "POS " + w.mShownFrame.left
10251 + ", " + w.mShownFrame.top, null);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010252 w.mSurfaceX = w.mShownFrame.left;
10253 w.mSurfaceY = w.mShownFrame.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010254 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
10255 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010256 Slog.w(TAG, "Error positioning surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010257 if (!recoveringMemory) {
10258 reclaimSomeSurfaceMemoryLocked(w, "position");
10259 }
10260 }
10261 } else {
10262 resize = !w.mLastShownFrame.equals(w.mShownFrame);
10263 width = w.mShownFrame.width();
10264 height = w.mShownFrame.height();
10265 w.mLastShownFrame.set(w.mShownFrame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010266 }
10267
10268 if (resize) {
10269 if (width < 1) width = 1;
10270 if (height < 1) height = 1;
10271 if (w.mSurface != null) {
10272 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010273 if (SHOW_TRANSACTIONS) logSurface(w,
10274 "POS " + w.mShownFrame.left + ","
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010275 + w.mShownFrame.top + " SIZE "
10276 + w.mShownFrame.width() + "x"
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010277 + w.mShownFrame.height(), null);
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010278 w.mSurfaceResized = true;
Dianne Hackborn16064f92010-03-25 00:47:24 -070010279 w.mSurfaceW = width;
10280 w.mSurfaceH = height;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010281 w.mSurface.setSize(width, height);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010282 w.mSurfaceX = w.mShownFrame.left;
10283 w.mSurfaceY = w.mShownFrame.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010284 w.mSurface.setPosition(w.mShownFrame.left,
10285 w.mShownFrame.top);
10286 } catch (RuntimeException e) {
10287 // If something goes wrong with the surface (such
10288 // as running out of memory), don't take down the
10289 // entire system.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010290 Slog.e(TAG, "Failure updating surface of " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010291 + "size=(" + width + "x" + height
10292 + "), pos=(" + w.mShownFrame.left
10293 + "," + w.mShownFrame.top + ")", e);
10294 if (!recoveringMemory) {
10295 reclaimSomeSurfaceMemoryLocked(w, "size");
10296 }
10297 }
10298 }
10299 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010300 if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010301 w.mContentInsetsChanged =
10302 !w.mLastContentInsets.equals(w.mContentInsets);
10303 w.mVisibleInsetsChanged =
10304 !w.mLastVisibleInsets.equals(w.mVisibleInsets);
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010305 boolean configChanged =
10306 w.mConfiguration != mCurConfiguration
10307 && (w.mConfiguration == null
10308 || mCurConfiguration.diff(w.mConfiguration) != 0);
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010309 if (DEBUG_CONFIGURATION && configChanged) {
10310 Slog.v(TAG, "Win " + w + " config changed: "
10311 + mCurConfiguration);
10312 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010313 if (localLOGV) Slog.v(TAG, "Resizing " + w
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010314 + ": configChanged=" + configChanged
10315 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
Romain Guy06882f82009-06-10 13:36:04 -070010316 if (!w.mLastFrame.equals(w.mFrame)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010317 || w.mContentInsetsChanged
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010318 || w.mVisibleInsetsChanged
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010319 || w.mSurfaceResized
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010320 || configChanged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010321 w.mLastFrame.set(w.mFrame);
10322 w.mLastContentInsets.set(w.mContentInsets);
10323 w.mLastVisibleInsets.set(w.mVisibleInsets);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010324 // If the screen is currently frozen, then keep
10325 // it frozen until this window draws at its new
10326 // orientation.
10327 if (mDisplayFrozen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010328 if (DEBUG_ORIENTATION) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010329 "Resizing while display frozen: " + w);
10330 w.mOrientationChanging = true;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010331 if (!mWindowsFreezingScreen) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010332 mWindowsFreezingScreen = true;
10333 // XXX should probably keep timeout from
10334 // when we first froze the display.
10335 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10336 mH.sendMessageDelayed(mH.obtainMessage(
10337 H.WINDOW_FREEZE_TIMEOUT), 2000);
10338 }
10339 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010340 // If the orientation is changing, then we need to
10341 // hold off on unfreezing the display until this
10342 // window has been redrawn; to do that, we need
10343 // to go through the process of getting informed
10344 // by the application when it has finished drawing.
10345 if (w.mOrientationChanging) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010346 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010347 "Orientation start waiting for draw in "
10348 + w + ", surface " + w.mSurface);
10349 w.mDrawPending = true;
10350 w.mCommitDrawPending = false;
10351 w.mReadyToShow = false;
10352 if (w.mAppToken != null) {
10353 w.mAppToken.allDrawn = false;
10354 }
10355 }
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010356 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010357 "Resizing window " + w + " to " + w.mFrame);
10358 mResizingWindows.add(w);
10359 } else if (w.mOrientationChanging) {
10360 if (!w.mDrawPending && !w.mCommitDrawPending) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010361 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010362 "Orientation not waiting for draw in "
10363 + w + ", surface " + w.mSurface);
10364 w.mOrientationChanging = false;
10365 }
10366 }
10367 }
10368
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010369 if (w.mAttachedHidden || !w.isReadyForDisplay()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010370 if (!w.mLastHidden) {
10371 //dump();
10372 w.mLastHidden = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010373 if (SHOW_TRANSACTIONS) logSurface(w,
10374 "HIDE (performLayout)", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010375 if (w.mSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010376 w.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010377 try {
10378 w.mSurface.hide();
10379 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010380 Slog.w(TAG, "Exception hiding surface in " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010381 }
10382 }
10383 mKeyWaiter.releasePendingPointerLocked(w.mSession);
10384 }
10385 // If we are waiting for this window to handle an
10386 // orientation change, well, it is hidden, so
10387 // doesn't really matter. Note that this does
10388 // introduce a potential glitch if the window
10389 // becomes unhidden before it has drawn for the
10390 // new orientation.
10391 if (w.mOrientationChanging) {
10392 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010393 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010394 "Orientation change skips hidden " + w);
10395 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010396 } else if (w.mLastLayer != w.mAnimLayer
10397 || w.mLastAlpha != w.mShownAlpha
10398 || w.mLastDsDx != w.mDsDx
10399 || w.mLastDtDx != w.mDtDx
10400 || w.mLastDsDy != w.mDsDy
10401 || w.mLastDtDy != w.mDtDy
10402 || w.mLastHScale != w.mHScale
10403 || w.mLastVScale != w.mVScale
10404 || w.mLastHidden) {
10405 displayed = true;
10406 w.mLastAlpha = w.mShownAlpha;
10407 w.mLastLayer = w.mAnimLayer;
10408 w.mLastDsDx = w.mDsDx;
10409 w.mLastDtDx = w.mDtDx;
10410 w.mLastDsDy = w.mDsDy;
10411 w.mLastDtDy = w.mDtDy;
10412 w.mLastHScale = w.mHScale;
10413 w.mLastVScale = w.mVScale;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010414 if (SHOW_TRANSACTIONS) logSurface(w,
10415 "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010416 + " matrix=[" + (w.mDsDx*w.mHScale)
10417 + "," + (w.mDtDx*w.mVScale)
10418 + "][" + (w.mDsDy*w.mHScale)
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010419 + "," + (w.mDtDy*w.mVScale) + "]", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010420 if (w.mSurface != null) {
10421 try {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010422 w.mSurfaceAlpha = w.mShownAlpha;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 w.mSurface.setAlpha(w.mShownAlpha);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010424 w.mSurfaceLayer = w.mAnimLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010425 w.mSurface.setLayer(w.mAnimLayer);
10426 w.mSurface.setMatrix(
10427 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
10428 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
10429 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010430 Slog.w(TAG, "Error updating surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010431 if (!recoveringMemory) {
10432 reclaimSomeSurfaceMemoryLocked(w, "update");
10433 }
10434 }
10435 }
10436
10437 if (w.mLastHidden && !w.mDrawPending
10438 && !w.mCommitDrawPending
10439 && !w.mReadyToShow) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010440 if (SHOW_TRANSACTIONS) logSurface(w,
10441 "SHOW (performLayout)", null);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010442 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010443 + " during relayout");
10444 if (showSurfaceRobustlyLocked(w)) {
10445 w.mHasDrawn = true;
10446 w.mLastHidden = false;
10447 } else {
10448 w.mOrientationChanging = false;
10449 }
10450 }
10451 if (w.mSurface != null) {
10452 w.mToken.hasVisible = true;
10453 }
10454 } else {
10455 displayed = true;
10456 }
10457
10458 if (displayed) {
10459 if (!covered) {
Romain Guy980a9382010-01-08 15:06:28 -080010460 if (attrs.width == LayoutParams.MATCH_PARENT
10461 && attrs.height == LayoutParams.MATCH_PARENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010462 covered = true;
10463 }
10464 }
10465 if (w.mOrientationChanging) {
10466 if (w.mDrawPending || w.mCommitDrawPending) {
10467 orientationChangeComplete = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010468 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010469 "Orientation continue waiting for draw in " + w);
10470 } else {
10471 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010472 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010473 "Orientation change complete in " + w);
10474 }
10475 }
10476 w.mToken.hasVisible = true;
10477 }
10478 } else if (w.mOrientationChanging) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010479 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010480 "Orientation change skips hidden " + w);
10481 w.mOrientationChanging = false;
10482 }
10483
10484 final boolean canBeSeen = w.isDisplayedLw();
10485
10486 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
10487 focusDisplayed = true;
10488 }
10489
Dianne Hackborne9e9bca2009-08-18 15:08:22 -070010490 final boolean obscuredChanged = w.mObscured != obscured;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010491
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010492 // Update effect.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010493 if (!(w.mObscured=obscured)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010494 if (w.mSurface != null) {
10495 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
10496 holdScreen = w.mSession;
10497 }
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070010498 if (!syswin && w.mAttrs.screenBrightness >= 0
10499 && screenBrightness < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010500 screenBrightness = w.mAttrs.screenBrightness;
10501 }
Mike Lockwoodfb73f792009-11-20 11:31:18 -050010502 if (!syswin && w.mAttrs.buttonBrightness >= 0
10503 && buttonBrightness < 0) {
10504 buttonBrightness = w.mAttrs.buttonBrightness;
10505 }
Mike Lockwood46af6a82010-03-09 08:28:22 -050010506 if (canBeSeen
10507 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
10508 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
10509 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070010510 syswin = true;
10511 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010512 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010513
Dianne Hackborn25994b42009-09-04 14:21:19 -070010514 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
10515 if (opaqueDrawn && w.isFullscreen(dw, dh)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010516 // This window completely covers everything behind it,
10517 // so we want to leave all of them as unblurred (for
10518 // performance reasons).
10519 obscured = true;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010520 } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010521 if (SHOW_TRANSACTIONS) Slog.d(TAG, "showing background filler");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010522 // This window is in compatibility mode, and needs background filler.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010523 obscured = true;
10524 if (mBackgroundFillerSurface == null) {
10525 try {
10526 mBackgroundFillerSurface = new Surface(mFxSession, 0,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080010527 "BackGroundFiller",
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010528 0, dw, dh,
10529 PixelFormat.OPAQUE,
10530 Surface.FX_SURFACE_NORMAL);
10531 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010532 Slog.e(TAG, "Exception creating filler surface", e);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010533 }
10534 }
10535 try {
10536 mBackgroundFillerSurface.setPosition(0, 0);
10537 mBackgroundFillerSurface.setSize(dw, dh);
10538 // Using the same layer as Dim because they will never be shown at the
10539 // same time.
10540 mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
10541 mBackgroundFillerSurface.show();
10542 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010543 Slog.e(TAG, "Exception showing filler surface");
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010544 }
10545 backgroundFillerShown = true;
10546 mBackgroundFillerShown = true;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010547 } else if (canBeSeen && !obscured &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010548 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010549 if (localLOGV) Slog.v(TAG, "Win " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010550 + ": blurring=" + blurring
10551 + " obscured=" + obscured
10552 + " displayed=" + displayed);
10553 if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
10554 if (!dimming) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010555 //Slog.i(TAG, "DIM BEHIND: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010556 dimming = true;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010557 if (mDimAnimator == null) {
10558 mDimAnimator = new DimAnimator(mFxSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010559 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010560 mDimAnimator.show(dw, dh);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010561 mDimAnimator.updateParameters(w, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010563 }
10564 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
10565 if (!blurring) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010566 //Slog.i(TAG, "BLUR BEHIND: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010567 blurring = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 if (mBlurSurface == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010569 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010570 + mBlurSurface + ": CREATE");
10571 try {
Romain Guy06882f82009-06-10 13:36:04 -070010572 mBlurSurface = new Surface(mFxSession, 0,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080010573 "BlurSurface",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010574 -1, 16, 16,
10575 PixelFormat.OPAQUE,
10576 Surface.FX_SURFACE_BLUR);
10577 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010578 Slog.e(TAG, "Exception creating Blur surface", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010579 }
10580 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010581 if (mBlurSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010582 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
10583 + mBlurSurface + ": pos=(0,0) (" +
10584 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010585 mBlurSurface.setPosition(0, 0);
10586 mBlurSurface.setSize(dw, dh);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010587 mBlurSurface.setLayer(w.mAnimLayer-2);
10588 if (!mBlurShown) {
10589 try {
10590 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
10591 + mBlurSurface + ": SHOW");
10592 mBlurSurface.show();
10593 } catch (RuntimeException e) {
10594 Slog.w(TAG, "Failure showing blur surface", e);
10595 }
10596 mBlurShown = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010597 }
10598 }
10599 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010600 }
10601 }
10602 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010603
Dianne Hackborne9e9bca2009-08-18 15:08:22 -070010604 if (obscuredChanged && mWallpaperTarget == w) {
10605 // This is the wallpaper target and its obscured state
10606 // changed... make sure the current wallaper's visibility
10607 // has been updated accordingly.
10608 updateWallpaperVisibilityLocked();
10609 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010610 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010611
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010612 if (backgroundFillerShown == false && mBackgroundFillerShown) {
10613 mBackgroundFillerShown = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010614 if (SHOW_TRANSACTIONS) Slog.d(TAG, "hiding background filler");
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010615 try {
10616 mBackgroundFillerSurface.hide();
10617 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010618 Slog.e(TAG, "Exception hiding filler surface", e);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010619 }
10620 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010621
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010622 if (mDimAnimator != null && mDimAnimator.mDimShown) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010623 animating |= mDimAnimator.updateSurface(dimming, currentTime,
10624 mDisplayFrozen || !mPolicy.isScreenOn());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010625 }
Romain Guy06882f82009-06-10 13:36:04 -070010626
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010627 if (!blurring && mBlurShown) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010628 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " + mBlurSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010629 + ": HIDE");
10630 try {
10631 mBlurSurface.hide();
10632 } catch (IllegalArgumentException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010633 Slog.w(TAG, "Illegal argument exception hiding blur surface");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010634 }
10635 mBlurShown = false;
10636 }
10637
Joe Onorato8a9b2202010-02-26 18:56:32 -080010638 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010639 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010640 Slog.e(TAG, "Unhandled exception in Window Manager", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010641 }
10642
10643 Surface.closeTransaction();
Romain Guy06882f82009-06-10 13:36:04 -070010644
Joe Onorato8a9b2202010-02-26 18:56:32 -080010645 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010646 "With display frozen, orientationChangeComplete="
10647 + orientationChangeComplete);
10648 if (orientationChangeComplete) {
10649 if (mWindowsFreezingScreen) {
10650 mWindowsFreezingScreen = false;
10651 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10652 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010653 stopFreezingDisplayLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010654 }
Romain Guy06882f82009-06-10 13:36:04 -070010655
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010656 i = mResizingWindows.size();
10657 if (i > 0) {
10658 do {
10659 i--;
10660 WindowState win = mResizingWindows.get(i);
10661 try {
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010662 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
10663 "Reporting new frame to " + win + ": " + win.mFrame);
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010664 int diff = 0;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010665 boolean configChanged =
10666 win.mConfiguration != mCurConfiguration
10667 && (win.mConfiguration == null
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010668 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0);
10669 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
10670 && configChanged) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010671 Slog.i(TAG, "Sending new config to window " + win + ": "
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010672 + win.mFrame.width() + "x" + win.mFrame.height()
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010673 + " / " + mCurConfiguration + " / 0x"
10674 + Integer.toHexString(diff));
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010675 }
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010676 win.mConfiguration = mCurConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010677 win.mClient.resized(win.mFrame.width(),
10678 win.mFrame.height(), win.mLastContentInsets,
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010679 win.mLastVisibleInsets, win.mDrawPending,
10680 configChanged ? win.mConfiguration : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010681 win.mContentInsetsChanged = false;
10682 win.mVisibleInsetsChanged = false;
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010683 win.mSurfaceResized = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010684 } catch (RemoteException e) {
10685 win.mOrientationChanging = false;
10686 }
10687 } while (i > 0);
10688 mResizingWindows.clear();
10689 }
Romain Guy06882f82009-06-10 13:36:04 -070010690
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010691 // Destroy the surface of any windows that are no longer visible.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010692 boolean wallpaperDestroyed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010693 i = mDestroySurface.size();
10694 if (i > 0) {
10695 do {
10696 i--;
10697 WindowState win = mDestroySurface.get(i);
10698 win.mDestroying = false;
10699 if (mInputMethodWindow == win) {
10700 mInputMethodWindow = null;
10701 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010702 if (win == mWallpaperTarget) {
10703 wallpaperDestroyed = true;
10704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010705 win.destroySurfaceLocked();
10706 } while (i > 0);
10707 mDestroySurface.clear();
10708 }
10709
10710 // Time to remove any exiting tokens?
10711 for (i=mExitingTokens.size()-1; i>=0; i--) {
10712 WindowToken token = mExitingTokens.get(i);
10713 if (!token.hasVisible) {
10714 mExitingTokens.remove(i);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070010715 if (token.windowType == TYPE_WALLPAPER) {
10716 mWallpaperTokens.remove(token);
10717 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010718 }
10719 }
10720
10721 // Time to remove any exiting applications?
10722 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
10723 AppWindowToken token = mExitingAppTokens.get(i);
10724 if (!token.hasVisible && !mClosingApps.contains(token)) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -070010725 // Make sure there is no animation running on this token,
10726 // so any windows associated with it will be removed as
10727 // soon as their animations are complete
10728 token.animation = null;
10729 token.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010730 mAppTokens.remove(token);
10731 mExitingAppTokens.remove(i);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010732 if (mLastEnterAnimToken == token) {
10733 mLastEnterAnimToken = null;
10734 mLastEnterAnimParams = null;
10735 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010736 }
10737 }
10738
Dianne Hackborna8f60182009-09-01 19:01:50 -070010739 boolean needRelayout = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010740
Dianne Hackborna8f60182009-09-01 19:01:50 -070010741 if (!animating && mAppTransitionRunning) {
10742 // We have finished the animation of an app transition. To do
10743 // this, we have delayed a lot of operations like showing and
10744 // hiding apps, moving apps in Z-order, etc. The app token list
10745 // reflects the correct Z-order, but the window list may now
10746 // be out of sync with it. So here we will just rebuild the
10747 // entire app window list. Fun!
10748 mAppTransitionRunning = false;
10749 needRelayout = true;
10750 rebuildAppWindowListLocked();
Dianne Hackborn16064f92010-03-25 00:47:24 -070010751 assignLayersLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070010752 // Clear information about apps that were moving.
10753 mToBottomApps.clear();
10754 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010756 if (focusDisplayed) {
10757 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
10758 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010759 if (wallpaperDestroyed) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010760 needRelayout = adjustWallpaperWindowsLocked() != 0;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010761 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070010762 if (needRelayout) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010763 requestAnimationLocked(0);
10764 } else if (animating) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010765 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
10766 }
10767 mQueue.setHoldScreenLocked(holdScreen != null);
10768 if (screenBrightness < 0 || screenBrightness > 1.0f) {
10769 mPowerManager.setScreenBrightnessOverride(-1);
10770 } else {
10771 mPowerManager.setScreenBrightnessOverride((int)
10772 (screenBrightness * Power.BRIGHTNESS_ON));
10773 }
Mike Lockwoodfb73f792009-11-20 11:31:18 -050010774 if (buttonBrightness < 0 || buttonBrightness > 1.0f) {
10775 mPowerManager.setButtonBrightnessOverride(-1);
10776 } else {
10777 mPowerManager.setButtonBrightnessOverride((int)
10778 (buttonBrightness * Power.BRIGHTNESS_ON));
10779 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010780 if (holdScreen != mHoldingScreenOn) {
10781 mHoldingScreenOn = holdScreen;
10782 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
10783 mH.sendMessage(m);
10784 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010785
Dianne Hackborn93e462b2009-09-15 22:50:40 -070010786 if (mTurnOnScreen) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010787 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
Dianne Hackborn93e462b2009-09-15 22:50:40 -070010788 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
10789 LocalPowerManager.BUTTON_EVENT, true);
10790 mTurnOnScreen = false;
10791 }
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -080010792
10793 // Check to see if we are now in a state where the screen should
10794 // be enabled, because the window obscured flags have changed.
10795 enableScreenIfNeededLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010796 }
10797
10798 void requestAnimationLocked(long delay) {
10799 if (!mAnimationPending) {
10800 mAnimationPending = true;
10801 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
10802 }
10803 }
Romain Guy06882f82009-06-10 13:36:04 -070010804
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 /**
10806 * Have the surface flinger show a surface, robustly dealing with
10807 * error conditions. In particular, if there is not enough memory
10808 * to show the surface, then we will try to get rid of other surfaces
10809 * in order to succeed.
Romain Guy06882f82009-06-10 13:36:04 -070010810 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010811 * @return Returns true if the surface was successfully shown.
10812 */
10813 boolean showSurfaceRobustlyLocked(WindowState win) {
10814 try {
10815 if (win.mSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010816 win.mSurfaceShown = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010817 win.mSurface.show();
Dianne Hackborn93e462b2009-09-15 22:50:40 -070010818 if (win.mTurnOnScreen) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010819 if (DEBUG_VISIBILITY) Slog.v(TAG,
10820 "Show surface turning screen on: " + win);
Dianne Hackborn93e462b2009-09-15 22:50:40 -070010821 win.mTurnOnScreen = false;
10822 mTurnOnScreen = true;
10823 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010824 }
10825 return true;
10826 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010827 Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010828 }
Romain Guy06882f82009-06-10 13:36:04 -070010829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010830 reclaimSomeSurfaceMemoryLocked(win, "show");
Romain Guy06882f82009-06-10 13:36:04 -070010831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010832 return false;
10833 }
Romain Guy06882f82009-06-10 13:36:04 -070010834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010835 void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
10836 final Surface surface = win.mSurface;
Romain Guy06882f82009-06-10 13:36:04 -070010837
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010838 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010839 win.mSession.mPid, operation);
Romain Guy06882f82009-06-10 13:36:04 -070010840
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010841 if (mForceRemoves == null) {
10842 mForceRemoves = new ArrayList<WindowState>();
10843 }
Romain Guy06882f82009-06-10 13:36:04 -070010844
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010845 long callingIdentity = Binder.clearCallingIdentity();
10846 try {
10847 // There was some problem... first, do a sanity check of the
10848 // window list to make sure we haven't left any dangling surfaces
10849 // around.
10850 int N = mWindows.size();
10851 boolean leakedSurface = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010852 Slog.i(TAG, "Out of memory for surface! Looking for leaks...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010853 for (int i=0; i<N; i++) {
10854 WindowState ws = (WindowState)mWindows.get(i);
10855 if (ws.mSurface != null) {
10856 if (!mSessions.contains(ws.mSession)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010857 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010858 + ws + " surface=" + ws.mSurface
10859 + " token=" + win.mToken
10860 + " pid=" + ws.mSession.mPid
10861 + " uid=" + ws.mSession.mUid);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010862 ws.mSurface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070010863 ws.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010864 ws.mSurface = null;
10865 mForceRemoves.add(ws);
10866 i--;
10867 N--;
10868 leakedSurface = true;
10869 } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010870 Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010871 + ws + " surface=" + ws.mSurface
10872 + " token=" + win.mAppToken);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010873 ws.mSurface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070010874 ws.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010875 ws.mSurface = null;
10876 leakedSurface = true;
10877 }
10878 }
10879 }
Romain Guy06882f82009-06-10 13:36:04 -070010880
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010881 boolean killedApps = false;
10882 if (!leakedSurface) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010883 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010884 SparseIntArray pidCandidates = new SparseIntArray();
10885 for (int i=0; i<N; i++) {
10886 WindowState ws = (WindowState)mWindows.get(i);
10887 if (ws.mSurface != null) {
10888 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
10889 }
10890 }
10891 if (pidCandidates.size() > 0) {
10892 int[] pids = new int[pidCandidates.size()];
10893 for (int i=0; i<pids.length; i++) {
10894 pids[i] = pidCandidates.keyAt(i);
10895 }
10896 try {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010897 if (mActivityManager.killPids(pids, "Free memory")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010898 killedApps = true;
10899 }
10900 } catch (RemoteException e) {
10901 }
10902 }
10903 }
Romain Guy06882f82009-06-10 13:36:04 -070010904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010905 if (leakedSurface || killedApps) {
10906 // We managed to reclaim some memory, so get rid of the trouble
10907 // surface and ask the app to request another one.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010908 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010909 if (surface != null) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010910 surface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070010911 win.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010912 win.mSurface = null;
10913 }
Romain Guy06882f82009-06-10 13:36:04 -070010914
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010915 try {
10916 win.mClient.dispatchGetNewSurface();
10917 } catch (RemoteException e) {
10918 }
10919 }
10920 } finally {
10921 Binder.restoreCallingIdentity(callingIdentity);
10922 }
10923 }
Romain Guy06882f82009-06-10 13:36:04 -070010924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010925 private boolean updateFocusedWindowLocked(int mode) {
10926 WindowState newFocus = computeFocusedWindowLocked();
10927 if (mCurrentFocus != newFocus) {
10928 // This check makes sure that we don't already have the focus
10929 // change message pending.
10930 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
10931 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010932 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010933 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
10934 final WindowState oldFocus = mCurrentFocus;
10935 mCurrentFocus = newFocus;
10936 mLosingFocus.remove(newFocus);
Romain Guy06882f82009-06-10 13:36:04 -070010937
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010938 final WindowState imWindow = mInputMethodWindow;
10939 if (newFocus != imWindow && oldFocus != imWindow) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010940 if (moveInputMethodWindowsIfNeededLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010941 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010942 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
10943 mLayoutNeeded = true;
10944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010945 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10946 performLayoutLockedInner();
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010947 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
10948 // Client will do the layout, but we need to assign layers
10949 // for handleNewWindowLocked() below.
10950 assignLayersLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010951 }
10952 }
Romain Guy06882f82009-06-10 13:36:04 -070010953
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010954 if (newFocus != null && mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
10955 mKeyWaiter.handleNewWindowLocked(newFocus);
10956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 return true;
10958 }
10959 return false;
10960 }
10961
10962 private WindowState computeFocusedWindowLocked() {
10963 WindowState result = null;
10964 WindowState win;
10965
10966 int i = mWindows.size() - 1;
10967 int nextAppIndex = mAppTokens.size()-1;
10968 WindowToken nextApp = nextAppIndex >= 0
10969 ? mAppTokens.get(nextAppIndex) : null;
10970
10971 while (i >= 0) {
10972 win = (WindowState)mWindows.get(i);
10973
Joe Onorato8a9b2202010-02-26 18:56:32 -080010974 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010975 TAG, "Looking for focus: " + i
10976 + " = " + win
10977 + ", flags=" + win.mAttrs.flags
10978 + ", canReceive=" + win.canReceiveKeys());
10979
10980 AppWindowToken thisApp = win.mAppToken;
Romain Guy06882f82009-06-10 13:36:04 -070010981
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010982 // If this window's application has been removed, just skip it.
10983 if (thisApp != null && thisApp.removed) {
10984 i--;
10985 continue;
10986 }
Romain Guy06882f82009-06-10 13:36:04 -070010987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010988 // If there is a focused app, don't allow focus to go to any
10989 // windows below it. If this is an application window, step
10990 // through the app tokens until we find its app.
10991 if (thisApp != null && nextApp != null && thisApp != nextApp
10992 && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
10993 int origAppIndex = nextAppIndex;
10994 while (nextAppIndex > 0) {
10995 if (nextApp == mFocusedApp) {
10996 // Whoops, we are below the focused app... no focus
10997 // for you!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010998 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010999 TAG, "Reached focused app: " + mFocusedApp);
11000 return null;
11001 }
11002 nextAppIndex--;
11003 nextApp = mAppTokens.get(nextAppIndex);
11004 if (nextApp == thisApp) {
11005 break;
11006 }
11007 }
11008 if (thisApp != nextApp) {
11009 // Uh oh, the app token doesn't exist! This shouldn't
11010 // happen, but if it does we can get totally hosed...
11011 // so restart at the original app.
11012 nextAppIndex = origAppIndex;
11013 nextApp = mAppTokens.get(nextAppIndex);
11014 }
11015 }
11016
11017 // Dispatch to this window if it is wants key events.
11018 if (win.canReceiveKeys()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011019 if (DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011020 TAG, "Found focus @ " + i + " = " + win);
11021 result = win;
11022 break;
11023 }
11024
11025 i--;
11026 }
11027
11028 return result;
11029 }
11030
11031 private void startFreezingDisplayLocked() {
11032 if (mDisplayFrozen) {
Chris Tate2ad63a92009-03-25 17:36:48 -070011033 // Freezing the display also suspends key event delivery, to
11034 // keep events from going astray while the display is reconfigured.
11035 // If someone has changed orientation again while the screen is
11036 // still frozen, the events will continue to be blocked while the
11037 // successive orientation change is processed. To prevent spurious
11038 // ANRs, we reset the event dispatch timeout in this case.
11039 synchronized (mKeyWaiter) {
11040 mKeyWaiter.mWasFrozen = true;
11041 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011042 return;
11043 }
Romain Guy06882f82009-06-10 13:36:04 -070011044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011045 mScreenFrozenLock.acquire();
Romain Guy06882f82009-06-10 13:36:04 -070011046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011047 long now = SystemClock.uptimeMillis();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011048 //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011049 if (mFreezeGcPending != 0) {
11050 if (now > (mFreezeGcPending+1000)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011051 //Slog.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011052 mH.removeMessages(H.FORCE_GC);
11053 Runtime.getRuntime().gc();
11054 mFreezeGcPending = now;
11055 }
11056 } else {
11057 mFreezeGcPending = now;
11058 }
Romain Guy06882f82009-06-10 13:36:04 -070011059
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011060 mDisplayFrozen = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -070011061 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
11062 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011063 mNextAppTransitionPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 mAppTransitionReady = true;
11065 }
Romain Guy06882f82009-06-10 13:36:04 -070011066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011067 if (PROFILE_ORIENTATION) {
11068 File file = new File("/data/system/frozen");
11069 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
11070 }
11071 Surface.freezeDisplay(0);
11072 }
Romain Guy06882f82009-06-10 13:36:04 -070011073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011074 private void stopFreezingDisplayLocked() {
11075 if (!mDisplayFrozen) {
11076 return;
11077 }
Romain Guy06882f82009-06-10 13:36:04 -070011078
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011079 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
11080 return;
11081 }
11082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011083 mDisplayFrozen = false;
11084 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
11085 if (PROFILE_ORIENTATION) {
11086 Debug.stopMethodTracing();
11087 }
11088 Surface.unfreezeDisplay(0);
Romain Guy06882f82009-06-10 13:36:04 -070011089
Chris Tate2ad63a92009-03-25 17:36:48 -070011090 // Reset the key delivery timeout on unfreeze, too. We force a wakeup here
11091 // too because regular key delivery processing should resume immediately.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011092 synchronized (mKeyWaiter) {
11093 mKeyWaiter.mWasFrozen = true;
11094 mKeyWaiter.notifyAll();
11095 }
11096
Christopher Tateb696aee2010-04-02 19:08:30 -070011097 // While the display is frozen we don't re-compute the orientation
11098 // to avoid inconsistent states. However, something interesting
11099 // could have actually changed during that time so re-evaluate it
11100 // now to catch that.
11101 if (updateOrientationFromAppTokensLocked()) {
11102 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
11103 }
11104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011105 // A little kludge: a lot could have happened while the
11106 // display was frozen, so now that we are coming back we
11107 // do a gc so that any remote references the system
11108 // processes holds on others can be released if they are
11109 // no longer needed.
11110 mH.removeMessages(H.FORCE_GC);
11111 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
11112 2000);
Romain Guy06882f82009-06-10 13:36:04 -070011113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011114 mScreenFrozenLock.release();
11115 }
Romain Guy06882f82009-06-10 13:36:04 -070011116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011117 @Override
11118 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
11119 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
11120 != PackageManager.PERMISSION_GRANTED) {
11121 pw.println("Permission Denial: can't dump WindowManager from from pid="
11122 + Binder.getCallingPid()
11123 + ", uid=" + Binder.getCallingUid());
11124 return;
11125 }
Romain Guy06882f82009-06-10 13:36:04 -070011126
Dianne Hackborna2e92262010-03-02 17:19:29 -080011127 pw.println("Input State:");
11128 mQueue.dump(pw, " ");
11129 pw.println(" ");
11130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011131 synchronized(mWindowMap) {
11132 pw.println("Current Window Manager state:");
11133 for (int i=mWindows.size()-1; i>=0; i--) {
11134 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011135 pw.print(" Window #"); pw.print(i); pw.print(' ');
11136 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011137 w.dump(pw, " ");
11138 }
11139 if (mInputMethodDialogs.size() > 0) {
11140 pw.println(" ");
11141 pw.println(" Input method dialogs:");
11142 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
11143 WindowState w = mInputMethodDialogs.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011144 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 }
11146 }
11147 if (mPendingRemove.size() > 0) {
11148 pw.println(" ");
11149 pw.println(" Remove pending for:");
11150 for (int i=mPendingRemove.size()-1; i>=0; i--) {
11151 WindowState w = mPendingRemove.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011152 pw.print(" Remove #"); pw.print(i); pw.print(' ');
11153 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011154 w.dump(pw, " ");
11155 }
11156 }
11157 if (mForceRemoves != null && mForceRemoves.size() > 0) {
11158 pw.println(" ");
11159 pw.println(" Windows force removing:");
11160 for (int i=mForceRemoves.size()-1; i>=0; i--) {
11161 WindowState w = mForceRemoves.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011162 pw.print(" Removing #"); pw.print(i); pw.print(' ');
11163 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011164 w.dump(pw, " ");
11165 }
11166 }
11167 if (mDestroySurface.size() > 0) {
11168 pw.println(" ");
11169 pw.println(" Windows waiting to destroy their surface:");
11170 for (int i=mDestroySurface.size()-1; i>=0; i--) {
11171 WindowState w = mDestroySurface.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011172 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
11173 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011174 w.dump(pw, " ");
11175 }
11176 }
11177 if (mLosingFocus.size() > 0) {
11178 pw.println(" ");
11179 pw.println(" Windows losing focus:");
11180 for (int i=mLosingFocus.size()-1; i>=0; i--) {
11181 WindowState w = mLosingFocus.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011182 pw.print(" Losing #"); pw.print(i); pw.print(' ');
11183 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011184 w.dump(pw, " ");
11185 }
11186 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011187 if (mResizingWindows.size() > 0) {
11188 pw.println(" ");
11189 pw.println(" Windows waiting to resize:");
11190 for (int i=mResizingWindows.size()-1; i>=0; i--) {
11191 WindowState w = mResizingWindows.get(i);
11192 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
11193 pw.print(w); pw.println(":");
11194 w.dump(pw, " ");
11195 }
11196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011197 if (mSessions.size() > 0) {
11198 pw.println(" ");
11199 pw.println(" All active sessions:");
11200 Iterator<Session> it = mSessions.iterator();
11201 while (it.hasNext()) {
11202 Session s = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011203 pw.print(" Session "); pw.print(s); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011204 s.dump(pw, " ");
11205 }
11206 }
11207 if (mTokenMap.size() > 0) {
11208 pw.println(" ");
11209 pw.println(" All tokens:");
11210 Iterator<WindowToken> it = mTokenMap.values().iterator();
11211 while (it.hasNext()) {
11212 WindowToken token = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011213 pw.print(" Token "); pw.print(token.token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011214 token.dump(pw, " ");
11215 }
11216 }
11217 if (mTokenList.size() > 0) {
11218 pw.println(" ");
11219 pw.println(" Window token list:");
11220 for (int i=0; i<mTokenList.size(); i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011221 pw.print(" #"); pw.print(i); pw.print(": ");
11222 pw.println(mTokenList.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011223 }
11224 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070011225 if (mWallpaperTokens.size() > 0) {
11226 pw.println(" ");
11227 pw.println(" Wallpaper tokens:");
11228 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
11229 WindowToken token = mWallpaperTokens.get(i);
11230 pw.print(" Wallpaper #"); pw.print(i);
11231 pw.print(' '); pw.print(token); pw.println(':');
11232 token.dump(pw, " ");
11233 }
11234 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 if (mAppTokens.size() > 0) {
11236 pw.println(" ");
11237 pw.println(" Application tokens in Z order:");
11238 for (int i=mAppTokens.size()-1; i>=0; i--) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011239 pw.print(" App #"); pw.print(i); pw.print(": ");
11240 pw.println(mAppTokens.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011241 }
11242 }
11243 if (mFinishedStarting.size() > 0) {
11244 pw.println(" ");
11245 pw.println(" Finishing start of application tokens:");
11246 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
11247 WindowToken token = mFinishedStarting.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011248 pw.print(" Finished Starting #"); pw.print(i);
11249 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011250 token.dump(pw, " ");
11251 }
11252 }
11253 if (mExitingTokens.size() > 0) {
11254 pw.println(" ");
11255 pw.println(" Exiting tokens:");
11256 for (int i=mExitingTokens.size()-1; i>=0; i--) {
11257 WindowToken token = mExitingTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011258 pw.print(" Exiting #"); pw.print(i);
11259 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011260 token.dump(pw, " ");
11261 }
11262 }
11263 if (mExitingAppTokens.size() > 0) {
11264 pw.println(" ");
11265 pw.println(" Exiting application tokens:");
11266 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
11267 WindowToken token = mExitingAppTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011268 pw.print(" Exiting App #"); pw.print(i);
11269 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011270 token.dump(pw, " ");
11271 }
11272 }
11273 pw.println(" ");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011274 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
11275 pw.print(" mLastFocus="); pw.println(mLastFocus);
11276 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
11277 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
11278 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
Dianne Hackbornf21adf62009-08-13 10:20:21 -070011279 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
Dianne Hackborn284ac932009-08-28 10:34:25 -070011280 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
11281 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
11282 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
11283 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011284 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration);
11285 pw.print(" mInTouchMode="); pw.print(mInTouchMode);
11286 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011287 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
11288 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
11289 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
11290 pw.print(" mBlurShown="); pw.println(mBlurShown);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011291 if (mDimAnimator != null) {
11292 mDimAnimator.printTo(pw);
11293 } else {
Dianne Hackborna2e92262010-03-02 17:19:29 -080011294 pw.println( " no DimAnimator ");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011295 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011296 pw.print(" mInputMethodAnimLayerAdjustment=");
Dianne Hackborn759a39e2009-08-09 17:20:27 -070011297 pw.print(mInputMethodAnimLayerAdjustment);
11298 pw.print(" mWallpaperAnimLayerAdjustment=");
11299 pw.println(mWallpaperAnimLayerAdjustment);
Dianne Hackborn284ac932009-08-28 10:34:25 -070011300 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
11301 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011302 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
11303 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011304 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
11305 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011306 pw.print(" mRotation="); pw.print(mRotation);
11307 pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
11308 pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
11309 pw.print(" mAnimationPending="); pw.print(mAnimationPending);
11310 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
11311 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
11312 pw.print(" mNextAppTransition=0x");
11313 pw.print(Integer.toHexString(mNextAppTransition));
11314 pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
Dianne Hackborna8f60182009-09-01 19:01:50 -070011315 pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011316 pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011317 if (mNextAppTransitionPackage != null) {
11318 pw.print(" mNextAppTransitionPackage=");
11319 pw.print(mNextAppTransitionPackage);
11320 pw.print(", mNextAppTransitionEnter=0x");
11321 pw.print(Integer.toHexString(mNextAppTransitionEnter));
11322 pw.print(", mNextAppTransitionExit=0x");
11323 pw.print(Integer.toHexString(mNextAppTransitionExit));
11324 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011325 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
11326 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011327 if (mLastEnterAnimToken != null || mLastEnterAnimToken != null) {
11328 pw.print(" mLastEnterAnimToken="); pw.print(mLastEnterAnimToken);
11329 pw.print(", mLastEnterAnimParams="); pw.println(mLastEnterAnimParams);
11330 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011331 if (mOpeningApps.size() > 0) {
11332 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
11333 }
11334 if (mClosingApps.size() > 0) {
11335 pw.print(" mClosingApps="); pw.println(mClosingApps);
11336 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070011337 if (mToTopApps.size() > 0) {
11338 pw.print(" mToTopApps="); pw.println(mToTopApps);
11339 }
11340 if (mToBottomApps.size() > 0) {
11341 pw.print(" mToBottomApps="); pw.println(mToBottomApps);
11342 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011343 pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth());
11344 pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011345 pw.println(" KeyWaiter state:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011346 pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin);
11347 pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
11348 pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished);
11349 pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
11350 pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
11351 pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011352 }
11353 }
11354
11355 public void monitor() {
11356 synchronized (mWindowMap) { }
Mike Lockwood983ee092009-11-22 01:42:24 -050011357 synchronized (mKeyguardTokenWatcher) { }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011358 synchronized (mKeyWaiter) { }
11359 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011360
Dianne Hackbornddca3ee2009-07-23 19:01:31 -070011361 public void virtualKeyFeedback(KeyEvent event) {
11362 mPolicy.keyFeedbackFromInput(event);
11363 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011364
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011365 /**
11366 * DimAnimator class that controls the dim animation. This holds the surface and
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011367 * all state used for dim animation.
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011368 */
11369 private static class DimAnimator {
11370 Surface mDimSurface;
11371 boolean mDimShown = false;
11372 float mDimCurrentAlpha;
11373 float mDimTargetAlpha;
11374 float mDimDeltaPerMs;
11375 long mLastDimAnimTime;
Dianne Hackbornf83c5552010-03-31 22:19:32 -070011376
11377 int mLastDimWidth, mLastDimHeight;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011378
11379 DimAnimator (SurfaceSession session) {
11380 if (mDimSurface == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011381 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011382 + mDimSurface + ": CREATE");
11383 try {
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080011384 mDimSurface = new Surface(session, 0,
11385 "DimSurface",
11386 -1, 16, 16, PixelFormat.OPAQUE,
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011387 Surface.FX_SURFACE_DIM);
Maciej Białka9ee5c222010-03-24 10:25:40 +010011388 mDimSurface.setAlpha(0.0f);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011389 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011390 Slog.e(TAG, "Exception creating Dim surface", e);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011391 }
11392 }
11393 }
11394
11395 /**
11396 * Show the dim surface.
11397 */
11398 void show(int dw, int dh) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070011399 if (!mDimShown) {
11400 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
11401 dw + "x" + dh + ")");
11402 mDimShown = true;
11403 try {
Dianne Hackbornf83c5552010-03-31 22:19:32 -070011404 mLastDimWidth = dw;
11405 mLastDimHeight = dh;
Dianne Hackborn16064f92010-03-25 00:47:24 -070011406 mDimSurface.setPosition(0, 0);
11407 mDimSurface.setSize(dw, dh);
11408 mDimSurface.show();
11409 } catch (RuntimeException e) {
11410 Slog.w(TAG, "Failure showing dim surface", e);
11411 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -070011412 } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
11413 mLastDimWidth = dw;
11414 mLastDimHeight = dh;
11415 mDimSurface.setSize(dw, dh);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011416 }
11417 }
11418
11419 /**
11420 * Set's the dim surface's layer and update dim parameters that will be used in
11421 * {@link updateSurface} after all windows are examined.
11422 */
11423 void updateParameters(WindowState w, long currentTime) {
11424 mDimSurface.setLayer(w.mAnimLayer-1);
11425
11426 final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011427 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011428 + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011429 if (mDimTargetAlpha != target) {
11430 // If the desired dim level has changed, then
11431 // start an animation to it.
11432 mLastDimAnimTime = currentTime;
11433 long duration = (w.mAnimating && w.mAnimation != null)
11434 ? w.mAnimation.computeDurationHint()
11435 : DEFAULT_DIM_DURATION;
11436 if (target > mDimTargetAlpha) {
11437 // This is happening behind the activity UI,
11438 // so we can make it run a little longer to
11439 // give a stronger impression without disrupting
11440 // the user.
11441 duration *= DIM_DURATION_MULTIPLIER;
11442 }
11443 if (duration < 1) {
11444 // Don't divide by zero
11445 duration = 1;
11446 }
11447 mDimTargetAlpha = target;
11448 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
11449 }
11450 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011451
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011452 /**
11453 * Updating the surface's alpha. Returns true if the animation continues, or returns
11454 * false when the animation is finished and the dim surface is hidden.
11455 */
11456 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
11457 if (!dimming) {
11458 if (mDimTargetAlpha != 0) {
11459 mLastDimAnimTime = currentTime;
11460 mDimTargetAlpha = 0;
11461 mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
11462 }
11463 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011464
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011465 boolean animating = false;
11466 if (mLastDimAnimTime != 0) {
11467 mDimCurrentAlpha += mDimDeltaPerMs
11468 * (currentTime-mLastDimAnimTime);
11469 boolean more = true;
11470 if (displayFrozen) {
11471 // If the display is frozen, there is no reason to animate.
11472 more = false;
11473 } else if (mDimDeltaPerMs > 0) {
11474 if (mDimCurrentAlpha > mDimTargetAlpha) {
11475 more = false;
11476 }
11477 } else if (mDimDeltaPerMs < 0) {
11478 if (mDimCurrentAlpha < mDimTargetAlpha) {
11479 more = false;
11480 }
11481 } else {
11482 more = false;
11483 }
11484
11485 // Do we need to continue animating?
11486 if (more) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011487 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011488 + mDimSurface + ": alpha=" + mDimCurrentAlpha);
11489 mLastDimAnimTime = currentTime;
11490 mDimSurface.setAlpha(mDimCurrentAlpha);
11491 animating = true;
11492 } else {
11493 mDimCurrentAlpha = mDimTargetAlpha;
11494 mLastDimAnimTime = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011495 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011496 + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
11497 mDimSurface.setAlpha(mDimCurrentAlpha);
11498 if (!dimming) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011499 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011500 + ": HIDE");
11501 try {
11502 mDimSurface.hide();
11503 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011504 Slog.w(TAG, "Illegal argument exception hiding dim surface");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011505 }
11506 mDimShown = false;
11507 }
11508 }
11509 }
11510 return animating;
11511 }
11512
11513 public void printTo(PrintWriter pw) {
11514 pw.print(" mDimShown="); pw.print(mDimShown);
11515 pw.print(" current="); pw.print(mDimCurrentAlpha);
11516 pw.print(" target="); pw.print(mDimTargetAlpha);
11517 pw.print(" delta="); pw.print(mDimDeltaPerMs);
11518 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
11519 }
11520 }
11521
11522 /**
11523 * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
11524 * This is used for opening/closing transition for apps in compatible mode.
11525 */
11526 private static class FadeInOutAnimation extends Animation {
11527 int mWidth;
11528 boolean mFadeIn;
11529
11530 public FadeInOutAnimation(boolean fadeIn) {
11531 setInterpolator(new AccelerateInterpolator());
11532 setDuration(DEFAULT_FADE_IN_OUT_DURATION);
11533 mFadeIn = fadeIn;
11534 }
11535
11536 @Override
11537 protected void applyTransformation(float interpolatedTime, Transformation t) {
11538 float x = interpolatedTime;
11539 if (!mFadeIn) {
11540 x = 1.0f - x; // reverse the interpolation for fade out
11541 }
11542 if (x < 0.5) {
11543 // move the window out of the screen.
11544 t.getMatrix().setTranslate(mWidth, 0);
11545 } else {
11546 t.getMatrix().setTranslate(0, 0);// show
11547 t.setAlpha((x - 0.5f) * 2);
11548 }
11549 }
11550
11551 @Override
11552 public void initialize(int width, int height, int parentWidth, int parentHeight) {
11553 // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
11554 mWidth = width;
11555 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011556
11557 @Override
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -070011558 public int getZAdjustment() {
11559 return Animation.ZORDER_TOP;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011560 }
11561 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011562}