blob: a8dad8812339d3682d0538c0c1659baaad2cb6b3 [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;
Dianne Hackbornce73c1e2010-04-12 23:11:38 -0700156 static final boolean DEBUG_FREEZE = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800157 static final boolean SHOW_TRANSACTIONS = false;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700158 static final boolean HIDE_STACK_CRAWLS = true;
Michael Chan53071d62009-05-13 17:29:48 -0700159 static final boolean MEASURE_LATENCY = false;
160 static private LatencyTimer lt;
161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 static final boolean PROFILE_ORIENTATION = false;
163 static final boolean BLUR = true;
Dave Bortcfe65242009-04-09 14:51:04 -0700164 static final boolean localLOGV = DEBUG;
Romain Guy06882f82009-06-10 13:36:04 -0700165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 /** How long to wait for subsequent key repeats, in milliseconds */
167 static final int KEY_REPEAT_DELAY = 50;
168
169 /** How much to multiply the policy's type layer, to reserve room
170 * for multiple windows of the same type and Z-ordering adjustment
171 * with TYPE_LAYER_OFFSET. */
172 static final int TYPE_LAYER_MULTIPLIER = 10000;
Romain Guy06882f82009-06-10 13:36:04 -0700173
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
175 * or below others in the same layer. */
176 static final int TYPE_LAYER_OFFSET = 1000;
Romain Guy06882f82009-06-10 13:36:04 -0700177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 /** How much to increment the layer for each window, to reserve room
179 * for effect surfaces between them.
180 */
181 static final int WINDOW_LAYER_MULTIPLIER = 5;
Romain Guy06882f82009-06-10 13:36:04 -0700182
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 /** The maximum length we will accept for a loaded animation duration:
184 * this is 10 seconds.
185 */
186 static final int MAX_ANIMATION_DURATION = 10*1000;
187
188 /** Amount of time (in milliseconds) to animate the dim surface from one
189 * value to another, when no window animation is driving it.
190 */
191 static final int DEFAULT_DIM_DURATION = 200;
192
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700193 /** Amount of time (in milliseconds) to animate the fade-in-out transition for
194 * compatible windows.
195 */
196 static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 /** Adjustment to time to perform a dim, to make it more dramatic.
199 */
200 static final int DIM_DURATION_MULTIPLIER = 6;
Romain Guy06882f82009-06-10 13:36:04 -0700201
Dianne Hackborncfaef692009-06-15 14:24:44 -0700202 static final int INJECT_FAILED = 0;
203 static final int INJECT_SUCCEEDED = 1;
204 static final int INJECT_NO_PERMISSION = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 static final int UPDATE_FOCUS_NORMAL = 0;
207 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
208 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
209 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
Romain Guy06882f82009-06-10 13:36:04 -0700210
Michael Chane96440f2009-05-06 10:27:36 -0700211 /** The minimum time between dispatching touch events. */
212 int mMinWaitTimeBetweenTouchEvents = 1000 / 35;
213
214 // Last touch event time
215 long mLastTouchEventTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700216
Michael Chane96440f2009-05-06 10:27:36 -0700217 // Last touch event type
218 int mLastTouchEventType = OTHER_EVENT;
Romain Guy06882f82009-06-10 13:36:04 -0700219
Michael Chane96440f2009-05-06 10:27:36 -0700220 // Time to wait before calling useractivity again. This saves CPU usage
221 // when we get a flood of touch events.
222 static final int MIN_TIME_BETWEEN_USERACTIVITIES = 1000;
223
224 // Last time we call user activity
225 long mLastUserActivityCallTime = 0;
226
Romain Guy06882f82009-06-10 13:36:04 -0700227 // Last time we updated battery stats
Michael Chane96440f2009-05-06 10:27:36 -0700228 long mLastBatteryStatsCallTime = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700229
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 private static final String SYSTEM_SECURE = "ro.secure";
Romain Guy06882f82009-06-10 13:36:04 -0700231 private static final String SYSTEM_DEBUGGABLE = "ro.debuggable";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232
233 /**
234 * Condition waited on by {@link #reenableKeyguard} to know the call to
235 * the window policy has finished.
Mike Lockwood983ee092009-11-22 01:42:24 -0500236 * This is set to true only if mKeyguardTokenWatcher.acquired() has
237 * actually disabled the keyguard.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 */
Mike Lockwood983ee092009-11-22 01:42:24 -0500239 private boolean mKeyguardDisabled = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240
Jim Miller284b62e2010-06-08 14:27:42 -0700241 private static final int ALLOW_DISABLE_YES = 1;
242 private static final int ALLOW_DISABLE_NO = 0;
243 private static final int ALLOW_DISABLE_UNKNOWN = -1; // check with DevicePolicyManager
244 private int mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN; // sync'd by mKeyguardTokenWatcher
245
Mike Lockwood983ee092009-11-22 01:42:24 -0500246 final TokenWatcher mKeyguardTokenWatcher = new TokenWatcher(
247 new Handler(), "WindowManagerService.mKeyguardTokenWatcher") {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 public void acquired() {
Jim Miller284b62e2010-06-08 14:27:42 -0700249 if (shouldAllowDisableKeyguard()) {
250 mPolicy.enableKeyguard(false);
251 mKeyguardDisabled = true;
252 } else {
253 Log.v(TAG, "Not disabling keyguard since device policy is enforced");
254 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 }
256 public void released() {
Dianne Hackborna33e3f72009-09-29 17:28:24 -0700257 mPolicy.enableKeyguard(true);
Mike Lockwood983ee092009-11-22 01:42:24 -0500258 synchronized (mKeyguardTokenWatcher) {
259 mKeyguardDisabled = false;
260 mKeyguardTokenWatcher.notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 }
262 }
263 };
264
Jim Miller284b62e2010-06-08 14:27:42 -0700265 final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
266 @Override
267 public void onReceive(Context context, Intent intent) {
268 mPolicy.enableKeyguard(true);
269 synchronized(mKeyguardTokenWatcher) {
270 // lazily evaluate this next time we're asked to disable keyguard
271 mAllowDisableKeyguard = ALLOW_DISABLE_UNKNOWN;
272 mKeyguardDisabled = false;
273 }
274 }
275 };
276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 final Context mContext;
278
279 final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 final boolean mLimitedAlphaCompositing;
Romain Guy06882f82009-06-10 13:36:04 -0700282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
284
285 final IActivityManager mActivityManager;
Romain Guy06882f82009-06-10 13:36:04 -0700286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287 final IBatteryStats mBatteryStats;
Romain Guy06882f82009-06-10 13:36:04 -0700288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289 /**
290 * All currently active sessions with clients.
291 */
292 final HashSet<Session> mSessions = new HashSet<Session>();
Romain Guy06882f82009-06-10 13:36:04 -0700293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800294 /**
295 * Mapping from an IWindow IBinder to the server's Window object.
296 * This is also used as the lock for all of our state.
297 */
298 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
299
300 /**
301 * Mapping from a token IBinder to a WindowToken object.
302 */
303 final HashMap<IBinder, WindowToken> mTokenMap =
304 new HashMap<IBinder, WindowToken>();
305
306 /**
307 * The same tokens as mTokenMap, stored in a list for efficient iteration
308 * over them.
309 */
310 final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800312 /**
313 * Window tokens that are in the process of exiting, but still
314 * on screen for animations.
315 */
316 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
317
318 /**
319 * Z-ordered (bottom-most first) list of all application tokens, for
320 * controlling the ordering of windows in different applications. This
321 * contains WindowToken objects.
322 */
323 final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
324
325 /**
326 * Application tokens that are in the process of exiting, but still
327 * on screen for animations.
328 */
329 final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
330
331 /**
332 * List of window tokens that have finished starting their application,
333 * and now need to have the policy remove their windows.
334 */
335 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
336
337 /**
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700338 * This was the app token that was used to retrieve the last enter
339 * animation. It will be used for the next exit animation.
340 */
341 AppWindowToken mLastEnterAnimToken;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800342
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700343 /**
344 * These were the layout params used to retrieve the last enter animation.
345 * They will be used for the next exit animation.
346 */
347 LayoutParams mLastEnterAnimParams;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800348
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700349 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 * Z-ordered (bottom-most first) list of all Window objects.
351 */
352 final ArrayList mWindows = new ArrayList();
353
354 /**
355 * Windows that are being resized. Used so we can tell the client about
356 * the resize after closing the transaction in which we resized the
357 * underlying surface.
358 */
359 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
360
361 /**
362 * Windows whose animations have ended and now must be removed.
363 */
364 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
365
366 /**
367 * Windows whose surface should be destroyed.
368 */
369 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
370
371 /**
372 * Windows that have lost input focus and are waiting for the new
373 * focus window to be displayed before they are told about this.
374 */
375 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
376
377 /**
378 * This is set when we have run out of memory, and will either be an empty
379 * list or contain windows that need to be force removed.
380 */
381 ArrayList<WindowState> mForceRemoves;
Romain Guy06882f82009-06-10 13:36:04 -0700382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 IInputMethodManager mInputMethodManager;
Romain Guy06882f82009-06-10 13:36:04 -0700384
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 SurfaceSession mFxSession;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -0700386 private DimAnimator mDimAnimator = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800387 Surface mBlurSurface;
388 boolean mBlurShown;
Romain Guy06882f82009-06-10 13:36:04 -0700389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 int mTransactionSequence = 0;
Romain Guy06882f82009-06-10 13:36:04 -0700391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 final float[] mTmpFloats = new float[9];
393
394 boolean mSafeMode;
395 boolean mDisplayEnabled = false;
396 boolean mSystemBooted = false;
Christopher Tateb696aee2010-04-02 19:08:30 -0700397 int mInitialDisplayWidth = 0;
398 int mInitialDisplayHeight = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399 int mRotation = 0;
400 int mRequestedRotation = 0;
401 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Dianne Hackborn321ae682009-03-27 16:16:03 -0700402 int mLastRotationFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800403 ArrayList<IRotationWatcher> mRotationWatchers
404 = new ArrayList<IRotationWatcher>();
Romain Guy06882f82009-06-10 13:36:04 -0700405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 boolean mLayoutNeeded = true;
407 boolean mAnimationPending = false;
408 boolean mDisplayFrozen = false;
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800409 boolean mWaitingForConfig = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800410 boolean mWindowsFreezingScreen = false;
411 long mFreezeGcPending = 0;
412 int mAppsFreezingScreen = 0;
413
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800414 int mLayoutSeq = 0;
415
Dianne Hackbornb601ce12010-03-01 23:36:02 -0800416 // State while inside of layoutAndPlaceSurfacesLocked().
417 boolean mFocusMayChange;
418
Dianne Hackborne36d6e22010-02-17 19:46:25 -0800419 Configuration mCurConfiguration = new Configuration();
420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 // This is held as long as we have the screen frozen, to give us time to
422 // perform a rotation animation when turning off shows the lock screen which
423 // changes the orientation.
424 PowerManager.WakeLock mScreenFrozenLock;
Romain Guy06882f82009-06-10 13:36:04 -0700425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 // State management of app transitions. When we are preparing for a
427 // transition, mNextAppTransition will be the kind of transition to
428 // perform or TRANSIT_NONE if we are not waiting. If we are waiting,
429 // mOpeningApps and mClosingApps are the lists of tokens that will be
430 // made visible or hidden at the next transition.
Dianne Hackbornbfe319e2009-09-21 00:34:05 -0700431 int mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -0700432 String mNextAppTransitionPackage;
433 int mNextAppTransitionEnter;
434 int mNextAppTransitionExit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 boolean mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -0700436 boolean mAppTransitionRunning = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 boolean mAppTransitionTimeout = false;
438 boolean mStartingIconInTransition = false;
439 boolean mSkipAppTransitionAnimation = false;
440 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
441 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
Dianne Hackborna8f60182009-09-01 19:01:50 -0700442 final ArrayList<AppWindowToken> mToTopApps = new ArrayList<AppWindowToken>();
443 final ArrayList<AppWindowToken> mToBottomApps = new ArrayList<AppWindowToken>();
Romain Guy06882f82009-06-10 13:36:04 -0700444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 //flag to detect fat touch events
446 boolean mFatTouch = false;
447 Display mDisplay;
Romain Guy06882f82009-06-10 13:36:04 -0700448
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 H mH = new H();
450
451 WindowState mCurrentFocus = null;
452 WindowState mLastFocus = null;
Romain Guy06882f82009-06-10 13:36:04 -0700453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 // This just indicates the window the input method is on top of, not
455 // necessarily the window its input is going to.
456 WindowState mInputMethodTarget = null;
457 WindowState mUpcomingInputMethodTarget = null;
458 boolean mInputMethodTargetWaitingAnim;
459 int mInputMethodAnimLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -0700460
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 WindowState mInputMethodWindow = null;
462 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
463
Dianne Hackborn4c62fc02009-08-08 20:40:27 -0700464 final ArrayList<WindowToken> mWallpaperTokens = new ArrayList<WindowToken>();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800465
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700466 // If non-null, this is the currently visible window that is associated
467 // with the wallpaper.
468 WindowState mWallpaperTarget = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -0700469 // If non-null, we are in the middle of animating from one wallpaper target
470 // to another, and this is the lower one in Z-order.
471 WindowState mLowerWallpaperTarget = null;
472 // If non-null, we are in the middle of animating from one wallpaper target
473 // to another, and this is the higher one in Z-order.
474 WindowState mUpperWallpaperTarget = null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -0700475 int mWallpaperAnimLayerAdjustment;
Dianne Hackborn73e92b42009-10-15 14:29:19 -0700476 float mLastWallpaperX = -1;
477 float mLastWallpaperY = -1;
Marco Nelissenbf6956b2009-11-09 15:21:13 -0800478 float mLastWallpaperXStep = -1;
479 float mLastWallpaperYStep = -1;
Dianne Hackborn6adba242009-11-10 11:10:09 -0800480 boolean mSendingPointersToWallpaper = false;
Dianne Hackborn19382ac2009-09-11 21:13:37 -0700481 // This is set when we are waiting for a wallpaper to tell us it is done
482 // changing its scroll position.
483 WindowState mWaitingOnWallpaper;
484 // The last time we had a timeout when waiting for a wallpaper.
485 long mLastWallpaperTimeoutTime;
486 // We give a wallpaper up to 150ms to finish scrolling.
487 static final long WALLPAPER_TIMEOUT = 150;
488 // Time we wait after a timeout before trying to wait again.
489 static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800490
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491 AppWindowToken mFocusedApp = null;
492
493 PowerManagerService mPowerManager;
Romain Guy06882f82009-06-10 13:36:04 -0700494
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 float mWindowAnimationScale = 1.0f;
496 float mTransitionAnimationScale = 1.0f;
Romain Guy06882f82009-06-10 13:36:04 -0700497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 final KeyWaiter mKeyWaiter = new KeyWaiter();
499 final KeyQ mQueue;
500 final InputDispatcherThread mInputThread;
501
502 // Who is holding the screen on.
503 Session mHoldingScreenOn;
Romain Guy06882f82009-06-10 13:36:04 -0700504
Dianne Hackborn93e462b2009-09-15 22:50:40 -0700505 boolean mTurnOnScreen;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 /**
508 * Whether the UI is currently running in touch mode (not showing
509 * navigational focus because the user is directly pressing the screen).
510 */
511 boolean mInTouchMode = false;
512
513 private ViewServer mViewServer;
514
515 final Rect mTempRect = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -0700516
Dianne Hackbornc485a602009-03-24 22:39:49 -0700517 final Configuration mTempConfiguration = new Configuration();
Dianne Hackbornc4db95c2009-07-21 17:46:02 -0700518 int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -0700519
520 // The frame use to limit the size of the app running in compatibility mode.
521 Rect mCompatibleScreenFrame = new Rect();
522 // The surface used to fill the outer rim of the app running in compatibility mode.
523 Surface mBackgroundFillerSurface = null;
524 boolean mBackgroundFillerShown = false;
525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 public static WindowManagerService main(Context context,
527 PowerManagerService pm, boolean haveInputMethods) {
528 WMThread thr = new WMThread(context, pm, haveInputMethods);
529 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 synchronized (thr) {
532 while (thr.mService == null) {
533 try {
534 thr.wait();
535 } catch (InterruptedException e) {
536 }
537 }
538 }
Romain Guy06882f82009-06-10 13:36:04 -0700539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 return thr.mService;
541 }
Romain Guy06882f82009-06-10 13:36:04 -0700542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 static class WMThread extends Thread {
544 WindowManagerService mService;
Romain Guy06882f82009-06-10 13:36:04 -0700545
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800546 private final Context mContext;
547 private final PowerManagerService mPM;
548 private final boolean mHaveInputMethods;
Romain Guy06882f82009-06-10 13:36:04 -0700549
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 public WMThread(Context context, PowerManagerService pm,
551 boolean haveInputMethods) {
552 super("WindowManager");
553 mContext = context;
554 mPM = pm;
555 mHaveInputMethods = haveInputMethods;
556 }
Romain Guy06882f82009-06-10 13:36:04 -0700557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 public void run() {
559 Looper.prepare();
560 WindowManagerService s = new WindowManagerService(mContext, mPM,
561 mHaveInputMethods);
562 android.os.Process.setThreadPriority(
563 android.os.Process.THREAD_PRIORITY_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -0700564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 synchronized (this) {
566 mService = s;
567 notifyAll();
568 }
Romain Guy06882f82009-06-10 13:36:04 -0700569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 Looper.loop();
571 }
572 }
573
574 static class PolicyThread extends Thread {
575 private final WindowManagerPolicy mPolicy;
576 private final WindowManagerService mService;
577 private final Context mContext;
578 private final PowerManagerService mPM;
579 boolean mRunning = false;
Romain Guy06882f82009-06-10 13:36:04 -0700580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 public PolicyThread(WindowManagerPolicy policy,
582 WindowManagerService service, Context context,
583 PowerManagerService pm) {
584 super("WindowManagerPolicy");
585 mPolicy = policy;
586 mService = service;
587 mContext = context;
588 mPM = pm;
589 }
Romain Guy06882f82009-06-10 13:36:04 -0700590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 public void run() {
592 Looper.prepare();
Dianne Hackbornac3587d2010-03-11 11:12:11 -0800593 WindowManagerPolicyThread.set(this, Looper.myLooper());
594
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800595 //Looper.myLooper().setMessageLogging(new LogPrinter(
Joe Onorato8a9b2202010-02-26 18:56:32 -0800596 // Log.VERBOSE, "WindowManagerPolicy", Log.LOG_ID_SYSTEM));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 android.os.Process.setThreadPriority(
598 android.os.Process.THREAD_PRIORITY_FOREGROUND);
599 mPolicy.init(mContext, mService, mPM);
Romain Guy06882f82009-06-10 13:36:04 -0700600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 synchronized (this) {
602 mRunning = true;
603 notifyAll();
604 }
Romain Guy06882f82009-06-10 13:36:04 -0700605
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800606 Looper.loop();
607 }
608 }
609
610 private WindowManagerService(Context context, PowerManagerService pm,
611 boolean haveInputMethods) {
Michael Chan53071d62009-05-13 17:29:48 -0700612 if (MEASURE_LATENCY) {
613 lt = new LatencyTimer(100, 1000);
614 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800615
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 mContext = context;
617 mHaveInputMethods = haveInputMethods;
618 mLimitedAlphaCompositing = context.getResources().getBoolean(
619 com.android.internal.R.bool.config_sf_limitedAlpha);
Romain Guy06882f82009-06-10 13:36:04 -0700620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800621 mPowerManager = pm;
622 mPowerManager.setPolicy(mPolicy);
623 PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
624 mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
625 "SCREEN_FROZEN");
626 mScreenFrozenLock.setReferenceCounted(false);
627
628 mActivityManager = ActivityManagerNative.getDefault();
629 mBatteryStats = BatteryStatsService.getService();
630
631 // Get persisted window scale setting
632 mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
633 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
634 mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
635 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
Romain Guy06882f82009-06-10 13:36:04 -0700636
Jim Miller284b62e2010-06-08 14:27:42 -0700637 // Track changes to DevicePolicyManager state so we can enable/disable keyguard.
638 IntentFilter filter = new IntentFilter();
639 filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
640 mContext.registerReceiver(mBroadcastReceiver, filter);
641
Michael Chan9f028e62009-08-04 17:37:46 -0700642 int max_events_per_sec = 35;
643 try {
644 max_events_per_sec = Integer.parseInt(SystemProperties
645 .get("windowsmgr.max_events_per_sec"));
646 if (max_events_per_sec < 1) {
647 max_events_per_sec = 35;
648 }
649 } catch (NumberFormatException e) {
650 }
651 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
652
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653 mQueue = new KeyQ();
654
655 mInputThread = new InputDispatcherThread();
Romain Guy06882f82009-06-10 13:36:04 -0700656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800657 PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
658 thr.start();
Romain Guy06882f82009-06-10 13:36:04 -0700659
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 synchronized (thr) {
661 while (!thr.mRunning) {
662 try {
663 thr.wait();
664 } catch (InterruptedException e) {
665 }
666 }
667 }
Romain Guy06882f82009-06-10 13:36:04 -0700668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 mInputThread.start();
Romain Guy06882f82009-06-10 13:36:04 -0700670
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800671 // Add ourself to the Watchdog monitors.
672 Watchdog.getInstance().addMonitor(this);
673 }
674
675 @Override
676 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
677 throws RemoteException {
678 try {
679 return super.onTransact(code, data, reply, flags);
680 } catch (RuntimeException e) {
681 // The window manager only throws security exceptions, so let's
682 // log all others.
683 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800684 Slog.e(TAG, "Window Manager Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685 }
686 throw e;
687 }
688 }
689
690 private void placeWindowAfter(Object pos, WindowState window) {
691 final int i = mWindows.indexOf(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800692 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800693 TAG, "Adding window " + window + " at "
694 + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
695 mWindows.add(i+1, window);
696 }
697
698 private void placeWindowBefore(Object pos, WindowState window) {
699 final int i = mWindows.indexOf(pos);
Joe Onorato8a9b2202010-02-26 18:56:32 -0800700 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800701 TAG, "Adding window " + window + " at "
702 + i + " of " + mWindows.size() + " (before " + pos + ")");
703 mWindows.add(i, window);
704 }
705
706 //This method finds out the index of a window that has the same app token as
707 //win. used for z ordering the windows in mWindows
708 private int findIdxBasedOnAppTokens(WindowState win) {
709 //use a local variable to cache mWindows
710 ArrayList localmWindows = mWindows;
711 int jmax = localmWindows.size();
712 if(jmax == 0) {
713 return -1;
714 }
715 for(int j = (jmax-1); j >= 0; j--) {
716 WindowState wentry = (WindowState)localmWindows.get(j);
717 if(wentry.mAppToken == win.mAppToken) {
718 return j;
719 }
720 }
721 return -1;
722 }
Romain Guy06882f82009-06-10 13:36:04 -0700723
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800724 private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
725 final IWindow client = win.mClient;
726 final WindowToken token = win.mToken;
727 final ArrayList localmWindows = mWindows;
Romain Guy06882f82009-06-10 13:36:04 -0700728
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729 final int N = localmWindows.size();
730 final WindowState attached = win.mAttachedWindow;
731 int i;
732 if (attached == null) {
733 int tokenWindowsPos = token.windows.size();
734 if (token.appWindowToken != null) {
735 int index = tokenWindowsPos-1;
736 if (index >= 0) {
737 // If this application has existing windows, we
738 // simply place the new window on top of them... but
739 // keep the starting window on top.
740 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
741 // Base windows go behind everything else.
742 placeWindowBefore(token.windows.get(0), win);
743 tokenWindowsPos = 0;
744 } else {
745 AppWindowToken atoken = win.mAppToken;
746 if (atoken != null &&
747 token.windows.get(index) == atoken.startingWindow) {
748 placeWindowBefore(token.windows.get(index), win);
749 tokenWindowsPos--;
750 } else {
751 int newIdx = findIdxBasedOnAppTokens(win);
752 if(newIdx != -1) {
Romain Guy06882f82009-06-10 13:36:04 -0700753 //there is a window above this one associated with the same
754 //apptoken note that the window could be a floating window
755 //that was created later or a window at the top of the list of
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800756 //windows associated with this token.
Joe Onorato8a9b2202010-02-26 18:56:32 -0800757 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700758 TAG, "Adding window " + win + " at "
759 + (newIdx+1) + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760 localmWindows.add(newIdx+1, win);
Romain Guy06882f82009-06-10 13:36:04 -0700761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 }
763 }
764 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800765 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800766 TAG, "Figuring out where to add app window "
767 + client.asBinder() + " (token=" + token + ")");
768 // Figure out where the window should go, based on the
769 // order of applications.
770 final int NA = mAppTokens.size();
771 Object pos = null;
772 for (i=NA-1; i>=0; i--) {
773 AppWindowToken t = mAppTokens.get(i);
774 if (t == token) {
775 i--;
776 break;
777 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800778
Dianne Hackborna8f60182009-09-01 19:01:50 -0700779 // We haven't reached the token yet; if this token
780 // is not going to the bottom and has windows, we can
781 // use it as an anchor for when we do reach the token.
782 if (!t.sendingToBottom && t.windows.size() > 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800783 pos = t.windows.get(0);
784 }
785 }
786 // We now know the index into the apps. If we found
787 // an app window above, that gives us the position; else
788 // we need to look some more.
789 if (pos != null) {
790 // Move behind any windows attached to this one.
Romain Guy06882f82009-06-10 13:36:04 -0700791 WindowToken atoken =
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792 mTokenMap.get(((WindowState)pos).mClient.asBinder());
793 if (atoken != null) {
794 final int NC = atoken.windows.size();
795 if (NC > 0) {
796 WindowState bottom = atoken.windows.get(0);
797 if (bottom.mSubLayer < 0) {
798 pos = bottom;
799 }
800 }
801 }
802 placeWindowBefore(pos, win);
803 } else {
Dianne Hackborna8f60182009-09-01 19:01:50 -0700804 // Continue looking down until we find the first
805 // token that has windows.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 while (i >= 0) {
807 AppWindowToken t = mAppTokens.get(i);
808 final int NW = t.windows.size();
809 if (NW > 0) {
810 pos = t.windows.get(NW-1);
811 break;
812 }
813 i--;
814 }
815 if (pos != null) {
816 // Move in front of any windows attached to this
817 // one.
818 WindowToken atoken =
819 mTokenMap.get(((WindowState)pos).mClient.asBinder());
820 if (atoken != null) {
821 final int NC = atoken.windows.size();
822 if (NC > 0) {
823 WindowState top = atoken.windows.get(NC-1);
824 if (top.mSubLayer >= 0) {
825 pos = top;
826 }
827 }
828 }
829 placeWindowAfter(pos, win);
830 } else {
831 // Just search for the start of this layer.
832 final int myLayer = win.mBaseLayer;
833 for (i=0; i<N; i++) {
834 WindowState w = (WindowState)localmWindows.get(i);
835 if (w.mBaseLayer > myLayer) {
836 break;
837 }
838 }
Joe Onorato8a9b2202010-02-26 18:56:32 -0800839 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700840 TAG, "Adding window " + win + " at "
841 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842 localmWindows.add(i, win);
843 }
844 }
845 }
846 } else {
847 // Figure out where window should go, based on layer.
848 final int myLayer = win.mBaseLayer;
849 for (i=N-1; i>=0; i--) {
850 if (((WindowState)localmWindows.get(i)).mBaseLayer <= myLayer) {
851 i++;
852 break;
853 }
854 }
855 if (i < 0) i = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -0800856 if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -0700857 TAG, "Adding window " + win + " at "
858 + i + " of " + N);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 localmWindows.add(i, win);
860 }
861 if (addToToken) {
862 token.windows.add(tokenWindowsPos, win);
863 }
864
865 } else {
866 // Figure out this window's ordering relative to the window
867 // it is attached to.
868 final int NA = token.windows.size();
869 final int sublayer = win.mSubLayer;
870 int largestSublayer = Integer.MIN_VALUE;
871 WindowState windowWithLargestSublayer = null;
872 for (i=0; i<NA; i++) {
873 WindowState w = token.windows.get(i);
874 final int wSublayer = w.mSubLayer;
875 if (wSublayer >= largestSublayer) {
876 largestSublayer = wSublayer;
877 windowWithLargestSublayer = w;
878 }
879 if (sublayer < 0) {
880 // For negative sublayers, we go below all windows
881 // in the same sublayer.
882 if (wSublayer >= sublayer) {
883 if (addToToken) {
884 token.windows.add(i, win);
885 }
886 placeWindowBefore(
887 wSublayer >= 0 ? attached : w, win);
888 break;
889 }
890 } else {
891 // For positive sublayers, we go above all windows
892 // in the same sublayer.
893 if (wSublayer > sublayer) {
894 if (addToToken) {
895 token.windows.add(i, win);
896 }
897 placeWindowBefore(w, win);
898 break;
899 }
900 }
901 }
902 if (i >= NA) {
903 if (addToToken) {
904 token.windows.add(win);
905 }
906 if (sublayer < 0) {
907 placeWindowBefore(attached, win);
908 } else {
909 placeWindowAfter(largestSublayer >= 0
910 ? windowWithLargestSublayer
911 : attached,
912 win);
913 }
914 }
915 }
Romain Guy06882f82009-06-10 13:36:04 -0700916
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 if (win.mAppToken != null && addToToken) {
918 win.mAppToken.allAppWindows.add(win);
919 }
920 }
Romain Guy06882f82009-06-10 13:36:04 -0700921
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 static boolean canBeImeTarget(WindowState w) {
923 final int fl = w.mAttrs.flags
924 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
925 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
926 return w.isVisibleOrAdding();
927 }
928 return false;
929 }
Romain Guy06882f82009-06-10 13:36:04 -0700930
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931 int findDesiredInputMethodWindowIndexLocked(boolean willMove) {
932 final ArrayList localmWindows = mWindows;
933 final int N = localmWindows.size();
934 WindowState w = null;
935 int i = N;
936 while (i > 0) {
937 i--;
938 w = (WindowState)localmWindows.get(i);
Romain Guy06882f82009-06-10 13:36:04 -0700939
Joe Onorato8a9b2202010-02-26 18:56:32 -0800940 //Slog.i(TAG, "Checking window @" + i + " " + w + " fl=0x"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 // + Integer.toHexString(w.mAttrs.flags));
942 if (canBeImeTarget(w)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800943 //Slog.i(TAG, "Putting input method here!");
Romain Guy06882f82009-06-10 13:36:04 -0700944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 // Yet more tricksyness! If this window is a "starting"
946 // window, we do actually want to be on top of it, but
947 // it is not -really- where input will go. So if the caller
948 // is not actually looking to move the IME, look down below
949 // for a real window to target...
950 if (!willMove
951 && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
952 && i > 0) {
953 WindowState wb = (WindowState)localmWindows.get(i-1);
954 if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
955 i--;
956 w = wb;
957 }
958 }
959 break;
960 }
961 }
Romain Guy06882f82009-06-10 13:36:04 -0700962
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800963 mUpcomingInputMethodTarget = w;
Romain Guy06882f82009-06-10 13:36:04 -0700964
Joe Onorato8a9b2202010-02-26 18:56:32 -0800965 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Desired input method target="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800966 + w + " willMove=" + willMove);
Romain Guy06882f82009-06-10 13:36:04 -0700967
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800968 if (willMove && w != null) {
969 final WindowState curTarget = mInputMethodTarget;
970 if (curTarget != null && curTarget.mAppToken != null) {
Romain Guy06882f82009-06-10 13:36:04 -0700971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 // Now some fun for dealing with window animations that
973 // modify the Z order. We need to look at all windows below
974 // the current target that are in this app, finding the highest
975 // visible one in layering.
976 AppWindowToken token = curTarget.mAppToken;
977 WindowState highestTarget = null;
978 int highestPos = 0;
979 if (token.animating || token.animation != null) {
980 int pos = 0;
981 pos = localmWindows.indexOf(curTarget);
982 while (pos >= 0) {
983 WindowState win = (WindowState)localmWindows.get(pos);
984 if (win.mAppToken != token) {
985 break;
986 }
987 if (!win.mRemoved) {
988 if (highestTarget == null || win.mAnimLayer >
989 highestTarget.mAnimLayer) {
990 highestTarget = win;
991 highestPos = pos;
992 }
993 }
994 pos--;
995 }
996 }
Romain Guy06882f82009-06-10 13:36:04 -0700997
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800998 if (highestTarget != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -0800999 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "mNextAppTransition="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001000 + mNextAppTransition + " " + highestTarget
1001 + " animating=" + highestTarget.isAnimating()
1002 + " layer=" + highestTarget.mAnimLayer
1003 + " new layer=" + w.mAnimLayer);
Romain Guy06882f82009-06-10 13:36:04 -07001004
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001005 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001006 // If we are currently setting up for an animation,
1007 // hold everything until we can find out what will happen.
1008 mInputMethodTargetWaitingAnim = true;
1009 mInputMethodTarget = highestTarget;
1010 return highestPos + 1;
1011 } else if (highestTarget.isAnimating() &&
1012 highestTarget.mAnimLayer > w.mAnimLayer) {
1013 // If the window we are currently targeting is involved
1014 // with an animation, and it is on top of the next target
1015 // we will be over, then hold off on moving until
1016 // that is done.
1017 mInputMethodTarget = highestTarget;
1018 return highestPos + 1;
1019 }
1020 }
1021 }
1022 }
Romain Guy06882f82009-06-10 13:36:04 -07001023
Joe Onorato8a9b2202010-02-26 18:56:32 -08001024 //Slog.i(TAG, "Placing input method @" + (i+1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 if (w != null) {
1026 if (willMove) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08001027 if (DEBUG_INPUT_METHOD) {
1028 RuntimeException e = null;
1029 if (!HIDE_STACK_CRAWLS) {
1030 e = new RuntimeException();
1031 e.fillInStackTrace();
1032 }
1033 Slog.w(TAG, "Moving IM target from "
1034 + mInputMethodTarget + " to " + w, e);
1035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036 mInputMethodTarget = w;
1037 if (w.mAppToken != null) {
1038 setInputMethodAnimLayerAdjustment(w.mAppToken.animLayerAdjustment);
1039 } else {
1040 setInputMethodAnimLayerAdjustment(0);
1041 }
1042 }
1043 return i+1;
1044 }
1045 if (willMove) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08001046 if (DEBUG_INPUT_METHOD) {
1047 RuntimeException e = null;
1048 if (!HIDE_STACK_CRAWLS) {
1049 e = new RuntimeException();
1050 e.fillInStackTrace();
1051 }
1052 Slog.w(TAG, "Moving IM target from "
1053 + mInputMethodTarget + " to null", e);
1054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 mInputMethodTarget = null;
1056 setInputMethodAnimLayerAdjustment(0);
1057 }
1058 return -1;
1059 }
Romain Guy06882f82009-06-10 13:36:04 -07001060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001061 void addInputMethodWindowToListLocked(WindowState win) {
1062 int pos = findDesiredInputMethodWindowIndexLocked(true);
1063 if (pos >= 0) {
1064 win.mTargetAppToken = mInputMethodTarget.mAppToken;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001065 if (DEBUG_WINDOW_MOVEMENT) Slog.v(
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001066 TAG, "Adding input method window " + win + " at " + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 mWindows.add(pos, win);
1068 moveInputMethodDialogsLocked(pos+1);
1069 return;
1070 }
1071 win.mTargetAppToken = null;
1072 addWindowToListInOrderLocked(win, true);
1073 moveInputMethodDialogsLocked(pos);
1074 }
Romain Guy06882f82009-06-10 13:36:04 -07001075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 void setInputMethodAnimLayerAdjustment(int adj) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001077 if (DEBUG_LAYERS) Slog.v(TAG, "Setting im layer adj to " + adj);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001078 mInputMethodAnimLayerAdjustment = adj;
1079 WindowState imw = mInputMethodWindow;
1080 if (imw != null) {
1081 imw.mAnimLayer = imw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001082 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 + " anim layer: " + imw.mAnimLayer);
1084 int wi = imw.mChildWindows.size();
1085 while (wi > 0) {
1086 wi--;
1087 WindowState cw = (WindowState)imw.mChildWindows.get(wi);
1088 cw.mAnimLayer = cw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001089 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + cw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090 + " anim layer: " + cw.mAnimLayer);
1091 }
1092 }
1093 int di = mInputMethodDialogs.size();
1094 while (di > 0) {
1095 di --;
1096 imw = mInputMethodDialogs.get(di);
1097 imw.mAnimLayer = imw.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001098 if (DEBUG_LAYERS) Slog.v(TAG, "IM win " + imw
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 + " anim layer: " + imw.mAnimLayer);
1100 }
1101 }
Romain Guy06882f82009-06-10 13:36:04 -07001102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
1104 int wpos = mWindows.indexOf(win);
1105 if (wpos >= 0) {
1106 if (wpos < interestingPos) interestingPos--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001107 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing at " + wpos + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108 mWindows.remove(wpos);
1109 int NC = win.mChildWindows.size();
1110 while (NC > 0) {
1111 NC--;
1112 WindowState cw = (WindowState)win.mChildWindows.get(NC);
1113 int cpos = mWindows.indexOf(cw);
1114 if (cpos >= 0) {
1115 if (cpos < interestingPos) interestingPos--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001116 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Temp removing child at "
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001117 + cpos + ": " + cw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 mWindows.remove(cpos);
1119 }
1120 }
1121 }
1122 return interestingPos;
1123 }
Romain Guy06882f82009-06-10 13:36:04 -07001124
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125 private void reAddWindowToListInOrderLocked(WindowState win) {
1126 addWindowToListInOrderLocked(win, false);
1127 // This is a hack to get all of the child windows added as well
1128 // at the right position. Child windows should be rare and
1129 // this case should be rare, so it shouldn't be that big a deal.
1130 int wpos = mWindows.indexOf(win);
1131 if (wpos >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001132 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "ReAdd removing from " + wpos
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001133 + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 mWindows.remove(wpos);
1135 reAddWindowLocked(wpos, win);
1136 }
1137 }
Romain Guy06882f82009-06-10 13:36:04 -07001138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139 void logWindowList(String prefix) {
1140 int N = mWindows.size();
1141 while (N > 0) {
1142 N--;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001143 Slog.v(TAG, prefix + "#" + N + ": " + mWindows.get(N));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144 }
1145 }
Romain Guy06882f82009-06-10 13:36:04 -07001146
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 void moveInputMethodDialogsLocked(int pos) {
1148 ArrayList<WindowState> dialogs = mInputMethodDialogs;
Romain Guy06882f82009-06-10 13:36:04 -07001149
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001150 final int N = dialogs.size();
Joe Onorato8a9b2202010-02-26 18:56:32 -08001151 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Removing " + N + " dialogs w/pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 for (int i=0; i<N; i++) {
1153 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
1154 }
1155 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001156 Slog.v(TAG, "Window list w/pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001157 logWindowList(" ");
1158 }
Romain Guy06882f82009-06-10 13:36:04 -07001159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 if (pos >= 0) {
1161 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
1162 if (pos < mWindows.size()) {
1163 WindowState wp = (WindowState)mWindows.get(pos);
1164 if (wp == mInputMethodWindow) {
1165 pos++;
1166 }
1167 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001168 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Adding " + N + " dialogs at pos=" + pos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 for (int i=0; i<N; i++) {
1170 WindowState win = dialogs.get(i);
1171 win.mTargetAppToken = targetAppToken;
1172 pos = reAddWindowLocked(pos, win);
1173 }
1174 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001175 Slog.v(TAG, "Final window list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001176 logWindowList(" ");
1177 }
1178 return;
1179 }
1180 for (int i=0; i<N; i++) {
1181 WindowState win = dialogs.get(i);
1182 win.mTargetAppToken = null;
1183 reAddWindowToListInOrderLocked(win);
1184 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001185 Slog.v(TAG, "No IM target, final list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 logWindowList(" ");
1187 }
1188 }
1189 }
Romain Guy06882f82009-06-10 13:36:04 -07001190
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001191 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
1192 final WindowState imWin = mInputMethodWindow;
1193 final int DN = mInputMethodDialogs.size();
1194 if (imWin == null && DN == 0) {
1195 return false;
1196 }
Romain Guy06882f82009-06-10 13:36:04 -07001197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 int imPos = findDesiredInputMethodWindowIndexLocked(true);
1199 if (imPos >= 0) {
1200 // In this case, the input method windows are to be placed
1201 // immediately above the window they are targeting.
Romain Guy06882f82009-06-10 13:36:04 -07001202
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 // First check to see if the input method windows are already
1204 // located here, and contiguous.
1205 final int N = mWindows.size();
1206 WindowState firstImWin = imPos < N
1207 ? (WindowState)mWindows.get(imPos) : null;
Romain Guy06882f82009-06-10 13:36:04 -07001208
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001209 // Figure out the actual input method window that should be
1210 // at the bottom of their stack.
1211 WindowState baseImWin = imWin != null
1212 ? imWin : mInputMethodDialogs.get(0);
1213 if (baseImWin.mChildWindows.size() > 0) {
1214 WindowState cw = (WindowState)baseImWin.mChildWindows.get(0);
1215 if (cw.mSubLayer < 0) baseImWin = cw;
1216 }
Romain Guy06882f82009-06-10 13:36:04 -07001217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 if (firstImWin == baseImWin) {
1219 // The windows haven't moved... but are they still contiguous?
1220 // First find the top IM window.
1221 int pos = imPos+1;
1222 while (pos < N) {
1223 if (!((WindowState)mWindows.get(pos)).mIsImWindow) {
1224 break;
1225 }
1226 pos++;
1227 }
1228 pos++;
1229 // Now there should be no more input method windows above.
1230 while (pos < N) {
1231 if (((WindowState)mWindows.get(pos)).mIsImWindow) {
1232 break;
1233 }
1234 pos++;
1235 }
1236 if (pos >= N) {
1237 // All is good!
1238 return false;
1239 }
1240 }
Romain Guy06882f82009-06-10 13:36:04 -07001241
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242 if (imWin != null) {
1243 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001244 Slog.v(TAG, "Moving IM from " + imPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001245 logWindowList(" ");
1246 }
1247 imPos = tmpRemoveWindowLocked(imPos, imWin);
1248 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001249 Slog.v(TAG, "List after moving with new pos " + imPos + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001250 logWindowList(" ");
1251 }
1252 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
1253 reAddWindowLocked(imPos, imWin);
1254 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001255 Slog.v(TAG, "List after moving IM to " + imPos + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 logWindowList(" ");
1257 }
1258 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
1259 } else {
1260 moveInputMethodDialogsLocked(imPos);
1261 }
Romain Guy06882f82009-06-10 13:36:04 -07001262
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263 } else {
1264 // In this case, the input method windows go in a fixed layer,
1265 // because they aren't currently associated with a focus window.
Romain Guy06882f82009-06-10 13:36:04 -07001266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001267 if (imWin != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001268 if (DEBUG_INPUT_METHOD) Slog.v(TAG, "Moving IM from " + imPos);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001269 tmpRemoveWindowLocked(0, imWin);
1270 imWin.mTargetAppToken = null;
1271 reAddWindowToListInOrderLocked(imWin);
1272 if (DEBUG_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001273 Slog.v(TAG, "List with no IM target:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001274 logWindowList(" ");
1275 }
1276 if (DN > 0) moveInputMethodDialogsLocked(-1);;
1277 } else {
1278 moveInputMethodDialogsLocked(-1);;
1279 }
Romain Guy06882f82009-06-10 13:36:04 -07001280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281 }
Romain Guy06882f82009-06-10 13:36:04 -07001282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 if (needAssignLayers) {
1284 assignLayersLocked();
1285 }
Romain Guy06882f82009-06-10 13:36:04 -07001286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001287 return true;
1288 }
Romain Guy06882f82009-06-10 13:36:04 -07001289
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001290 void adjustInputMethodDialogsLocked() {
1291 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked(true));
1292 }
Romain Guy06882f82009-06-10 13:36:04 -07001293
Dianne Hackborn25994b42009-09-04 14:21:19 -07001294 final boolean isWallpaperVisible(WindowState wallpaperTarget) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001295 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target obscured="
Dianne Hackborn25994b42009-09-04 14:21:19 -07001296 + (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
1297 + " anim=" + ((wallpaperTarget != null && wallpaperTarget.mAppToken != null)
1298 ? wallpaperTarget.mAppToken.animation : null)
1299 + " upper=" + mUpperWallpaperTarget
1300 + " lower=" + mLowerWallpaperTarget);
1301 return (wallpaperTarget != null
1302 && (!wallpaperTarget.mObscured || (wallpaperTarget.mAppToken != null
1303 && wallpaperTarget.mAppToken.animation != null)))
1304 || mUpperWallpaperTarget != null
1305 || mLowerWallpaperTarget != null;
1306 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001307
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001308 static final int ADJUST_WALLPAPER_LAYERS_CHANGED = 1<<1;
1309 static final int ADJUST_WALLPAPER_VISIBILITY_CHANGED = 1<<2;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001310
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001311 int adjustWallpaperWindowsLocked() {
1312 int changed = 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001313
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001314 final int dw = mDisplay.getWidth();
1315 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001316
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001317 // First find top-most window that has asked to be on top of the
1318 // wallpaper; all wallpapers go behind it.
1319 final ArrayList localmWindows = mWindows;
1320 int N = localmWindows.size();
1321 WindowState w = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001322 WindowState foundW = null;
1323 int foundI = 0;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001324 WindowState topCurW = null;
1325 int topCurI = 0;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001326 int i = N;
1327 while (i > 0) {
1328 i--;
1329 w = (WindowState)localmWindows.get(i);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001330 if ((w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER)) {
1331 if (topCurW == null) {
1332 topCurW = w;
1333 topCurI = i;
1334 }
1335 continue;
1336 }
1337 topCurW = null;
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001338 if (w.mAppToken != null) {
1339 // If this window's app token is hidden and not animating,
1340 // it is of no interest to us.
1341 if (w.mAppToken.hidden && w.mAppToken.animation == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001342 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001343 "Skipping hidden or animating token: " + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001344 topCurW = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001345 continue;
1346 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001347 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001348 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w + ": readyfordisplay="
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001349 + w.isReadyForDisplay() + " drawpending=" + w.mDrawPending
1350 + " commitdrawpending=" + w.mCommitDrawPending);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001351 if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07001352 && (mWallpaperTarget == w
1353 || (!w.mDrawPending && !w.mCommitDrawPending))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001354 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001355 "Found wallpaper activity: #" + i + "=" + w);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001356 foundW = w;
1357 foundI = i;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001358 if (w == mWallpaperTarget && ((w.mAppToken != null
1359 && w.mAppToken.animation != null)
1360 || w.mAnimation != null)) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001361 // The current wallpaper target is animating, so we'll
1362 // look behind it for another possible target and figure
1363 // out what is going on below.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001364 if (DEBUG_WALLPAPER) Slog.v(TAG, "Win " + w
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001365 + ": token animating, looking behind.");
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001366 continue;
1367 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001368 break;
1369 }
1370 }
1371
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07001372 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001373 // If we are currently waiting for an app transition, and either
1374 // the current target or the next target are involved with it,
1375 // then hold off on doing anything with the wallpaper.
1376 // Note that we are checking here for just whether the target
1377 // is part of an app token... which is potentially overly aggressive
1378 // (the app token may not be involved in the transition), but good
1379 // enough (we'll just wait until whatever transition is pending
1380 // executes).
1381 if (mWallpaperTarget != null && mWallpaperTarget.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001382 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001383 "Wallpaper not changing: waiting for app anim in current target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001384 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001385 }
1386 if (foundW != null && foundW.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001387 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001388 "Wallpaper not changing: waiting for app anim in found target");
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001389 return 0;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001390 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001391 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001392
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001393 if (mWallpaperTarget != foundW) {
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001394 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001395 Slog.v(TAG, "New wallpaper target: " + foundW
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001396 + " oldTarget: " + mWallpaperTarget);
1397 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001398
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001399 mLowerWallpaperTarget = null;
1400 mUpperWallpaperTarget = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001401
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001402 WindowState oldW = mWallpaperTarget;
1403 mWallpaperTarget = foundW;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001404
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001405 // Now what is happening... if the current and new targets are
1406 // animating, then we are in our super special mode!
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001407 if (foundW != null && oldW != null) {
1408 boolean oldAnim = oldW.mAnimation != null
1409 || (oldW.mAppToken != null && oldW.mAppToken.animation != null);
1410 boolean foundAnim = foundW.mAnimation != null
1411 || (foundW.mAppToken != null && foundW.mAppToken.animation != null);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001412 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001413 Slog.v(TAG, "New animation: " + foundAnim
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001414 + " old animation: " + oldAnim);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001415 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001416 if (foundAnim && oldAnim) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001417 int oldI = localmWindows.indexOf(oldW);
1418 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001419 Slog.v(TAG, "New i: " + foundI + " old i: " + oldI);
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001420 }
1421 if (oldI >= 0) {
1422 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001423 Slog.v(TAG, "Animating wallpapers: old#" + oldI
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001424 + "=" + oldW + "; new#" + foundI
1425 + "=" + foundW);
1426 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001427
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001428 // Set the new target correctly.
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001429 if (foundW.mAppToken != null && foundW.mAppToken.hiddenRequested) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001430 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001431 Slog.v(TAG, "Old wallpaper still the target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001432 }
1433 mWallpaperTarget = oldW;
1434 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001435
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001436 // Now set the upper and lower wallpaper targets
1437 // correctly, and make sure that we are positioning
1438 // the wallpaper below the lower.
1439 if (foundI > oldI) {
1440 // The new target is on top of the old one.
1441 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001442 Slog.v(TAG, "Found target above old target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001443 }
1444 mUpperWallpaperTarget = foundW;
1445 mLowerWallpaperTarget = oldW;
1446 foundW = oldW;
1447 foundI = oldI;
1448 } else {
1449 // The new target is below the old one.
1450 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001451 Slog.v(TAG, "Found target below old target.");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001452 }
1453 mUpperWallpaperTarget = oldW;
1454 mLowerWallpaperTarget = foundW;
1455 }
1456 }
1457 }
1458 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001459
Dianne Hackborn6b1cb352009-09-28 18:27:26 -07001460 } else if (mLowerWallpaperTarget != null) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001461 // Is it time to stop animating?
Dianne Hackborn6b1cb352009-09-28 18:27:26 -07001462 boolean lowerAnimating = mLowerWallpaperTarget.mAnimation != null
1463 || (mLowerWallpaperTarget.mAppToken != null
1464 && mLowerWallpaperTarget.mAppToken.animation != null);
1465 boolean upperAnimating = mUpperWallpaperTarget.mAnimation != null
1466 || (mUpperWallpaperTarget.mAppToken != null
1467 && mUpperWallpaperTarget.mAppToken.animation != null);
1468 if (!lowerAnimating || !upperAnimating) {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001469 if (DEBUG_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001470 Slog.v(TAG, "No longer animating wallpaper targets!");
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001471 }
1472 mLowerWallpaperTarget = null;
1473 mUpperWallpaperTarget = null;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001474 }
1475 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001476
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001477 boolean visible = foundW != null;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001478 if (visible) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001479 // The window is visible to the compositor... but is it visible
1480 // to the user? That is what the wallpaper cares about.
Dianne Hackborn25994b42009-09-04 14:21:19 -07001481 visible = isWallpaperVisible(foundW);
Joe Onorato8a9b2202010-02-26 18:56:32 -08001482 if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper visibility: " + visible);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001483
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001484 // If the wallpaper target is animating, we may need to copy
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001485 // its layer adjustment. Only do this if we are not transfering
1486 // between two wallpaper targets.
1487 mWallpaperAnimLayerAdjustment =
Dianne Hackborn3be63c02009-08-20 19:31:38 -07001488 (mLowerWallpaperTarget == null && foundW.mAppToken != null)
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001489 ? foundW.mAppToken.animLayerAdjustment : 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001490
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001491 final int maxLayer = mPolicy.getMaxWallpaperLayer()
1492 * TYPE_LAYER_MULTIPLIER
1493 + TYPE_LAYER_OFFSET;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001494
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001495 // Now w is the window we are supposed to be behind... but we
1496 // need to be sure to also be behind any of its attached windows,
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001497 // AND any starting window associated with it, AND below the
1498 // maximum layer the policy allows for wallpapers.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001499 while (foundI > 0) {
1500 WindowState wb = (WindowState)localmWindows.get(foundI-1);
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07001501 if (wb.mBaseLayer < maxLayer &&
1502 wb.mAttachedWindow != foundW &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001503 (wb.mAttrs.type != TYPE_APPLICATION_STARTING ||
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001504 wb.mToken != foundW.mToken)) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001505 // This window is not related to the previous one in any
1506 // interesting way, so stop here.
1507 break;
1508 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001509 foundW = wb;
1510 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001511 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07001512 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001513 if (DEBUG_WALLPAPER) Slog.v(TAG, "No wallpaper target");
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001514 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001515
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07001516 if (foundW == null && topCurW != null) {
1517 // There is no wallpaper target, so it goes at the bottom.
1518 // We will assume it is the same place as last time, if known.
1519 foundW = topCurW;
1520 foundI = topCurI+1;
1521 } else {
1522 // Okay i is the position immediately above the wallpaper. Look at
1523 // what is below it for later.
1524 foundW = foundI > 0 ? (WindowState)localmWindows.get(foundI-1) : null;
1525 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001526
Dianne Hackborn284ac932009-08-28 10:34:25 -07001527 if (visible) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001528 if (mWallpaperTarget.mWallpaperX >= 0) {
1529 mLastWallpaperX = mWallpaperTarget.mWallpaperX;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001530 mLastWallpaperXStep = mWallpaperTarget.mWallpaperXStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001531 }
1532 if (mWallpaperTarget.mWallpaperY >= 0) {
1533 mLastWallpaperY = mWallpaperTarget.mWallpaperY;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001534 mLastWallpaperYStep = mWallpaperTarget.mWallpaperYStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001535 }
Dianne Hackborn284ac932009-08-28 10:34:25 -07001536 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001537
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001538 // Start stepping backwards from here, ensuring that our wallpaper windows
1539 // are correctly placed.
1540 int curTokenIndex = mWallpaperTokens.size();
1541 while (curTokenIndex > 0) {
1542 curTokenIndex--;
1543 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001544 if (token.hidden == visible) {
1545 changed |= ADJUST_WALLPAPER_VISIBILITY_CHANGED;
1546 token.hidden = !visible;
1547 // Need to do a layout to ensure the wallpaper now has the
1548 // correct size.
1549 mLayoutNeeded = true;
1550 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001551
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001552 int curWallpaperIndex = token.windows.size();
1553 while (curWallpaperIndex > 0) {
1554 curWallpaperIndex--;
1555 WindowState wallpaper = token.windows.get(curWallpaperIndex);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001556
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001557 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001558 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001559 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001560
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001561 // First, make sure the client has the current visibility
1562 // state.
1563 if (wallpaper.mWallpaperVisible != visible) {
1564 wallpaper.mWallpaperVisible = visible;
1565 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001566 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001567 "Setting visibility of wallpaper " + wallpaper
1568 + ": " + visible);
1569 wallpaper.mClient.dispatchAppVisibility(visible);
1570 } catch (RemoteException e) {
1571 }
1572 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001573
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001574 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001575 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001576 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001577
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001578 // First, if this window is at the current index, then all
1579 // is well.
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001580 if (wallpaper == foundW) {
1581 foundI--;
1582 foundW = foundI > 0
1583 ? (WindowState)localmWindows.get(foundI-1) : null;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001584 continue;
1585 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001586
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001587 // The window didn't match... the current wallpaper window,
1588 // wherever it is, is in the wrong place, so make sure it is
1589 // not in the list.
1590 int oldIndex = localmWindows.indexOf(wallpaper);
1591 if (oldIndex >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001592 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Wallpaper removing at "
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001593 + oldIndex + ": " + wallpaper);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001594 localmWindows.remove(oldIndex);
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001595 if (oldIndex < foundI) {
1596 foundI--;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001597 }
1598 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001599
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001600 // Now stick it in.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001601 if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07001602 "Moving wallpaper " + wallpaper
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001603 + " from " + oldIndex + " to " + foundI);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001604
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07001605 localmWindows.add(foundI, wallpaper);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001606 changed |= ADJUST_WALLPAPER_LAYERS_CHANGED;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001607 }
1608 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001609
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001610 return changed;
1611 }
1612
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001613 void setWallpaperAnimLayerAdjustmentLocked(int adj) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001614 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001615 "Setting wallpaper layer adj to " + adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001616 mWallpaperAnimLayerAdjustment = adj;
1617 int curTokenIndex = mWallpaperTokens.size();
1618 while (curTokenIndex > 0) {
1619 curTokenIndex--;
1620 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1621 int curWallpaperIndex = token.windows.size();
1622 while (curWallpaperIndex > 0) {
1623 curWallpaperIndex--;
1624 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1625 wallpaper.mAnimLayer = wallpaper.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08001626 if (DEBUG_LAYERS || DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper win "
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001627 + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07001628 }
1629 }
1630 }
1631
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001632 boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
1633 boolean sync) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001634 boolean changed = false;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001635 boolean rawChanged = false;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001636 float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001637 float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001638 int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
1639 int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
1640 changed = wallpaperWin.mXOffset != offset;
1641 if (changed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001642 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001643 + wallpaperWin + " x: " + offset);
1644 wallpaperWin.mXOffset = offset;
1645 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001646 if (wallpaperWin.mWallpaperX != wpx || wallpaperWin.mWallpaperXStep != wpxs) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001647 wallpaperWin.mWallpaperX = wpx;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001648 wallpaperWin.mWallpaperXStep = wpxs;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001649 rawChanged = true;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001650 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001651
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001652 float wpy = mLastWallpaperY >= 0 ? mLastWallpaperY : 0.5f;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001653 float wpys = mLastWallpaperYStep >= 0 ? mLastWallpaperYStep : -1.0f;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001654 int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
1655 offset = availh > 0 ? -(int)(availh*wpy+.5f) : 0;
1656 if (wallpaperWin.mYOffset != offset) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001657 if (DEBUG_WALLPAPER) Slog.v(TAG, "Update wallpaper "
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001658 + wallpaperWin + " y: " + offset);
1659 changed = true;
1660 wallpaperWin.mYOffset = offset;
1661 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001662 if (wallpaperWin.mWallpaperY != wpy || wallpaperWin.mWallpaperYStep != wpys) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001663 wallpaperWin.mWallpaperY = wpy;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001664 wallpaperWin.mWallpaperYStep = wpys;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001665 rawChanged = true;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001666 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001667
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07001668 if (rawChanged) {
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001669 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001670 if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001671 + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
1672 + " y=" + wallpaperWin.mWallpaperY);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001673 if (sync) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001674 mWaitingOnWallpaper = wallpaperWin;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001675 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001676 wallpaperWin.mClient.dispatchWallpaperOffsets(
Marco Nelissenbf6956b2009-11-09 15:21:13 -08001677 wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY,
1678 wallpaperWin.mWallpaperXStep, wallpaperWin.mWallpaperYStep, sync);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001679 if (sync) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001680 if (mWaitingOnWallpaper != null) {
1681 long start = SystemClock.uptimeMillis();
1682 if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
1683 < start) {
1684 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001685 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn75804932009-10-20 20:15:20 -07001686 "Waiting for offset complete...");
1687 mWindowMap.wait(WALLPAPER_TIMEOUT);
1688 } catch (InterruptedException e) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001689 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08001690 if (DEBUG_WALLPAPER) Slog.v(TAG, "Offset complete!");
Dianne Hackborn75804932009-10-20 20:15:20 -07001691 if ((start+WALLPAPER_TIMEOUT)
1692 < SystemClock.uptimeMillis()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001693 Slog.i(TAG, "Timeout waiting for wallpaper to offset: "
Dianne Hackborn75804932009-10-20 20:15:20 -07001694 + wallpaperWin);
1695 mLastWallpaperTimeoutTime = start;
1696 }
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001697 }
Dianne Hackborn75804932009-10-20 20:15:20 -07001698 mWaitingOnWallpaper = null;
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001699 }
1700 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07001701 } catch (RemoteException e) {
1702 }
1703 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001704
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001705 return changed;
1706 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001707
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001708 void wallpaperOffsetsComplete(IBinder window) {
Dianne Hackborn75804932009-10-20 20:15:20 -07001709 synchronized (mWindowMap) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001710 if (mWaitingOnWallpaper != null &&
1711 mWaitingOnWallpaper.mClient.asBinder() == window) {
1712 mWaitingOnWallpaper = null;
Dianne Hackborn75804932009-10-20 20:15:20 -07001713 mWindowMap.notifyAll();
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001714 }
1715 }
1716 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001717
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001718 boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001719 final int dw = mDisplay.getWidth();
1720 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001721
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001722 boolean changed = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001723
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001724 WindowState target = mWallpaperTarget;
1725 if (target != null) {
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001726 if (target.mWallpaperX >= 0) {
1727 mLastWallpaperX = target.mWallpaperX;
1728 } else if (changingTarget.mWallpaperX >= 0) {
1729 mLastWallpaperX = changingTarget.mWallpaperX;
1730 }
1731 if (target.mWallpaperY >= 0) {
1732 mLastWallpaperY = target.mWallpaperY;
1733 } else if (changingTarget.mWallpaperY >= 0) {
1734 mLastWallpaperY = changingTarget.mWallpaperY;
1735 }
1736 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001737
Dianne Hackborn73e92b42009-10-15 14:29:19 -07001738 int curTokenIndex = mWallpaperTokens.size();
1739 while (curTokenIndex > 0) {
1740 curTokenIndex--;
1741 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1742 int curWallpaperIndex = token.windows.size();
1743 while (curWallpaperIndex > 0) {
1744 curWallpaperIndex--;
1745 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1746 if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
1747 wallpaper.computeShownFrameLocked();
1748 changed = true;
1749 // We only want to be synchronous with one wallpaper.
1750 sync = false;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001751 }
1752 }
1753 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001754
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07001755 return changed;
1756 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001757
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001758 void updateWallpaperVisibilityLocked() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07001759 final boolean visible = isWallpaperVisible(mWallpaperTarget);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001760 final int dw = mDisplay.getWidth();
1761 final int dh = mDisplay.getHeight();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001762
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001763 int curTokenIndex = mWallpaperTokens.size();
1764 while (curTokenIndex > 0) {
1765 curTokenIndex--;
1766 WindowToken token = mWallpaperTokens.get(curTokenIndex);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07001767 if (token.hidden == visible) {
1768 token.hidden = !visible;
1769 // Need to do a layout to ensure the wallpaper now has the
1770 // correct size.
1771 mLayoutNeeded = true;
1772 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001773
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001774 int curWallpaperIndex = token.windows.size();
1775 while (curWallpaperIndex > 0) {
1776 curWallpaperIndex--;
1777 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1778 if (visible) {
Dianne Hackborn19382ac2009-09-11 21:13:37 -07001779 updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001780 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001781
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001782 if (wallpaper.mWallpaperVisible != visible) {
1783 wallpaper.mWallpaperVisible = visible;
1784 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001785 if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07001786 "Updating visibility of wallpaper " + wallpaper
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07001787 + ": " + visible);
1788 wallpaper.mClient.dispatchAppVisibility(visible);
1789 } catch (RemoteException e) {
1790 }
1791 }
1792 }
1793 }
1794 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001795
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001796 void sendPointerToWallpaperLocked(WindowState srcWin,
1797 MotionEvent pointer, long eventTime) {
1798 int curTokenIndex = mWallpaperTokens.size();
1799 while (curTokenIndex > 0) {
1800 curTokenIndex--;
1801 WindowToken token = mWallpaperTokens.get(curTokenIndex);
1802 int curWallpaperIndex = token.windows.size();
1803 while (curWallpaperIndex > 0) {
1804 curWallpaperIndex--;
1805 WindowState wallpaper = token.windows.get(curWallpaperIndex);
1806 if ((wallpaper.mAttrs.flags &
1807 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
1808 continue;
1809 }
1810 try {
1811 MotionEvent ev = MotionEvent.obtainNoHistory(pointer);
Dianne Hackborn6adba242009-11-10 11:10:09 -08001812 if (srcWin != null) {
1813 ev.offsetLocation(srcWin.mFrame.left-wallpaper.mFrame.left,
1814 srcWin.mFrame.top-wallpaper.mFrame.top);
1815 } else {
1816 ev.offsetLocation(-wallpaper.mFrame.left, -wallpaper.mFrame.top);
1817 }
1818 switch (pointer.getAction()) {
1819 case MotionEvent.ACTION_DOWN:
1820 mSendingPointersToWallpaper = true;
1821 break;
1822 case MotionEvent.ACTION_UP:
1823 mSendingPointersToWallpaper = false;
1824 break;
1825 }
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001826 wallpaper.mClient.dispatchPointer(ev, eventTime, false);
1827 } catch (RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001828 Slog.w(TAG, "Failure sending pointer to wallpaper", e);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07001829 }
1830 }
1831 }
1832 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001833
Dianne Hackborn90d2db32010-02-11 22:19:06 -08001834 void dispatchPointerElsewhereLocked(WindowState srcWin, WindowState relWin,
1835 MotionEvent pointer, long eventTime, boolean skipped) {
1836 if (relWin != null) {
1837 mPolicy.dispatchedPointerEventLw(pointer, relWin.mFrame.left, relWin.mFrame.top);
1838 } else {
1839 mPolicy.dispatchedPointerEventLw(pointer, 0, 0);
1840 }
1841
1842 // If we sent an initial down to the wallpaper, then continue
1843 // sending events until the final up.
1844 if (mSendingPointersToWallpaper) {
1845 if (skipped) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001846 Slog.i(TAG, "Sending skipped pointer to wallpaper!");
Dianne Hackborn90d2db32010-02-11 22:19:06 -08001847 }
1848 sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1849
1850 // If we are on top of the wallpaper, then the wallpaper also
1851 // gets to see this movement.
1852 } else if (srcWin != null
1853 && pointer.getAction() == MotionEvent.ACTION_DOWN
1854 && mWallpaperTarget == srcWin
1855 && srcWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
1856 sendPointerToWallpaperLocked(relWin, pointer, eventTime);
1857 }
1858 }
1859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001860 public int addWindow(Session session, IWindow client,
1861 WindowManager.LayoutParams attrs, int viewVisibility,
1862 Rect outContentInsets) {
1863 int res = mPolicy.checkAddPermission(attrs);
1864 if (res != WindowManagerImpl.ADD_OKAY) {
1865 return res;
1866 }
Romain Guy06882f82009-06-10 13:36:04 -07001867
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001868 boolean reportNewConfig = false;
1869 WindowState attachedWindow = null;
1870 WindowState win = null;
Romain Guy06882f82009-06-10 13:36:04 -07001871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 synchronized(mWindowMap) {
1873 // Instantiating a Display requires talking with the simulator,
1874 // so don't do it until we know the system is mostly up and
1875 // running.
1876 if (mDisplay == null) {
1877 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
1878 mDisplay = wm.getDefaultDisplay();
Christopher Tateb696aee2010-04-02 19:08:30 -07001879 mInitialDisplayWidth = mDisplay.getWidth();
1880 mInitialDisplayHeight = mDisplay.getHeight();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001881 mQueue.setDisplay(mDisplay);
1882 reportNewConfig = true;
1883 }
Romain Guy06882f82009-06-10 13:36:04 -07001884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001885 if (mWindowMap.containsKey(client.asBinder())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001886 Slog.w(TAG, "Window " + client + " is already added");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 return WindowManagerImpl.ADD_DUPLICATE_ADD;
1888 }
1889
1890 if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08001891 attachedWindow = windowForClientLocked(null, attrs.token, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 if (attachedWindow == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001893 Slog.w(TAG, "Attempted to add window with token that is not a window: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001894 + attrs.token + ". Aborting.");
1895 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1896 }
1897 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
1898 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001899 Slog.w(TAG, "Attempted to add window with token that is a sub-window: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001900 + attrs.token + ". Aborting.");
1901 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
1902 }
1903 }
1904
1905 boolean addToken = false;
1906 WindowToken token = mTokenMap.get(attrs.token);
1907 if (token == null) {
1908 if (attrs.type >= FIRST_APPLICATION_WINDOW
1909 && attrs.type <= LAST_APPLICATION_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001910 Slog.w(TAG, "Attempted to add application window with unknown token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911 + attrs.token + ". Aborting.");
1912 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1913 }
1914 if (attrs.type == TYPE_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001915 Slog.w(TAG, "Attempted to add input method window with unknown token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001916 + attrs.token + ". Aborting.");
1917 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1918 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001919 if (attrs.type == TYPE_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001920 Slog.w(TAG, "Attempted to add wallpaper window with unknown token "
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001921 + attrs.token + ". Aborting.");
1922 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1923 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001924 token = new WindowToken(attrs.token, -1, false);
1925 addToken = true;
1926 } else if (attrs.type >= FIRST_APPLICATION_WINDOW
1927 && attrs.type <= LAST_APPLICATION_WINDOW) {
1928 AppWindowToken atoken = token.appWindowToken;
1929 if (atoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001930 Slog.w(TAG, "Attempted to add window with non-application token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001931 + token + ". Aborting.");
1932 return WindowManagerImpl.ADD_NOT_APP_TOKEN;
1933 } else if (atoken.removed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001934 Slog.w(TAG, "Attempted to add window with exiting application token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001935 + token + ". Aborting.");
1936 return WindowManagerImpl.ADD_APP_EXITING;
1937 }
1938 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
1939 // No need for this guy!
Joe Onorato8a9b2202010-02-26 18:56:32 -08001940 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001941 TAG, "**** NO NEED TO START: " + attrs.getTitle());
1942 return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
1943 }
1944 } else if (attrs.type == TYPE_INPUT_METHOD) {
1945 if (token.windowType != TYPE_INPUT_METHOD) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001946 Slog.w(TAG, "Attempted to add input method window with bad token "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001947 + attrs.token + ". Aborting.");
1948 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1949 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001950 } else if (attrs.type == TYPE_WALLPAPER) {
1951 if (token.windowType != TYPE_WALLPAPER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08001952 Slog.w(TAG, "Attempted to add wallpaper window with bad token "
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07001953 + attrs.token + ". Aborting.");
1954 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1955 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 }
1957
1958 win = new WindowState(session, client, token,
1959 attachedWindow, attrs, viewVisibility);
1960 if (win.mDeathRecipient == null) {
1961 // Client has apparently died, so there is no reason to
1962 // continue.
Joe Onorato8a9b2202010-02-26 18:56:32 -08001963 Slog.w(TAG, "Adding window client " + client.asBinder()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001964 + " that is dead, aborting.");
1965 return WindowManagerImpl.ADD_APP_EXITING;
1966 }
1967
1968 mPolicy.adjustWindowParamsLw(win.mAttrs);
Romain Guy06882f82009-06-10 13:36:04 -07001969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 res = mPolicy.prepareAddWindowLw(win, attrs);
1971 if (res != WindowManagerImpl.ADD_OKAY) {
1972 return res;
1973 }
1974
1975 // From now on, no exceptions or errors allowed!
1976
1977 res = WindowManagerImpl.ADD_OKAY;
Romain Guy06882f82009-06-10 13:36:04 -07001978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001979 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07001980
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001981 if (addToken) {
1982 mTokenMap.put(attrs.token, token);
1983 mTokenList.add(token);
1984 }
1985 win.attach();
1986 mWindowMap.put(client.asBinder(), win);
1987
1988 if (attrs.type == TYPE_APPLICATION_STARTING &&
1989 token.appWindowToken != null) {
1990 token.appWindowToken.startingWindow = win;
1991 }
1992
1993 boolean imMayMove = true;
Romain Guy06882f82009-06-10 13:36:04 -07001994
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001995 if (attrs.type == TYPE_INPUT_METHOD) {
1996 mInputMethodWindow = win;
1997 addInputMethodWindowToListLocked(win);
1998 imMayMove = false;
1999 } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
2000 mInputMethodDialogs.add(win);
2001 addWindowToListInOrderLocked(win, true);
2002 adjustInputMethodDialogsLocked();
2003 imMayMove = false;
2004 } else {
2005 addWindowToListInOrderLocked(win, true);
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002006 if (attrs.type == TYPE_WALLPAPER) {
2007 mLastWallpaperTimeoutTime = 0;
2008 adjustWallpaperWindowsLocked();
2009 } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002010 adjustWallpaperWindowsLocked();
2011 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002012 }
Romain Guy06882f82009-06-10 13:36:04 -07002013
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002014 win.mEnterAnimationPending = true;
Romain Guy06882f82009-06-10 13:36:04 -07002015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002016 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
Romain Guy06882f82009-06-10 13:36:04 -07002017
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002018 if (mInTouchMode) {
2019 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
2020 }
2021 if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
2022 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
2023 }
Romain Guy06882f82009-06-10 13:36:04 -07002024
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002025 boolean focusChanged = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 if (win.canReceiveKeys()) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002027 if ((focusChanged=updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS))
2028 == true) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 imMayMove = false;
2030 }
2031 }
Romain Guy06882f82009-06-10 13:36:04 -07002032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002033 if (imMayMove) {
Romain Guy06882f82009-06-10 13:36:04 -07002034 moveInputMethodWindowsIfNeededLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 }
Romain Guy06882f82009-06-10 13:36:04 -07002036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 assignLayersLocked();
2038 // Don't do layout here, the window must call
2039 // relayout to be displayed, so we'll do it there.
Romain Guy06882f82009-06-10 13:36:04 -07002040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002041 //dump();
2042
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002043 if (focusChanged) {
2044 if (mCurrentFocus != null) {
2045 mKeyWaiter.handleNewWindowLocked(mCurrentFocus);
2046 }
2047 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002048 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002049 TAG, "New client " + client.asBinder()
2050 + ": window=" + win);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002051
2052 if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked()) {
2053 reportNewConfig = true;
2054 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 }
2056
2057 // sendNewConfiguration() checks caller permissions so we must call it with
2058 // privilege. updateOrientationFromAppTokens() clears and resets the caller
2059 // identity anyway, so it's safe to just clear & restore around this whole
2060 // block.
2061 final long origId = Binder.clearCallingIdentity();
2062 if (reportNewConfig) {
2063 sendNewConfiguration();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002064 }
2065 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07002066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002067 return res;
2068 }
Romain Guy06882f82009-06-10 13:36:04 -07002069
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002070 public void removeWindow(Session session, IWindow client) {
2071 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002072 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002073 if (win == null) {
2074 return;
2075 }
2076 removeWindowLocked(session, win);
2077 }
2078 }
Romain Guy06882f82009-06-10 13:36:04 -07002079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002080 public void removeWindowLocked(Session session, WindowState win) {
2081
Joe Onorato8a9b2202010-02-26 18:56:32 -08002082 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002083 TAG, "Remove " + win + " client="
2084 + Integer.toHexString(System.identityHashCode(
2085 win.mClient.asBinder()))
2086 + ", surface=" + win.mSurface);
2087
2088 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002089
Joe Onorato8a9b2202010-02-26 18:56:32 -08002090 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 TAG, "Remove " + win + ": mSurface=" + win.mSurface
2092 + " mExiting=" + win.mExiting
2093 + " isAnimating=" + win.isAnimating()
2094 + " app-animation="
2095 + (win.mAppToken != null ? win.mAppToken.animation : null)
2096 + " inPendingTransaction="
2097 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
2098 + " mDisplayFrozen=" + mDisplayFrozen);
2099 // Visibility of the removed window. Will be used later to update orientation later on.
2100 boolean wasVisible = false;
2101 // First, see if we need to run an animation. If we do, we have
2102 // to hold off on removing the window until the animation is done.
2103 // If the display is frozen, just remove immediately, since the
2104 // animation wouldn't be seen.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002105 if (win.mSurface != null && !mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002106 // If we are not currently running the exit animation, we
2107 // need to see about starting one.
2108 if (wasVisible=win.isWinVisibleLw()) {
Romain Guy06882f82009-06-10 13:36:04 -07002109
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002110 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2111 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2112 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2113 }
2114 // Try starting an animation.
2115 if (applyAnimationLocked(win, transit, false)) {
2116 win.mExiting = true;
2117 }
2118 }
2119 if (win.mExiting || win.isAnimating()) {
2120 // The exit animation is running... wait for it!
Joe Onorato8a9b2202010-02-26 18:56:32 -08002121 //Slog.i(TAG, "*** Running exit animation...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002122 win.mExiting = true;
2123 win.mRemoveOnExit = true;
2124 mLayoutNeeded = true;
2125 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
2126 performLayoutAndPlaceSurfacesLocked();
2127 if (win.mAppToken != null) {
2128 win.mAppToken.updateReportedVisibilityLocked();
2129 }
2130 //dump();
2131 Binder.restoreCallingIdentity(origId);
2132 return;
2133 }
2134 }
2135
2136 removeWindowInnerLocked(session, win);
2137 // Removing a visible window will effect the computed orientation
2138 // So just update orientation if needed.
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002139 if (wasVisible && computeForcedAppOrientationLocked()
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002140 != mForcedAppOrientation
2141 && updateOrientationFromAppTokensLocked()) {
2142 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002143 }
2144 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2145 Binder.restoreCallingIdentity(origId);
2146 }
Romain Guy06882f82009-06-10 13:36:04 -07002147
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002148 private void removeWindowInnerLocked(Session session, WindowState win) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07002149 mKeyWaiter.finishedKey(session, win.mClient, true,
2150 KeyWaiter.RETURN_NOTHING);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002151 mKeyWaiter.releasePendingPointerLocked(win.mSession);
2152 mKeyWaiter.releasePendingTrackballLocked(win.mSession);
Romain Guy06882f82009-06-10 13:36:04 -07002153
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002154 win.mRemoved = true;
Romain Guy06882f82009-06-10 13:36:04 -07002155
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002156 if (mInputMethodTarget == win) {
2157 moveInputMethodWindowsIfNeededLocked(false);
2158 }
Romain Guy06882f82009-06-10 13:36:04 -07002159
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002160 if (false) {
2161 RuntimeException e = new RuntimeException("here");
2162 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002163 Slog.w(TAG, "Removing window " + win, e);
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07002164 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002166 mPolicy.removeWindowLw(win);
2167 win.removeLocked();
2168
2169 mWindowMap.remove(win.mClient.asBinder());
2170 mWindows.remove(win);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002171 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002172
2173 if (mInputMethodWindow == win) {
2174 mInputMethodWindow = null;
2175 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
2176 mInputMethodDialogs.remove(win);
2177 }
Romain Guy06882f82009-06-10 13:36:04 -07002178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002179 final WindowToken token = win.mToken;
2180 final AppWindowToken atoken = win.mAppToken;
2181 token.windows.remove(win);
2182 if (atoken != null) {
2183 atoken.allAppWindows.remove(win);
2184 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002185 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002186 TAG, "**** Removing window " + win + ": count="
2187 + token.windows.size());
2188 if (token.windows.size() == 0) {
2189 if (!token.explicit) {
2190 mTokenMap.remove(token.token);
2191 mTokenList.remove(token);
2192 } else if (atoken != null) {
2193 atoken.firstWindowDrawn = false;
2194 }
2195 }
2196
2197 if (atoken != null) {
2198 if (atoken.startingWindow == win) {
2199 atoken.startingWindow = null;
2200 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
2201 // If this is the last window and we had requested a starting
2202 // transition window, well there is no point now.
2203 atoken.startingData = null;
2204 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
2205 // If this is the last window except for a starting transition
2206 // window, we need to get rid of the starting transition.
2207 if (DEBUG_STARTING_WINDOW) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002208 Slog.v(TAG, "Schedule remove starting " + token
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002209 + ": no more real windows");
2210 }
2211 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
2212 mH.sendMessage(m);
2213 }
2214 }
Romain Guy06882f82009-06-10 13:36:04 -07002215
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002216 if (win.mAttrs.type == TYPE_WALLPAPER) {
2217 mLastWallpaperTimeoutTime = 0;
2218 adjustWallpaperWindowsLocked();
2219 } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07002220 adjustWallpaperWindowsLocked();
2221 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002223 if (!mInLayout) {
2224 assignLayersLocked();
2225 mLayoutNeeded = true;
2226 performLayoutAndPlaceSurfacesLocked();
2227 if (win.mAppToken != null) {
2228 win.mAppToken.updateReportedVisibilityLocked();
2229 }
2230 }
2231 }
2232
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002233 private static void logSurface(WindowState w, String msg, RuntimeException where) {
2234 String str = " SURFACE " + Integer.toHexString(w.hashCode())
2235 + ": " + msg + " / " + w.mAttrs.getTitle();
2236 if (where != null) {
2237 Slog.i(TAG, str, where);
2238 } else {
2239 Slog.i(TAG, str);
2240 }
2241 }
2242
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002243 private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
2244 long origId = Binder.clearCallingIdentity();
2245 try {
2246 synchronized (mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002247 WindowState w = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002248 if ((w != null) && (w.mSurface != null)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002249 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002250 Surface.openTransaction();
2251 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002252 if (SHOW_TRANSACTIONS) logSurface(w,
2253 "transparentRegionHint=" + region, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002254 w.mSurface.setTransparentRegionHint(region);
2255 } finally {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002256 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002257 Surface.closeTransaction();
2258 }
2259 }
2260 }
2261 } finally {
2262 Binder.restoreCallingIdentity(origId);
2263 }
2264 }
2265
2266 void setInsetsWindow(Session session, IWindow client,
Romain Guy06882f82009-06-10 13:36:04 -07002267 int touchableInsets, Rect contentInsets,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002268 Rect visibleInsets) {
2269 long origId = Binder.clearCallingIdentity();
2270 try {
2271 synchronized (mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002272 WindowState w = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002273 if (w != null) {
2274 w.mGivenInsetsPending = false;
2275 w.mGivenContentInsets.set(contentInsets);
2276 w.mGivenVisibleInsets.set(visibleInsets);
2277 w.mTouchableInsets = touchableInsets;
2278 mLayoutNeeded = true;
2279 performLayoutAndPlaceSurfacesLocked();
2280 }
2281 }
2282 } finally {
2283 Binder.restoreCallingIdentity(origId);
2284 }
2285 }
Romain Guy06882f82009-06-10 13:36:04 -07002286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002287 public void getWindowDisplayFrame(Session session, IWindow client,
2288 Rect outDisplayFrame) {
2289 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002290 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002291 if (win == null) {
2292 outDisplayFrame.setEmpty();
2293 return;
2294 }
2295 outDisplayFrame.set(win.mDisplayFrame);
2296 }
2297 }
2298
Marco Nelissenbf6956b2009-11-09 15:21:13 -08002299 public void setWindowWallpaperPositionLocked(WindowState window, float x, float y,
2300 float xStep, float yStep) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002301 if (window.mWallpaperX != x || window.mWallpaperY != y) {
2302 window.mWallpaperX = x;
2303 window.mWallpaperY = y;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08002304 window.mWallpaperXStep = xStep;
2305 window.mWallpaperYStep = yStep;
Dianne Hackborn73e92b42009-10-15 14:29:19 -07002306 if (updateWallpaperOffsetLocked(window, true)) {
2307 performLayoutAndPlaceSurfacesLocked();
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07002308 }
2309 }
2310 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002311
Dianne Hackborn75804932009-10-20 20:15:20 -07002312 void wallpaperCommandComplete(IBinder window, Bundle result) {
2313 synchronized (mWindowMap) {
2314 if (mWaitingOnWallpaper != null &&
2315 mWaitingOnWallpaper.mClient.asBinder() == window) {
2316 mWaitingOnWallpaper = null;
2317 mWindowMap.notifyAll();
2318 }
2319 }
2320 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002321
Dianne Hackborn75804932009-10-20 20:15:20 -07002322 public Bundle sendWindowWallpaperCommandLocked(WindowState window,
2323 String action, int x, int y, int z, Bundle extras, boolean sync) {
2324 if (window == mWallpaperTarget || window == mLowerWallpaperTarget
2325 || window == mUpperWallpaperTarget) {
2326 boolean doWait = sync;
2327 int curTokenIndex = mWallpaperTokens.size();
2328 while (curTokenIndex > 0) {
2329 curTokenIndex--;
2330 WindowToken token = mWallpaperTokens.get(curTokenIndex);
2331 int curWallpaperIndex = token.windows.size();
2332 while (curWallpaperIndex > 0) {
2333 curWallpaperIndex--;
2334 WindowState wallpaper = token.windows.get(curWallpaperIndex);
2335 try {
2336 wallpaper.mClient.dispatchWallpaperCommand(action,
2337 x, y, z, extras, sync);
2338 // We only want to be synchronous with one wallpaper.
2339 sync = false;
2340 } catch (RemoteException e) {
2341 }
2342 }
2343 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002344
Dianne Hackborn75804932009-10-20 20:15:20 -07002345 if (doWait) {
2346 // XXX Need to wait for result.
2347 }
2348 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002349
Dianne Hackborn75804932009-10-20 20:15:20 -07002350 return null;
2351 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002353 public int relayoutWindow(Session session, IWindow client,
2354 WindowManager.LayoutParams attrs, int requestedWidth,
2355 int requestedHeight, int viewVisibility, boolean insetsPending,
2356 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07002357 Configuration outConfig, Surface outSurface) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002358 boolean displayed = false;
2359 boolean inTouchMode;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002360 boolean configChanged;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002361 long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07002362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002364 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002365 if (win == null) {
2366 return 0;
2367 }
2368 win.mRequestedWidth = requestedWidth;
2369 win.mRequestedHeight = requestedHeight;
2370
2371 if (attrs != null) {
2372 mPolicy.adjustWindowParamsLw(attrs);
2373 }
Romain Guy06882f82009-06-10 13:36:04 -07002374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002375 int attrChanges = 0;
2376 int flagChanges = 0;
2377 if (attrs != null) {
2378 flagChanges = win.mAttrs.flags ^= attrs.flags;
2379 attrChanges = win.mAttrs.copyFrom(attrs);
2380 }
2381
Joe Onorato8a9b2202010-02-26 18:56:32 -08002382 if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": " + win.mAttrs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002383
2384 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
2385 win.mAlpha = attrs.alpha;
2386 }
2387
2388 final boolean scaledWindow =
2389 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
2390
2391 if (scaledWindow) {
2392 // requested{Width|Height} Surface's physical size
2393 // attrs.{width|height} Size on screen
2394 win.mHScale = (attrs.width != requestedWidth) ?
2395 (attrs.width / (float)requestedWidth) : 1.0f;
2396 win.mVScale = (attrs.height != requestedHeight) ?
2397 (attrs.height / (float)requestedHeight) : 1.0f;
Dianne Hackborn9b52a212009-12-11 14:51:35 -08002398 } else {
2399 win.mHScale = win.mVScale = 1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002400 }
2401
2402 boolean imMayMove = (flagChanges&(
2403 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
2404 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07002405
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002406 boolean focusMayChange = win.mViewVisibility != viewVisibility
2407 || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
2408 || (!win.mRelayoutCalled);
Romain Guy06882f82009-06-10 13:36:04 -07002409
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002410 boolean wallpaperMayMove = win.mViewVisibility != viewVisibility
2411 && (win.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002412
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002413 win.mRelayoutCalled = true;
2414 final int oldVisibility = win.mViewVisibility;
2415 win.mViewVisibility = viewVisibility;
2416 if (viewVisibility == View.VISIBLE &&
2417 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
2418 displayed = !win.isVisibleLw();
2419 if (win.mExiting) {
2420 win.mExiting = false;
2421 win.mAnimation = null;
2422 }
2423 if (win.mDestroying) {
2424 win.mDestroying = false;
2425 mDestroySurface.remove(win);
2426 }
2427 if (oldVisibility == View.GONE) {
2428 win.mEnterAnimationPending = true;
2429 }
Dianne Hackborn694f79b2010-03-17 19:44:59 -07002430 if (displayed) {
2431 if (win.mSurface != null && !win.mDrawPending
2432 && !win.mCommitDrawPending && !mDisplayFrozen
2433 && mPolicy.isScreenOn()) {
2434 applyEnterAnimationLocked(win);
2435 }
2436 if ((win.mAttrs.flags
2437 & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
2438 if (DEBUG_VISIBILITY) Slog.v(TAG,
2439 "Relayout window turning screen on: " + win);
2440 win.mTurnOnScreen = true;
2441 }
2442 int diff = 0;
2443 if (win.mConfiguration != mCurConfiguration
2444 && (win.mConfiguration == null
2445 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0)) {
2446 win.mConfiguration = mCurConfiguration;
2447 if (DEBUG_CONFIGURATION) {
2448 Slog.i(TAG, "Window " + win + " visible with new config: "
2449 + win.mConfiguration + " / 0x"
2450 + Integer.toHexString(diff));
2451 }
2452 outConfig.setTo(mCurConfiguration);
2453 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07002454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002455 if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
2456 // To change the format, we need to re-build the surface.
2457 win.destroySurfaceLocked();
2458 displayed = true;
2459 }
2460 try {
2461 Surface surface = win.createSurfaceLocked();
2462 if (surface != null) {
2463 outSurface.copyFrom(surface);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002464 win.mReportDestroySurface = false;
2465 win.mSurfacePendingDestroy = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002466 if (SHOW_TRANSACTIONS) Slog.i(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002467 " OUT SURFACE " + outSurface + ": copied");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002468 } else {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002469 // For some reason there isn't a surface. Clear the
2470 // caller's object so they see the same state.
2471 outSurface.release();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002472 }
2473 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002474 Slog.w(TAG, "Exception thrown when creating surface for client "
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002475 + client + " (" + win.mAttrs.getTitle() + ")",
2476 e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002477 Binder.restoreCallingIdentity(origId);
2478 return 0;
2479 }
2480 if (displayed) {
2481 focusMayChange = true;
2482 }
2483 if (win.mAttrs.type == TYPE_INPUT_METHOD
2484 && mInputMethodWindow == null) {
2485 mInputMethodWindow = win;
2486 imMayMove = true;
2487 }
Dianne Hackborn558947c2009-12-18 16:02:50 -08002488 if (win.mAttrs.type == TYPE_BASE_APPLICATION
2489 && win.mAppToken != null
2490 && win.mAppToken.startingWindow != null) {
2491 // Special handling of starting window over the base
2492 // window of the app: propagate lock screen flags to it,
2493 // to provide the correct semantics while starting.
2494 final int mask =
2495 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
Mike Lockwoodef731622010-01-27 17:51:34 -05002496 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
2497 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
Dianne Hackborn558947c2009-12-18 16:02:50 -08002498 WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
2499 sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
2500 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002501 } else {
2502 win.mEnterAnimationPending = false;
2503 if (win.mSurface != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002504 if (DEBUG_VISIBILITY) Slog.i(TAG, "Relayout invis " + win
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002505 + ": mExiting=" + win.mExiting
2506 + " mSurfacePendingDestroy=" + win.mSurfacePendingDestroy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002507 // If we are not currently running the exit animation, we
2508 // need to see about starting one.
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002509 if (!win.mExiting || win.mSurfacePendingDestroy) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002510 // Try starting an animation; if there isn't one, we
2511 // can destroy the surface right away.
2512 int transit = WindowManagerPolicy.TRANSIT_EXIT;
2513 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
2514 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
2515 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002516 if (!win.mSurfacePendingDestroy && win.isWinVisibleLw() &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002517 applyAnimationLocked(win, transit, false)) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002518 focusMayChange = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002519 win.mExiting = true;
2520 mKeyWaiter.finishedKey(session, client, true,
2521 KeyWaiter.RETURN_NOTHING);
2522 } else if (win.isAnimating()) {
2523 // Currently in a hide animation... turn this into
2524 // an exit.
2525 win.mExiting = true;
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07002526 } else if (win == mWallpaperTarget) {
2527 // If the wallpaper is currently behind this
2528 // window, we need to change both of them inside
2529 // of a transaction to avoid artifacts.
2530 win.mExiting = true;
2531 win.mAnimating = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002532 } else {
2533 if (mInputMethodWindow == win) {
2534 mInputMethodWindow = null;
2535 }
2536 win.destroySurfaceLocked();
2537 }
2538 }
2539 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002540
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002541 if (win.mSurface == null || (win.getAttrs().flags
2542 & WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING) == 0
2543 || win.mSurfacePendingDestroy) {
2544 // We are being called from a local process, which
2545 // means outSurface holds its current surface. Ensure the
2546 // surface object is cleared, but we don't want it actually
2547 // destroyed at this point.
2548 win.mSurfacePendingDestroy = false;
2549 outSurface.release();
Joe Onorato8a9b2202010-02-26 18:56:32 -08002550 if (DEBUG_VISIBILITY) Slog.i(TAG, "Releasing surface in: " + win);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002551 } else if (win.mSurface != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002552 if (DEBUG_VISIBILITY) Slog.i(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002553 "Keeping surface, will report destroy: " + win);
2554 win.mReportDestroySurface = true;
2555 outSurface.copyFrom(win.mSurface);
2556 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002557 }
2558
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002559 if (focusMayChange) {
2560 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
2561 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002562 imMayMove = false;
2563 }
2564 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
2565 }
Romain Guy06882f82009-06-10 13:36:04 -07002566
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08002567 // updateFocusedWindowLocked() already assigned layers so we only need to
2568 // reassign them at this point if the IM window state gets shuffled
2569 boolean assignLayers = false;
Romain Guy06882f82009-06-10 13:36:04 -07002570
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002571 if (imMayMove) {
Dianne Hackborn8abd5f02009-11-20 18:09:03 -08002572 if (moveInputMethodWindowsIfNeededLocked(false) || displayed) {
2573 // Little hack here -- we -should- be able to rely on the
2574 // function to return true if the IME has moved and needs
2575 // its layer recomputed. However, if the IME was hidden
2576 // and isn't actually moved in the list, its layer may be
2577 // out of data so we make sure to recompute it.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002578 assignLayers = true;
2579 }
2580 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002581 if (wallpaperMayMove) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07002582 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002583 assignLayers = true;
2584 }
2585 }
Romain Guy06882f82009-06-10 13:36:04 -07002586
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002587 mLayoutNeeded = true;
2588 win.mGivenInsetsPending = insetsPending;
2589 if (assignLayers) {
2590 assignLayersLocked();
2591 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002592 configChanged = updateOrientationFromAppTokensLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002593 performLayoutAndPlaceSurfacesLocked();
Dianne Hackborn284ac932009-08-28 10:34:25 -07002594 if (displayed && win.mIsWallpaper) {
2595 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07002596 mDisplay.getHeight(), false);
Dianne Hackborn284ac932009-08-28 10:34:25 -07002597 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002598 if (win.mAppToken != null) {
2599 win.mAppToken.updateReportedVisibilityLocked();
2600 }
2601 outFrame.set(win.mFrame);
2602 outContentInsets.set(win.mContentInsets);
2603 outVisibleInsets.set(win.mVisibleInsets);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002604 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002605 TAG, "Relayout given client " + client.asBinder()
Romain Guy06882f82009-06-10 13:36:04 -07002606 + ", requestedWidth=" + requestedWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002607 + ", requestedHeight=" + requestedHeight
2608 + ", viewVisibility=" + viewVisibility
2609 + "\nRelayout returning frame=" + outFrame
2610 + ", surface=" + outSurface);
2611
Joe Onorato8a9b2202010-02-26 18:56:32 -08002612 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002613 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
2614
2615 inTouchMode = mInTouchMode;
2616 }
2617
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002618 if (configChanged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002619 sendNewConfiguration();
2620 }
Romain Guy06882f82009-06-10 13:36:04 -07002621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002622 Binder.restoreCallingIdentity(origId);
Romain Guy06882f82009-06-10 13:36:04 -07002623
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002624 return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
2625 | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
2626 }
2627
2628 public void finishDrawingWindow(Session session, IWindow client) {
2629 final long origId = Binder.clearCallingIdentity();
2630 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08002631 WindowState win = windowForClientLocked(session, client, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002632 if (win != null && win.finishDrawingLocked()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07002633 if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
2634 adjustWallpaperWindowsLocked();
2635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002636 mLayoutNeeded = true;
2637 performLayoutAndPlaceSurfacesLocked();
2638 }
2639 }
2640 Binder.restoreCallingIdentity(origId);
2641 }
2642
2643 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002644 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002645 + (lp != null ? lp.packageName : null)
2646 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
2647 if (lp != null && lp.windowAnimations != 0) {
2648 // If this is a system resource, don't try to load it from the
2649 // application resources. It is nice to avoid loading application
2650 // resources if we can.
2651 String packageName = lp.packageName != null ? lp.packageName : "android";
2652 int resId = lp.windowAnimations;
2653 if ((resId&0xFF000000) == 0x01000000) {
2654 packageName = "android";
2655 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002656 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002657 + packageName);
2658 return AttributeCache.instance().get(packageName, resId,
2659 com.android.internal.R.styleable.WindowAnimation);
2660 }
2661 return null;
2662 }
Romain Guy06882f82009-06-10 13:36:04 -07002663
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002664 private AttributeCache.Entry getCachedAnimations(String packageName, int resId) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002665 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: params package="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002666 + packageName + " resId=0x" + Integer.toHexString(resId));
2667 if (packageName != null) {
2668 if ((resId&0xFF000000) == 0x01000000) {
2669 packageName = "android";
2670 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002671 if (DEBUG_ANIM) Slog.v(TAG, "Loading animations: picked package="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002672 + packageName);
2673 return AttributeCache.instance().get(packageName, resId,
2674 com.android.internal.R.styleable.WindowAnimation);
2675 }
2676 return null;
2677 }
2678
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 private void applyEnterAnimationLocked(WindowState win) {
2680 int transit = WindowManagerPolicy.TRANSIT_SHOW;
2681 if (win.mEnterAnimationPending) {
2682 win.mEnterAnimationPending = false;
2683 transit = WindowManagerPolicy.TRANSIT_ENTER;
2684 }
2685
2686 applyAnimationLocked(win, transit, true);
2687 }
2688
2689 private boolean applyAnimationLocked(WindowState win,
2690 int transit, boolean isEntrance) {
2691 if (win.mLocalAnimating && win.mAnimationIsEntrance == isEntrance) {
2692 // If we are trying to apply an animation, but already running
2693 // an animation of the same type, then just leave that one alone.
2694 return true;
2695 }
Romain Guy06882f82009-06-10 13:36:04 -07002696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 // Only apply an animation if the display isn't frozen. If it is
2698 // frozen, there is no reason to animate and it can cause strange
2699 // artifacts when we unfreeze the display if some different animation
2700 // is running.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002701 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002702 int anim = mPolicy.selectAnimationLw(win, transit);
2703 int attr = -1;
2704 Animation a = null;
2705 if (anim != 0) {
2706 a = AnimationUtils.loadAnimation(mContext, anim);
2707 } else {
2708 switch (transit) {
2709 case WindowManagerPolicy.TRANSIT_ENTER:
2710 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
2711 break;
2712 case WindowManagerPolicy.TRANSIT_EXIT:
2713 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
2714 break;
2715 case WindowManagerPolicy.TRANSIT_SHOW:
2716 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
2717 break;
2718 case WindowManagerPolicy.TRANSIT_HIDE:
2719 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
2720 break;
2721 }
2722 if (attr >= 0) {
2723 a = loadAnimation(win.mAttrs, attr);
2724 }
2725 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002726 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: win=" + win
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
2728 + " mAnimation=" + win.mAnimation
2729 + " isEntrance=" + isEntrance);
2730 if (a != null) {
2731 if (DEBUG_ANIM) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002732 RuntimeException e = null;
2733 if (!HIDE_STACK_CRAWLS) {
2734 e = new RuntimeException();
2735 e.fillInStackTrace();
2736 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002737 Slog.v(TAG, "Loaded animation " + a + " for " + win, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002738 }
2739 win.setAnimation(a);
2740 win.mAnimationIsEntrance = isEntrance;
2741 }
2742 } else {
2743 win.clearAnimation();
2744 }
2745
2746 return win.mAnimation != null;
2747 }
2748
2749 private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
2750 int anim = 0;
2751 Context context = mContext;
2752 if (animAttr >= 0) {
2753 AttributeCache.Entry ent = getCachedAnimations(lp);
2754 if (ent != null) {
2755 context = ent.context;
2756 anim = ent.array.getResourceId(animAttr, 0);
2757 }
2758 }
2759 if (anim != 0) {
2760 return AnimationUtils.loadAnimation(context, anim);
2761 }
2762 return null;
2763 }
Romain Guy06882f82009-06-10 13:36:04 -07002764
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002765 private Animation loadAnimation(String packageName, int resId) {
2766 int anim = 0;
2767 Context context = mContext;
2768 if (resId >= 0) {
2769 AttributeCache.Entry ent = getCachedAnimations(packageName, resId);
2770 if (ent != null) {
2771 context = ent.context;
2772 anim = resId;
2773 }
2774 }
2775 if (anim != 0) {
2776 return AnimationUtils.loadAnimation(context, anim);
2777 }
2778 return null;
2779 }
2780
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002781 private boolean applyAnimationLocked(AppWindowToken wtoken,
2782 WindowManager.LayoutParams lp, int transit, boolean enter) {
2783 // Only apply an animation if the display isn't frozen. If it is
2784 // frozen, there is no reason to animate and it can cause strange
2785 // artifacts when we unfreeze the display if some different animation
2786 // is running.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08002787 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002788 Animation a;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07002789 if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002790 a = new FadeInOutAnimation(enter);
Joe Onorato8a9b2202010-02-26 18:56:32 -08002791 if (DEBUG_ANIM) Slog.v(TAG,
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002792 "applying FadeInOutAnimation for a window in compatibility mode");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07002793 } else if (mNextAppTransitionPackage != null) {
2794 a = loadAnimation(mNextAppTransitionPackage, enter ?
2795 mNextAppTransitionEnter : mNextAppTransitionExit);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002796 } else {
2797 int animAttr = 0;
2798 switch (transit) {
2799 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
2800 animAttr = enter
2801 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
2802 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
2803 break;
2804 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
2805 animAttr = enter
2806 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
2807 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
2808 break;
2809 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
2810 animAttr = enter
2811 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
2812 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
2813 break;
2814 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
2815 animAttr = enter
2816 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
2817 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
2818 break;
2819 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
2820 animAttr = enter
2821 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
2822 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
2823 break;
2824 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
2825 animAttr = enter
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -07002826 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002827 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
2828 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002829 case WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002830 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002831 ? com.android.internal.R.styleable.WindowAnimation_wallpaperOpenEnterAnimation
2832 : com.android.internal.R.styleable.WindowAnimation_wallpaperOpenExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002833 break;
Dianne Hackborn25994b42009-09-04 14:21:19 -07002834 case WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE:
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002835 animAttr = enter
Dianne Hackborn25994b42009-09-04 14:21:19 -07002836 ? com.android.internal.R.styleable.WindowAnimation_wallpaperCloseEnterAnimation
2837 : com.android.internal.R.styleable.WindowAnimation_wallpaperCloseExitAnimation;
2838 break;
2839 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN:
2840 animAttr = enter
2841 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenEnterAnimation
2842 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraOpenExitAnimation;
2843 break;
2844 case WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE:
2845 animAttr = enter
2846 ? com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseEnterAnimation
2847 : com.android.internal.R.styleable.WindowAnimation_wallpaperIntraCloseExitAnimation;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07002848 break;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002849 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07002850 a = animAttr != 0 ? loadAnimation(lp, animAttr) : null;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002851 if (DEBUG_ANIM) Slog.v(TAG, "applyAnimation: wtoken=" + wtoken
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07002852 + " anim=" + a
2853 + " animAttr=0x" + Integer.toHexString(animAttr)
2854 + " transit=" + transit);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856 if (a != null) {
2857 if (DEBUG_ANIM) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08002858 RuntimeException e = null;
2859 if (!HIDE_STACK_CRAWLS) {
2860 e = new RuntimeException();
2861 e.fillInStackTrace();
2862 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08002863 Slog.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864 }
2865 wtoken.setAnimation(a);
2866 }
2867 } else {
2868 wtoken.clearAnimation();
2869 }
2870
2871 return wtoken.animation != null;
2872 }
2873
2874 // -------------------------------------------------------------
2875 // Application Window Tokens
2876 // -------------------------------------------------------------
2877
2878 public void validateAppTokens(List tokens) {
2879 int v = tokens.size()-1;
2880 int m = mAppTokens.size()-1;
2881 while (v >= 0 && m >= 0) {
2882 AppWindowToken wtoken = mAppTokens.get(m);
2883 if (wtoken.removed) {
2884 m--;
2885 continue;
2886 }
2887 if (tokens.get(v) != wtoken.token) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002888 Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002889 + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
2890 }
2891 v--;
2892 m--;
2893 }
2894 while (v >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002895 Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002896 v--;
2897 }
2898 while (m >= 0) {
2899 AppWindowToken wtoken = mAppTokens.get(m);
2900 if (!wtoken.removed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002901 Slog.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002902 }
2903 m--;
2904 }
2905 }
2906
2907 boolean checkCallingPermission(String permission, String func) {
2908 // Quick check: if the calling permission is me, it's all okay.
2909 if (Binder.getCallingPid() == Process.myPid()) {
2910 return true;
2911 }
Romain Guy06882f82009-06-10 13:36:04 -07002912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002913 if (mContext.checkCallingPermission(permission)
2914 == PackageManager.PERMISSION_GRANTED) {
2915 return true;
2916 }
2917 String msg = "Permission Denial: " + func + " from pid="
2918 + Binder.getCallingPid()
2919 + ", uid=" + Binder.getCallingUid()
2920 + " requires " + permission;
Joe Onorato8a9b2202010-02-26 18:56:32 -08002921 Slog.w(TAG, msg);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002922 return false;
2923 }
Romain Guy06882f82009-06-10 13:36:04 -07002924
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002925 AppWindowToken findAppWindowToken(IBinder token) {
2926 WindowToken wtoken = mTokenMap.get(token);
2927 if (wtoken == null) {
2928 return null;
2929 }
2930 return wtoken.appWindowToken;
2931 }
Romain Guy06882f82009-06-10 13:36:04 -07002932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002933 public void addWindowToken(IBinder token, int type) {
2934 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2935 "addWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002936 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002937 }
Romain Guy06882f82009-06-10 13:36:04 -07002938
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002939 synchronized(mWindowMap) {
2940 WindowToken wtoken = mTokenMap.get(token);
2941 if (wtoken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08002942 Slog.w(TAG, "Attempted to add existing input method token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002943 return;
2944 }
2945 wtoken = new WindowToken(token, type, true);
2946 mTokenMap.put(token, wtoken);
2947 mTokenList.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002948 if (type == TYPE_WALLPAPER) {
2949 mWallpaperTokens.add(wtoken);
2950 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002951 }
2952 }
Romain Guy06882f82009-06-10 13:36:04 -07002953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002954 public void removeWindowToken(IBinder token) {
2955 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2956 "removeWindowToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07002957 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002958 }
2959
2960 final long origId = Binder.clearCallingIdentity();
2961 synchronized(mWindowMap) {
2962 WindowToken wtoken = mTokenMap.remove(token);
2963 mTokenList.remove(wtoken);
2964 if (wtoken != null) {
2965 boolean delayed = false;
2966 if (!wtoken.hidden) {
2967 wtoken.hidden = true;
Romain Guy06882f82009-06-10 13:36:04 -07002968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002969 final int N = wtoken.windows.size();
2970 boolean changed = false;
Romain Guy06882f82009-06-10 13:36:04 -07002971
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002972 for (int i=0; i<N; i++) {
2973 WindowState win = wtoken.windows.get(i);
2974
2975 if (win.isAnimating()) {
2976 delayed = true;
2977 }
Romain Guy06882f82009-06-10 13:36:04 -07002978
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002979 if (win.isVisibleNow()) {
2980 applyAnimationLocked(win,
2981 WindowManagerPolicy.TRANSIT_EXIT, false);
2982 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
2983 KeyWaiter.RETURN_NOTHING);
2984 changed = true;
2985 }
2986 }
2987
2988 if (changed) {
2989 mLayoutNeeded = true;
2990 performLayoutAndPlaceSurfacesLocked();
2991 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
2992 }
Romain Guy06882f82009-06-10 13:36:04 -07002993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002994 if (delayed) {
2995 mExitingTokens.add(wtoken);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07002996 } else if (wtoken.windowType == TYPE_WALLPAPER) {
2997 mWallpaperTokens.remove(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002998 }
2999 }
Romain Guy06882f82009-06-10 13:36:04 -07003000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003001 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003002 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003003 }
3004 }
3005 Binder.restoreCallingIdentity(origId);
3006 }
3007
3008 public void addAppToken(int addPos, IApplicationToken token,
3009 int groupId, int requestedOrientation, boolean fullscreen) {
3010 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3011 "addAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003012 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003013 }
Romain Guy06882f82009-06-10 13:36:04 -07003014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003015 synchronized(mWindowMap) {
3016 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3017 if (wtoken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003018 Slog.w(TAG, "Attempted to add existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003019 return;
3020 }
3021 wtoken = new AppWindowToken(token);
3022 wtoken.groupId = groupId;
3023 wtoken.appFullscreen = fullscreen;
3024 wtoken.requestedOrientation = requestedOrientation;
3025 mAppTokens.add(addPos, wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003026 if (localLOGV) Slog.v(TAG, "Adding new app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003027 mTokenMap.put(token.asBinder(), wtoken);
3028 mTokenList.add(wtoken);
Romain Guy06882f82009-06-10 13:36:04 -07003029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003030 // Application tokens start out hidden.
3031 wtoken.hidden = true;
3032 wtoken.hiddenRequested = true;
Romain Guy06882f82009-06-10 13:36:04 -07003033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003034 //dump();
3035 }
3036 }
Romain Guy06882f82009-06-10 13:36:04 -07003037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003038 public void setAppGroupId(IBinder token, int groupId) {
3039 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3040 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003041 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003042 }
3043
3044 synchronized(mWindowMap) {
3045 AppWindowToken wtoken = findAppWindowToken(token);
3046 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003047 Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003048 return;
3049 }
3050 wtoken.groupId = groupId;
3051 }
3052 }
Romain Guy06882f82009-06-10 13:36:04 -07003053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003054 public int getOrientationFromWindowsLocked() {
3055 int pos = mWindows.size() - 1;
3056 while (pos >= 0) {
3057 WindowState wtoken = (WindowState) mWindows.get(pos);
3058 pos--;
3059 if (wtoken.mAppToken != null) {
3060 // We hit an application window. so the orientation will be determined by the
3061 // app window. No point in continuing further.
3062 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3063 }
Christopher Tateb696aee2010-04-02 19:08:30 -07003064 if (!wtoken.isVisibleLw() || !wtoken.mPolicyVisibilityAfterAnim) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003065 continue;
3066 }
3067 int req = wtoken.mAttrs.screenOrientation;
3068 if((req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) ||
3069 (req == ActivityInfo.SCREEN_ORIENTATION_BEHIND)){
3070 continue;
3071 } else {
3072 return req;
3073 }
3074 }
3075 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3076 }
Romain Guy06882f82009-06-10 13:36:04 -07003077
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003078 public int getOrientationFromAppTokensLocked() {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003079 int pos = mAppTokens.size() - 1;
3080 int curGroup = 0;
3081 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3082 boolean findingBehind = false;
3083 boolean haveGroup = false;
3084 boolean lastFullscreen = false;
3085 while (pos >= 0) {
3086 AppWindowToken wtoken = mAppTokens.get(pos);
3087 pos--;
3088 // if we're about to tear down this window and not seek for
3089 // the behind activity, don't use it for orientation
3090 if (!findingBehind
3091 && (!wtoken.hidden && wtoken.hiddenRequested)) {
3092 continue;
3093 }
3094
3095 if (!haveGroup) {
3096 // We ignore any hidden applications on the top.
3097 if (wtoken.hiddenRequested || wtoken.willBeHidden) {
The Android Open Source Project10592532009-03-18 17:39:46 -07003098 continue;
3099 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003100 haveGroup = true;
3101 curGroup = wtoken.groupId;
3102 lastOrientation = wtoken.requestedOrientation;
3103 } else if (curGroup != wtoken.groupId) {
3104 // If we have hit a new application group, and the bottom
3105 // of the previous group didn't explicitly say to use
3106 // the orientation behind it, and the last app was
3107 // full screen, then we'll stick with the
3108 // user's orientation.
3109 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
3110 && lastFullscreen) {
3111 return lastOrientation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003112 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003113 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003114 int or = wtoken.requestedOrientation;
3115 // If this application is fullscreen, and didn't explicitly say
3116 // to use the orientation behind it, then just take whatever
3117 // orientation it has and ignores whatever is under it.
3118 lastFullscreen = wtoken.appFullscreen;
3119 if (lastFullscreen
3120 && or != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
3121 return or;
3122 }
3123 // If this application has requested an explicit orientation,
3124 // then use it.
3125 if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
3126 or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
3127 or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
3128 or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
3129 or == ActivityInfo.SCREEN_ORIENTATION_USER) {
3130 return or;
3131 }
3132 findingBehind |= (or == ActivityInfo.SCREEN_ORIENTATION_BEHIND);
3133 }
3134 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003135 }
Romain Guy06882f82009-06-10 13:36:04 -07003136
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003137 public Configuration updateOrientationFromAppTokens(
The Android Open Source Project10592532009-03-18 17:39:46 -07003138 Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003139 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3140 "updateOrientationFromAppTokens()")) {
3141 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3142 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003143
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003144 Configuration config = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 long ident = Binder.clearCallingIdentity();
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003146
3147 synchronized(mWindowMap) {
3148 if (updateOrientationFromAppTokensLocked()) {
3149 if (freezeThisOneIfNeeded != null) {
3150 AppWindowToken wtoken = findAppWindowToken(
3151 freezeThisOneIfNeeded);
3152 if (wtoken != null) {
3153 startAppFreezingScreenLocked(wtoken,
3154 ActivityInfo.CONFIG_ORIENTATION);
3155 }
3156 }
3157 config = computeNewConfigurationLocked();
3158
3159 } else if (currentConfig != null) {
3160 // No obvious action we need to take, but if our current
3161 // state mismatches the activity maanager's, update it
3162 mTempConfiguration.setToDefaults();
3163 if (computeNewConfigurationLocked(mTempConfiguration)) {
3164 if (currentConfig.diff(mTempConfiguration) != 0) {
3165 mWaitingForConfig = true;
3166 mLayoutNeeded = true;
3167 startFreezingDisplayLocked();
3168 config = new Configuration(mTempConfiguration);
3169 }
3170 }
3171 }
3172 }
3173
Dianne Hackborncfaef692009-06-15 14:24:44 -07003174 Binder.restoreCallingIdentity(ident);
3175 return config;
3176 }
3177
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003178 /*
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003179 * Determine the new desired orientation of the display, returning
3180 * a non-null new Configuration if it has changed from the current
3181 * orientation. IF TRUE IS RETURNED SOMEONE MUST CALL
3182 * setNewConfiguration() TO TELL THE WINDOW MANAGER IT CAN UNFREEZE THE
3183 * SCREEN. This will typically be done for you if you call
3184 * sendNewConfiguration().
3185 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003186 * The orientation is computed from non-application windows first. If none of
3187 * the non-application windows specify orientation, the orientation is computed from
Romain Guy06882f82009-06-10 13:36:04 -07003188 * application tokens.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003189 * @see android.view.IWindowManager#updateOrientationFromAppTokens(
3190 * android.os.IBinder)
3191 */
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003192 boolean updateOrientationFromAppTokensLocked() {
Christopher Tateb696aee2010-04-02 19:08:30 -07003193 if (mDisplayFrozen) {
3194 // If the display is frozen, some activities may be in the middle
3195 // of restarting, and thus have removed their old window. If the
3196 // window has the flag to hide the lock screen, then the lock screen
3197 // can re-appear and inflict its own orientation on us. Keep the
3198 // orientation stable until this all settles down.
3199 return false;
3200 }
3201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003202 boolean changed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003203 long ident = Binder.clearCallingIdentity();
3204 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003205 int req = computeForcedAppOrientationLocked();
Romain Guy06882f82009-06-10 13:36:04 -07003206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207 if (req != mForcedAppOrientation) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003208 mForcedAppOrientation = req;
3209 //send a message to Policy indicating orientation change to take
3210 //action like disabling/enabling sensors etc.,
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003211 mPolicy.setCurrentOrientationLw(req);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003212 if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
3213 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)) {
3214 changed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003215 }
3216 }
The Android Open Source Project10592532009-03-18 17:39:46 -07003217
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003218 return changed;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003219 } finally {
3220 Binder.restoreCallingIdentity(ident);
3221 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003222 }
Romain Guy06882f82009-06-10 13:36:04 -07003223
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07003224 int computeForcedAppOrientationLocked() {
3225 int req = getOrientationFromWindowsLocked();
3226 if (req == ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) {
3227 req = getOrientationFromAppTokensLocked();
3228 }
3229 return req;
3230 }
Romain Guy06882f82009-06-10 13:36:04 -07003231
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003232 public void setNewConfiguration(Configuration config) {
3233 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3234 "setNewConfiguration()")) {
3235 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
3236 }
3237
3238 synchronized(mWindowMap) {
3239 mCurConfiguration = new Configuration(config);
3240 mWaitingForConfig = false;
3241 performLayoutAndPlaceSurfacesLocked();
3242 }
3243 }
3244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003245 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
3246 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3247 "setAppOrientation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003248 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003249 }
Romain Guy06882f82009-06-10 13:36:04 -07003250
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003251 synchronized(mWindowMap) {
3252 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3253 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003254 Slog.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003255 return;
3256 }
Romain Guy06882f82009-06-10 13:36:04 -07003257
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003258 wtoken.requestedOrientation = requestedOrientation;
3259 }
3260 }
Romain Guy06882f82009-06-10 13:36:04 -07003261
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003262 public int getAppOrientation(IApplicationToken token) {
3263 synchronized(mWindowMap) {
3264 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
3265 if (wtoken == null) {
3266 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
3267 }
Romain Guy06882f82009-06-10 13:36:04 -07003268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003269 return wtoken.requestedOrientation;
3270 }
3271 }
Romain Guy06882f82009-06-10 13:36:04 -07003272
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003273 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
3274 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3275 "setFocusedApp()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003276 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003277 }
3278
3279 synchronized(mWindowMap) {
3280 boolean changed = false;
3281 if (token == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003282 if (DEBUG_FOCUS) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003283 changed = mFocusedApp != null;
3284 mFocusedApp = null;
3285 mKeyWaiter.tickle();
3286 } else {
3287 AppWindowToken newFocus = findAppWindowToken(token);
3288 if (newFocus == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003289 Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003290 return;
3291 }
3292 changed = mFocusedApp != newFocus;
3293 mFocusedApp = newFocus;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003294 if (DEBUG_FOCUS) Slog.v(TAG, "Set focused app to: " + mFocusedApp);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003295 mKeyWaiter.tickle();
3296 }
3297
3298 if (moveFocusNow && changed) {
3299 final long origId = Binder.clearCallingIdentity();
3300 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3301 Binder.restoreCallingIdentity(origId);
3302 }
3303 }
3304 }
3305
3306 public void prepareAppTransition(int transit) {
3307 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3308 "prepareAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003309 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003310 }
Romain Guy06882f82009-06-10 13:36:04 -07003311
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003312 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003313 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003314 TAG, "Prepare app transition: transit=" + transit
3315 + " mNextAppTransition=" + mNextAppTransition);
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003316 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003317 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
3318 || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003319 mNextAppTransition = transit;
Dianne Hackbornd7cd29d2009-07-01 11:22:45 -07003320 } else if (transit == WindowManagerPolicy.TRANSIT_TASK_OPEN
3321 && mNextAppTransition == WindowManagerPolicy.TRANSIT_TASK_CLOSE) {
3322 // Opening a new task always supersedes a close for the anim.
3323 mNextAppTransition = transit;
3324 } else if (transit == WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN
3325 && mNextAppTransition == WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE) {
3326 // Opening a new activity always supersedes a close for the anim.
3327 mNextAppTransition = transit;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003328 }
3329 mAppTransitionReady = false;
3330 mAppTransitionTimeout = false;
3331 mStartingIconInTransition = false;
3332 mSkipAppTransitionAnimation = false;
3333 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
3334 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT),
3335 5000);
3336 }
3337 }
3338 }
3339
3340 public int getPendingAppTransition() {
3341 return mNextAppTransition;
3342 }
Romain Guy06882f82009-06-10 13:36:04 -07003343
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003344 public void overridePendingAppTransition(String packageName,
3345 int enterAnim, int exitAnim) {
Dianne Hackborn8b571a82009-09-25 16:09:43 -07003346 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003347 mNextAppTransitionPackage = packageName;
3348 mNextAppTransitionEnter = enterAnim;
3349 mNextAppTransitionExit = exitAnim;
3350 }
3351 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003352
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003353 public void executeAppTransition() {
3354 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3355 "executeAppTransition()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003356 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003357 }
Romain Guy06882f82009-06-10 13:36:04 -07003358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003359 synchronized(mWindowMap) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003360 if (DEBUG_APP_TRANSITIONS) {
3361 RuntimeException e = new RuntimeException("here");
3362 e.fillInStackTrace();
Joe Onorato8a9b2202010-02-26 18:56:32 -08003363 Slog.w(TAG, "Execute app transition: mNextAppTransition="
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003364 + mNextAppTransition, e);
3365 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003366 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003367 mAppTransitionReady = true;
3368 final long origId = Binder.clearCallingIdentity();
3369 performLayoutAndPlaceSurfacesLocked();
3370 Binder.restoreCallingIdentity(origId);
3371 }
3372 }
3373 }
3374
3375 public void setAppStartingWindow(IBinder token, String pkg,
3376 int theme, CharSequence nonLocalizedLabel, int labelRes, int icon,
3377 IBinder transferFrom, boolean createIfNeeded) {
3378 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3379 "setAppStartingIcon()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003380 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003381 }
3382
3383 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003384 if (DEBUG_STARTING_WINDOW) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
3386 + " transferFrom=" + transferFrom);
Romain Guy06882f82009-06-10 13:36:04 -07003387
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003388 AppWindowToken wtoken = findAppWindowToken(token);
3389 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003390 Slog.w(TAG, "Attempted to set icon of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 return;
3392 }
3393
3394 // If the display is frozen, we won't do anything until the
3395 // actual window is displayed so there is no reason to put in
3396 // the starting window.
Dianne Hackbornde2606d2009-12-18 16:53:55 -08003397 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003398 return;
3399 }
Romain Guy06882f82009-06-10 13:36:04 -07003400
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 if (wtoken.startingData != null) {
3402 return;
3403 }
Romain Guy06882f82009-06-10 13:36:04 -07003404
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003405 if (transferFrom != null) {
3406 AppWindowToken ttoken = findAppWindowToken(transferFrom);
3407 if (ttoken != null) {
3408 WindowState startingWindow = ttoken.startingWindow;
3409 if (startingWindow != null) {
3410 if (mStartingIconInTransition) {
3411 // In this case, the starting icon has already
3412 // been displayed, so start letting windows get
3413 // shown immediately without any more transitions.
3414 mSkipAppTransitionAnimation = true;
3415 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003416 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003417 "Moving existing starting from " + ttoken
3418 + " to " + wtoken);
3419 final long origId = Binder.clearCallingIdentity();
Romain Guy06882f82009-06-10 13:36:04 -07003420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003421 // Transfer the starting window over to the new
3422 // token.
3423 wtoken.startingData = ttoken.startingData;
3424 wtoken.startingView = ttoken.startingView;
3425 wtoken.startingWindow = startingWindow;
3426 ttoken.startingData = null;
3427 ttoken.startingView = null;
3428 ttoken.startingWindow = null;
3429 ttoken.startingMoved = true;
3430 startingWindow.mToken = wtoken;
Dianne Hackbornef49c572009-03-24 19:27:32 -07003431 startingWindow.mRootToken = wtoken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003432 startingWindow.mAppToken = wtoken;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003433 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003434 "Removing starting window: " + startingWindow);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003435 mWindows.remove(startingWindow);
3436 ttoken.windows.remove(startingWindow);
3437 ttoken.allAppWindows.remove(startingWindow);
3438 addWindowToListInOrderLocked(startingWindow, true);
Romain Guy06882f82009-06-10 13:36:04 -07003439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003440 // Propagate other interesting state between the
3441 // tokens. If the old token is displayed, we should
3442 // immediately force the new one to be displayed. If
3443 // it is animating, we need to move that animation to
3444 // the new one.
3445 if (ttoken.allDrawn) {
3446 wtoken.allDrawn = true;
3447 }
3448 if (ttoken.firstWindowDrawn) {
3449 wtoken.firstWindowDrawn = true;
3450 }
3451 if (!ttoken.hidden) {
3452 wtoken.hidden = false;
3453 wtoken.hiddenRequested = false;
3454 wtoken.willBeHidden = false;
3455 }
3456 if (wtoken.clientHidden != ttoken.clientHidden) {
3457 wtoken.clientHidden = ttoken.clientHidden;
3458 wtoken.sendAppVisibilityToClients();
3459 }
3460 if (ttoken.animation != null) {
3461 wtoken.animation = ttoken.animation;
3462 wtoken.animating = ttoken.animating;
3463 wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
3464 ttoken.animation = null;
3465 ttoken.animLayerAdjustment = 0;
3466 wtoken.updateLayers();
3467 ttoken.updateLayers();
3468 }
Romain Guy06882f82009-06-10 13:36:04 -07003469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003470 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003471 mLayoutNeeded = true;
3472 performLayoutAndPlaceSurfacesLocked();
3473 Binder.restoreCallingIdentity(origId);
3474 return;
3475 } else if (ttoken.startingData != null) {
3476 // The previous app was getting ready to show a
3477 // starting window, but hasn't yet done so. Steal it!
Joe Onorato8a9b2202010-02-26 18:56:32 -08003478 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003479 "Moving pending starting from " + ttoken
3480 + " to " + wtoken);
3481 wtoken.startingData = ttoken.startingData;
3482 ttoken.startingData = null;
3483 ttoken.startingMoved = true;
3484 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3485 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3486 // want to process the message ASAP, before any other queued
3487 // messages.
3488 mH.sendMessageAtFrontOfQueue(m);
3489 return;
3490 }
3491 }
3492 }
3493
3494 // There is no existing starting window, and the caller doesn't
3495 // want us to create one, so that's it!
3496 if (!createIfNeeded) {
3497 return;
3498 }
Romain Guy06882f82009-06-10 13:36:04 -07003499
Dianne Hackborn284ac932009-08-28 10:34:25 -07003500 // If this is a translucent or wallpaper window, then don't
3501 // show a starting window -- the current effect (a full-screen
3502 // opaque starting window that fades away to the real contents
3503 // when it is ready) does not work for this.
3504 if (theme != 0) {
3505 AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
3506 com.android.internal.R.styleable.Window);
3507 if (ent.array.getBoolean(
3508 com.android.internal.R.styleable.Window_windowIsTranslucent, false)) {
3509 return;
3510 }
3511 if (ent.array.getBoolean(
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07003512 com.android.internal.R.styleable.Window_windowIsFloating, false)) {
3513 return;
3514 }
3515 if (ent.array.getBoolean(
Dianne Hackborn284ac932009-08-28 10:34:25 -07003516 com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
3517 return;
3518 }
3519 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003520
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003521 mStartingIconInTransition = true;
3522 wtoken.startingData = new StartingData(
3523 pkg, theme, nonLocalizedLabel,
3524 labelRes, icon);
3525 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
3526 // Note: we really want to do sendMessageAtFrontOfQueue() because we
3527 // want to process the message ASAP, before any other queued
3528 // messages.
3529 mH.sendMessageAtFrontOfQueue(m);
3530 }
3531 }
3532
3533 public void setAppWillBeHidden(IBinder token) {
3534 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3535 "setAppWillBeHidden()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003536 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003537 }
3538
3539 AppWindowToken wtoken;
3540
3541 synchronized(mWindowMap) {
3542 wtoken = findAppWindowToken(token);
3543 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003544 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 -08003545 return;
3546 }
3547 wtoken.willBeHidden = true;
3548 }
3549 }
Romain Guy06882f82009-06-10 13:36:04 -07003550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
3552 boolean visible, int transit, boolean performLayout) {
3553 boolean delayed = false;
3554
3555 if (wtoken.clientHidden == visible) {
3556 wtoken.clientHidden = !visible;
3557 wtoken.sendAppVisibilityToClients();
3558 }
Romain Guy06882f82009-06-10 13:36:04 -07003559
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003560 wtoken.willBeHidden = false;
3561 if (wtoken.hidden == visible) {
3562 final int N = wtoken.allAppWindows.size();
3563 boolean changed = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08003564 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003565 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
3566 + " performLayout=" + performLayout);
Romain Guy06882f82009-06-10 13:36:04 -07003567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003568 boolean runningAppAnimation = false;
Romain Guy06882f82009-06-10 13:36:04 -07003569
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003570 if (transit != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003571 if (wtoken.animation == sDummyAnimation) {
3572 wtoken.animation = null;
3573 }
3574 applyAnimationLocked(wtoken, lp, transit, visible);
3575 changed = true;
3576 if (wtoken.animation != null) {
3577 delayed = runningAppAnimation = true;
3578 }
3579 }
Romain Guy06882f82009-06-10 13:36:04 -07003580
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003581 for (int i=0; i<N; i++) {
3582 WindowState win = wtoken.allAppWindows.get(i);
3583 if (win == wtoken.startingWindow) {
3584 continue;
3585 }
3586
3587 if (win.isAnimating()) {
3588 delayed = true;
3589 }
Romain Guy06882f82009-06-10 13:36:04 -07003590
Joe Onorato8a9b2202010-02-26 18:56:32 -08003591 //Slog.i(TAG, "Window " + win + ": vis=" + win.isVisible());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003592 //win.dump(" ");
3593 if (visible) {
3594 if (!win.isVisibleNow()) {
3595 if (!runningAppAnimation) {
3596 applyAnimationLocked(win,
3597 WindowManagerPolicy.TRANSIT_ENTER, true);
3598 }
3599 changed = true;
3600 }
3601 } else if (win.isVisibleNow()) {
3602 if (!runningAppAnimation) {
3603 applyAnimationLocked(win,
3604 WindowManagerPolicy.TRANSIT_EXIT, false);
3605 }
3606 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
3607 KeyWaiter.RETURN_NOTHING);
3608 changed = true;
3609 }
3610 }
3611
3612 wtoken.hidden = wtoken.hiddenRequested = !visible;
3613 if (!visible) {
3614 unsetAppFreezingScreenLocked(wtoken, true, true);
3615 } else {
3616 // If we are being set visible, and the starting window is
3617 // not yet displayed, then make sure it doesn't get displayed.
3618 WindowState swin = wtoken.startingWindow;
3619 if (swin != null && (swin.mDrawPending
3620 || swin.mCommitDrawPending)) {
3621 swin.mPolicyVisibility = false;
3622 swin.mPolicyVisibilityAfterAnim = false;
3623 }
3624 }
Romain Guy06882f82009-06-10 13:36:04 -07003625
Joe Onorato8a9b2202010-02-26 18:56:32 -08003626 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "setTokenVisibilityLocked: " + wtoken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003627 + ": hidden=" + wtoken.hidden + " hiddenRequested="
3628 + wtoken.hiddenRequested);
Romain Guy06882f82009-06-10 13:36:04 -07003629
Dianne Hackborn9b52a212009-12-11 14:51:35 -08003630 if (changed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003631 mLayoutNeeded = true;
Dianne Hackborn9b52a212009-12-11 14:51:35 -08003632 if (performLayout) {
3633 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
3634 performLayoutAndPlaceSurfacesLocked();
3635 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003636 }
3637 }
3638
3639 if (wtoken.animation != null) {
3640 delayed = true;
3641 }
Romain Guy06882f82009-06-10 13:36:04 -07003642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003643 return delayed;
3644 }
3645
3646 public void setAppVisibility(IBinder token, boolean visible) {
3647 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3648 "setAppVisibility()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003649 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003650 }
3651
3652 AppWindowToken wtoken;
3653
3654 synchronized(mWindowMap) {
3655 wtoken = findAppWindowToken(token);
3656 if (wtoken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003657 Slog.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003658 return;
3659 }
3660
3661 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08003662 RuntimeException e = null;
3663 if (!HIDE_STACK_CRAWLS) {
3664 e = new RuntimeException();
3665 e.fillInStackTrace();
3666 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003667 Slog.v(TAG, "setAppVisibility(" + token + ", " + visible
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003668 + "): mNextAppTransition=" + mNextAppTransition
3669 + " hidden=" + wtoken.hidden
3670 + " hiddenRequested=" + wtoken.hiddenRequested, e);
3671 }
Romain Guy06882f82009-06-10 13:36:04 -07003672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 // If we are preparing an app transition, then delay changing
3674 // the visibility of this token until we execute that transition.
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003675 if (!mDisplayFrozen && mPolicy.isScreenOn()
3676 && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003677 // Already in requested state, don't do anything more.
3678 if (wtoken.hiddenRequested != visible) {
3679 return;
3680 }
3681 wtoken.hiddenRequested = !visible;
Romain Guy06882f82009-06-10 13:36:04 -07003682
Joe Onorato8a9b2202010-02-26 18:56:32 -08003683 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003684 TAG, "Setting dummy animation on: " + wtoken);
3685 wtoken.setDummyAnimation();
3686 mOpeningApps.remove(wtoken);
3687 mClosingApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003688 wtoken.waitingToShow = wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003689 wtoken.inPendingTransaction = true;
3690 if (visible) {
3691 mOpeningApps.add(wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003692 wtoken.startingDisplayed = false;
3693 wtoken.startingMoved = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003694
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003695 // If the token is currently hidden (should be the
3696 // common case), then we need to set up to wait for
3697 // its windows to be ready.
3698 if (wtoken.hidden) {
3699 wtoken.allDrawn = false;
3700 wtoken.waitingToShow = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003701
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003702 if (wtoken.clientHidden) {
3703 // In the case where we are making an app visible
3704 // but holding off for a transition, we still need
3705 // to tell the client to make its windows visible so
3706 // they get drawn. Otherwise, we will wait on
3707 // performing the transition until all windows have
3708 // been drawn, they never will be, and we are sad.
3709 wtoken.clientHidden = false;
3710 wtoken.sendAppVisibilityToClients();
3711 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003712 }
3713 } else {
3714 mClosingApps.add(wtoken);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08003715
Dianne Hackborn195f6a02009-11-24 11:26:00 -08003716 // If the token is currently visible (should be the
3717 // common case), then set up to wait for it to be hidden.
3718 if (!wtoken.hidden) {
3719 wtoken.waitingToHide = true;
3720 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003721 }
3722 return;
3723 }
Romain Guy06882f82009-06-10 13:36:04 -07003724
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003725 final long origId = Binder.clearCallingIdentity();
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003726 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003727 wtoken.updateReportedVisibilityLocked();
3728 Binder.restoreCallingIdentity(origId);
3729 }
3730 }
3731
3732 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
3733 boolean unfreezeSurfaceNow, boolean force) {
3734 if (wtoken.freezingScreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003735 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + wtoken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003736 + " force=" + force);
3737 final int N = wtoken.allAppWindows.size();
3738 boolean unfrozeWindows = false;
3739 for (int i=0; i<N; i++) {
3740 WindowState w = wtoken.allAppWindows.get(i);
3741 if (w.mAppFreezing) {
3742 w.mAppFreezing = false;
3743 if (w.mSurface != null && !w.mOrientationChanging) {
3744 w.mOrientationChanging = true;
3745 }
3746 unfrozeWindows = true;
3747 }
3748 }
3749 if (force || unfrozeWindows) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003750 if (DEBUG_ORIENTATION) Slog.v(TAG, "No longer freezing: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003751 wtoken.freezingScreen = false;
3752 mAppsFreezingScreen--;
3753 }
3754 if (unfreezeSurfaceNow) {
3755 if (unfrozeWindows) {
3756 mLayoutNeeded = true;
3757 performLayoutAndPlaceSurfacesLocked();
3758 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08003759 stopFreezingDisplayLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003760 }
3761 }
3762 }
Romain Guy06882f82009-06-10 13:36:04 -07003763
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003764 public void startAppFreezingScreenLocked(AppWindowToken wtoken,
3765 int configChanges) {
3766 if (DEBUG_ORIENTATION) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08003767 RuntimeException e = null;
3768 if (!HIDE_STACK_CRAWLS) {
3769 e = new RuntimeException();
3770 e.fillInStackTrace();
3771 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003772 Slog.i(TAG, "Set freezing of " + wtoken.appToken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003773 + ": hidden=" + wtoken.hidden + " freezing="
3774 + wtoken.freezingScreen, e);
3775 }
3776 if (!wtoken.hiddenRequested) {
3777 if (!wtoken.freezingScreen) {
3778 wtoken.freezingScreen = true;
3779 mAppsFreezingScreen++;
3780 if (mAppsFreezingScreen == 1) {
3781 startFreezingDisplayLocked();
3782 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
3783 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
3784 5000);
3785 }
3786 }
3787 final int N = wtoken.allAppWindows.size();
3788 for (int i=0; i<N; i++) {
3789 WindowState w = wtoken.allAppWindows.get(i);
3790 w.mAppFreezing = true;
3791 }
3792 }
3793 }
Romain Guy06882f82009-06-10 13:36:04 -07003794
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003795 public void startAppFreezingScreen(IBinder token, int configChanges) {
3796 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3797 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003798 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003799 }
3800
3801 synchronized(mWindowMap) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -08003802 if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOn()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003803 if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003804 return;
3805 }
Romain Guy06882f82009-06-10 13:36:04 -07003806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003807 AppWindowToken wtoken = findAppWindowToken(token);
3808 if (wtoken == null || wtoken.appToken == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003809 Slog.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003810 return;
3811 }
3812 final long origId = Binder.clearCallingIdentity();
3813 startAppFreezingScreenLocked(wtoken, configChanges);
3814 Binder.restoreCallingIdentity(origId);
3815 }
3816 }
Romain Guy06882f82009-06-10 13:36:04 -07003817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003818 public void stopAppFreezingScreen(IBinder token, boolean force) {
3819 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3820 "setAppFreezingScreen()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003821 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003822 }
3823
3824 synchronized(mWindowMap) {
3825 AppWindowToken wtoken = findAppWindowToken(token);
3826 if (wtoken == null || wtoken.appToken == null) {
3827 return;
3828 }
3829 final long origId = Binder.clearCallingIdentity();
Joe Onorato8a9b2202010-02-26 18:56:32 -08003830 if (DEBUG_ORIENTATION) Slog.v(TAG, "Clear freezing of " + token
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003831 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
3832 unsetAppFreezingScreenLocked(wtoken, true, force);
3833 Binder.restoreCallingIdentity(origId);
3834 }
3835 }
Romain Guy06882f82009-06-10 13:36:04 -07003836
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003837 public void removeAppToken(IBinder token) {
3838 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3839 "removeAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07003840 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003841 }
3842
3843 AppWindowToken wtoken = null;
3844 AppWindowToken startingToken = null;
3845 boolean delayed = false;
3846
3847 final long origId = Binder.clearCallingIdentity();
3848 synchronized(mWindowMap) {
3849 WindowToken basewtoken = mTokenMap.remove(token);
3850 mTokenList.remove(basewtoken);
3851 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003852 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003853 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003854 wtoken.inPendingTransaction = false;
3855 mOpeningApps.remove(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003856 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003857 if (mClosingApps.contains(wtoken)) {
3858 delayed = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07003859 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003860 mClosingApps.add(wtoken);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003861 wtoken.waitingToHide = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003862 delayed = true;
3863 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08003864 if (DEBUG_APP_TRANSITIONS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 TAG, "Removing app " + wtoken + " delayed=" + delayed
3866 + " animation=" + wtoken.animation
3867 + " animating=" + wtoken.animating);
3868 if (delayed) {
3869 // set the token aside because it has an active animation to be finished
3870 mExitingAppTokens.add(wtoken);
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07003871 } else {
3872 // Make sure there is no animation running on this token,
3873 // so any windows associated with it will be removed as
3874 // soon as their animations are complete
3875 wtoken.animation = null;
3876 wtoken.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 }
3878 mAppTokens.remove(wtoken);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07003879 if (mLastEnterAnimToken == wtoken) {
3880 mLastEnterAnimToken = null;
3881 mLastEnterAnimParams = null;
3882 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003883 wtoken.removed = true;
3884 if (wtoken.startingData != null) {
3885 startingToken = wtoken;
3886 }
3887 unsetAppFreezingScreenLocked(wtoken, true, true);
3888 if (mFocusedApp == wtoken) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003889 if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003890 mFocusedApp = null;
3891 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
3892 mKeyWaiter.tickle();
3893 }
3894 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003895 Slog.w(TAG, "Attempted to remove non-existing app token: " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003896 }
Romain Guy06882f82009-06-10 13:36:04 -07003897
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003898 if (!delayed && wtoken != null) {
3899 wtoken.updateReportedVisibilityLocked();
3900 }
3901 }
3902 Binder.restoreCallingIdentity(origId);
3903
3904 if (startingToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003905 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Schedule remove starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003906 + startingToken + ": app token removed");
3907 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
3908 mH.sendMessage(m);
3909 }
3910 }
3911
3912 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
3913 final int NW = token.windows.size();
3914 for (int i=0; i<NW; i++) {
3915 WindowState win = token.windows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003916 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Tmp removing app window " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 mWindows.remove(win);
3918 int j = win.mChildWindows.size();
3919 while (j > 0) {
3920 j--;
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003921 WindowState cwin = (WindowState)win.mChildWindows.get(j);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003922 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07003923 "Tmp removing child window " + cwin);
3924 mWindows.remove(cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003925 }
3926 }
3927 return NW > 0;
3928 }
3929
3930 void dumpAppTokensLocked() {
3931 for (int i=mAppTokens.size()-1; i>=0; i--) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003932 Slog.v(TAG, " #" + i + ": " + mAppTokens.get(i).token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003933 }
3934 }
Romain Guy06882f82009-06-10 13:36:04 -07003935
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003936 void dumpWindowsLocked() {
3937 for (int i=mWindows.size()-1; i>=0; i--) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003938 Slog.v(TAG, " #" + i + ": " + mWindows.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003939 }
3940 }
Romain Guy06882f82009-06-10 13:36:04 -07003941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003942 private int findWindowOffsetLocked(int tokenPos) {
3943 final int NW = mWindows.size();
3944
3945 if (tokenPos >= mAppTokens.size()) {
3946 int i = NW;
3947 while (i > 0) {
3948 i--;
3949 WindowState win = (WindowState)mWindows.get(i);
3950 if (win.getAppToken() != null) {
3951 return i+1;
3952 }
3953 }
3954 }
3955
3956 while (tokenPos > 0) {
3957 // Find the first app token below the new position that has
3958 // a window displayed.
3959 final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
Joe Onorato8a9b2202010-02-26 18:56:32 -08003960 if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003961 + tokenPos + " -- " + wtoken.token);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003962 if (wtoken.sendingToBottom) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003963 if (DEBUG_REORDER) Slog.v(TAG,
Dianne Hackborna8f60182009-09-01 19:01:50 -07003964 "Skipping token -- currently sending to bottom");
3965 tokenPos--;
3966 continue;
3967 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003968 int i = wtoken.windows.size();
3969 while (i > 0) {
3970 i--;
3971 WindowState win = wtoken.windows.get(i);
3972 int j = win.mChildWindows.size();
3973 while (j > 0) {
3974 j--;
3975 WindowState cwin = (WindowState)win.mChildWindows.get(j);
Dianne Hackborna8f60182009-09-01 19:01:50 -07003976 if (cwin.mSubLayer >= 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003977 for (int pos=NW-1; pos>=0; pos--) {
3978 if (mWindows.get(pos) == cwin) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003979 if (DEBUG_REORDER) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003980 "Found child win @" + (pos+1));
3981 return pos+1;
3982 }
3983 }
3984 }
3985 }
3986 for (int pos=NW-1; pos>=0; pos--) {
3987 if (mWindows.get(pos) == win) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08003988 if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003989 return pos+1;
3990 }
3991 }
3992 }
3993 tokenPos--;
3994 }
3995
3996 return 0;
3997 }
3998
3999 private final int reAddWindowLocked(int index, WindowState win) {
4000 final int NCW = win.mChildWindows.size();
4001 boolean added = false;
4002 for (int j=0; j<NCW; j++) {
4003 WindowState cwin = (WindowState)win.mChildWindows.get(j);
4004 if (!added && cwin.mSubLayer >= 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004005 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004006 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004007 mWindows.add(index, win);
4008 index++;
4009 added = true;
4010 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004011 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004012 + index + ": " + cwin);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004013 mWindows.add(index, cwin);
4014 index++;
4015 }
4016 if (!added) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004017 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07004018 + index + ": " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 mWindows.add(index, win);
4020 index++;
4021 }
4022 return index;
4023 }
Romain Guy06882f82009-06-10 13:36:04 -07004024
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004025 private final int reAddAppWindowsLocked(int index, WindowToken token) {
4026 final int NW = token.windows.size();
4027 for (int i=0; i<NW; i++) {
4028 index = reAddWindowLocked(index, token.windows.get(i));
4029 }
4030 return index;
4031 }
4032
4033 public void moveAppToken(int index, IBinder token) {
4034 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4035 "moveAppToken()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004036 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004037 }
4038
4039 synchronized(mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004040 if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004041 if (DEBUG_REORDER) dumpAppTokensLocked();
4042 final AppWindowToken wtoken = findAppWindowToken(token);
4043 if (wtoken == null || !mAppTokens.remove(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004044 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004045 + token + " (" + wtoken + ")");
4046 return;
4047 }
4048 mAppTokens.add(index, wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004049 if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004050 if (DEBUG_REORDER) dumpAppTokensLocked();
Romain Guy06882f82009-06-10 13:36:04 -07004051
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004052 final long origId = Binder.clearCallingIdentity();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004053 if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004054 if (DEBUG_REORDER) dumpWindowsLocked();
4055 if (tmpRemoveAppWindowsLocked(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004056 if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004057 if (DEBUG_REORDER) dumpWindowsLocked();
4058 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004059 if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004060 if (DEBUG_REORDER) dumpWindowsLocked();
4061 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004062 mLayoutNeeded = true;
4063 performLayoutAndPlaceSurfacesLocked();
4064 }
4065 Binder.restoreCallingIdentity(origId);
4066 }
4067 }
4068
4069 private void removeAppTokensLocked(List<IBinder> tokens) {
4070 // XXX This should be done more efficiently!
4071 // (take advantage of the fact that both lists should be
4072 // ordered in the same way.)
4073 int N = tokens.size();
4074 for (int i=0; i<N; i++) {
4075 IBinder token = tokens.get(i);
4076 final AppWindowToken wtoken = findAppWindowToken(token);
4077 if (!mAppTokens.remove(wtoken)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004078 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004079 + token + " (" + wtoken + ")");
4080 i--;
4081 N--;
4082 }
4083 }
4084 }
4085
Dianne Hackborna8f60182009-09-01 19:01:50 -07004086 private void moveAppWindowsLocked(AppWindowToken wtoken, int tokenPos,
4087 boolean updateFocusAndLayout) {
4088 // First remove all of the windows from the list.
4089 tmpRemoveAppWindowsLocked(wtoken);
4090
4091 // Where to start adding?
4092 int pos = findWindowOffsetLocked(tokenPos);
4093
4094 // And now add them back at the correct place.
4095 pos = reAddAppWindowsLocked(pos, wtoken);
4096
4097 if (updateFocusAndLayout) {
4098 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4099 assignLayersLocked();
4100 }
4101 mLayoutNeeded = true;
4102 performLayoutAndPlaceSurfacesLocked();
4103 }
4104 }
4105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004106 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
4107 // First remove all of the windows from the list.
4108 final int N = tokens.size();
4109 int i;
4110 for (i=0; i<N; i++) {
4111 WindowToken token = mTokenMap.get(tokens.get(i));
4112 if (token != null) {
4113 tmpRemoveAppWindowsLocked(token);
4114 }
4115 }
4116
4117 // Where to start adding?
4118 int pos = findWindowOffsetLocked(tokenPos);
4119
4120 // And now add them back at the correct place.
4121 for (i=0; i<N; i++) {
4122 WindowToken token = mTokenMap.get(tokens.get(i));
4123 if (token != null) {
4124 pos = reAddAppWindowsLocked(pos, token);
4125 }
4126 }
4127
Dianne Hackborna8f60182009-09-01 19:01:50 -07004128 if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
4129 assignLayersLocked();
4130 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004131 mLayoutNeeded = true;
4132 performLayoutAndPlaceSurfacesLocked();
4133
4134 //dump();
4135 }
4136
4137 public void moveAppTokensToTop(List<IBinder> tokens) {
4138 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4139 "moveAppTokensToTop()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004140 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004141 }
4142
4143 final long origId = Binder.clearCallingIdentity();
4144 synchronized(mWindowMap) {
4145 removeAppTokensLocked(tokens);
4146 final int N = tokens.size();
4147 for (int i=0; i<N; i++) {
4148 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4149 if (wt != null) {
4150 mAppTokens.add(wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004151 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004152 mToTopApps.remove(wt);
4153 mToBottomApps.remove(wt);
4154 mToTopApps.add(wt);
4155 wt.sendingToBottom = false;
4156 wt.sendingToTop = true;
4157 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004158 }
4159 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004160
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004161 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004162 moveAppWindowsLocked(tokens, mAppTokens.size());
4163 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004164 }
4165 Binder.restoreCallingIdentity(origId);
4166 }
4167
4168 public void moveAppTokensToBottom(List<IBinder> tokens) {
4169 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
4170 "moveAppTokensToBottom()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004171 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004172 }
4173
4174 final long origId = Binder.clearCallingIdentity();
4175 synchronized(mWindowMap) {
4176 removeAppTokensLocked(tokens);
4177 final int N = tokens.size();
4178 int pos = 0;
4179 for (int i=0; i<N; i++) {
4180 AppWindowToken wt = findAppWindowToken(tokens.get(i));
4181 if (wt != null) {
4182 mAppTokens.add(pos, wt);
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004183 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004184 mToTopApps.remove(wt);
4185 mToBottomApps.remove(wt);
4186 mToBottomApps.add(i, wt);
4187 wt.sendingToTop = false;
4188 wt.sendingToBottom = true;
4189 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004190 pos++;
4191 }
4192 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004193
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07004194 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07004195 moveAppWindowsLocked(tokens, 0);
4196 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004197 }
4198 Binder.restoreCallingIdentity(origId);
4199 }
4200
4201 // -------------------------------------------------------------
4202 // Misc IWindowSession methods
4203 // -------------------------------------------------------------
Romain Guy06882f82009-06-10 13:36:04 -07004204
Jim Miller284b62e2010-06-08 14:27:42 -07004205 private boolean shouldAllowDisableKeyguard()
Jim Millerd6b57052010-06-07 17:52:42 -07004206 {
Jim Miller284b62e2010-06-08 14:27:42 -07004207 // We fail safe and prevent disabling keyguard in the unlikely event this gets
4208 // called before DevicePolicyManagerService has started.
4209 if (mAllowDisableKeyguard == ALLOW_DISABLE_UNKNOWN) {
4210 DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(
4211 Context.DEVICE_POLICY_SERVICE);
4212 if (dpm != null) {
4213 mAllowDisableKeyguard = dpm.getPasswordQuality(null)
4214 == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED ?
4215 ALLOW_DISABLE_YES : ALLOW_DISABLE_NO;
4216 }
Jim Millerd6b57052010-06-07 17:52:42 -07004217 }
Jim Miller284b62e2010-06-08 14:27:42 -07004218 return mAllowDisableKeyguard == ALLOW_DISABLE_YES;
Jim Millerd6b57052010-06-07 17:52:42 -07004219 }
4220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 public void disableKeyguard(IBinder token, String tag) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004222 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004223 != PackageManager.PERMISSION_GRANTED) {
4224 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4225 }
Jim Millerd6b57052010-06-07 17:52:42 -07004226
Jim Miller284b62e2010-06-08 14:27:42 -07004227 synchronized (mKeyguardTokenWatcher) {
4228 mKeyguardTokenWatcher.acquire(token, tag);
Mike Lockwooddd884682009-10-11 16:57:08 -04004229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004230 }
4231
4232 public void reenableKeyguard(IBinder token) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004233 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004234 != PackageManager.PERMISSION_GRANTED) {
4235 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4236 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004237
Jim Miller284b62e2010-06-08 14:27:42 -07004238 synchronized (mKeyguardTokenWatcher) {
4239 mKeyguardTokenWatcher.release(token);
Jim Millerd6b57052010-06-07 17:52:42 -07004240
Jim Miller284b62e2010-06-08 14:27:42 -07004241 if (!mKeyguardTokenWatcher.isAcquired()) {
4242 // If we are the last one to reenable the keyguard wait until
4243 // we have actually finished reenabling until returning.
4244 // It is possible that reenableKeyguard() can be called before
4245 // the previous disableKeyguard() is handled, in which case
4246 // neither mKeyguardTokenWatcher.acquired() or released() would
4247 // be called. In that case mKeyguardDisabled will be false here
4248 // and we have nothing to wait for.
4249 while (mKeyguardDisabled) {
4250 try {
4251 mKeyguardTokenWatcher.wait();
4252 } catch (InterruptedException e) {
4253 Thread.currentThread().interrupt();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004254 }
4255 }
4256 }
4257 }
4258 }
4259
4260 /**
4261 * @see android.app.KeyguardManager#exitKeyguardSecurely
4262 */
4263 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
Mike Lockwood733fdf32009-09-28 19:08:53 -04004264 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004265 != PackageManager.PERMISSION_GRANTED) {
4266 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
4267 }
4268 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
4269 public void onKeyguardExitResult(boolean success) {
4270 try {
4271 callback.onKeyguardExitResult(success);
4272 } catch (RemoteException e) {
4273 // Client has died, we don't care.
4274 }
4275 }
4276 });
4277 }
4278
4279 public boolean inKeyguardRestrictedInputMode() {
4280 return mPolicy.inKeyguardRestrictedKeyInputMode();
4281 }
Romain Guy06882f82009-06-10 13:36:04 -07004282
Dianne Hackbornffa42482009-09-23 22:20:11 -07004283 public void closeSystemDialogs(String reason) {
4284 synchronized(mWindowMap) {
4285 for (int i=mWindows.size()-1; i>=0; i--) {
4286 WindowState w = (WindowState)mWindows.get(i);
4287 if (w.mSurface != null) {
4288 try {
4289 w.mClient.closeSystemDialogs(reason);
4290 } catch (RemoteException e) {
4291 }
4292 }
4293 }
4294 }
4295 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004297 static float fixScale(float scale) {
4298 if (scale < 0) scale = 0;
4299 else if (scale > 20) scale = 20;
4300 return Math.abs(scale);
4301 }
Romain Guy06882f82009-06-10 13:36:04 -07004302
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004303 public void setAnimationScale(int which, float scale) {
4304 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4305 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004306 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004307 }
4308
4309 if (scale < 0) scale = 0;
4310 else if (scale > 20) scale = 20;
4311 scale = Math.abs(scale);
4312 switch (which) {
4313 case 0: mWindowAnimationScale = fixScale(scale); break;
4314 case 1: mTransitionAnimationScale = fixScale(scale); break;
4315 }
Romain Guy06882f82009-06-10 13:36:04 -07004316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004317 // Persist setting
4318 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4319 }
Romain Guy06882f82009-06-10 13:36:04 -07004320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004321 public void setAnimationScales(float[] scales) {
4322 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
4323 "setAnimationScale()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004324 throw new SecurityException("Requires SET_ANIMATION_SCALE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004325 }
4326
4327 if (scales != null) {
4328 if (scales.length >= 1) {
4329 mWindowAnimationScale = fixScale(scales[0]);
4330 }
4331 if (scales.length >= 2) {
4332 mTransitionAnimationScale = fixScale(scales[1]);
4333 }
4334 }
Romain Guy06882f82009-06-10 13:36:04 -07004335
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004336 // Persist setting
4337 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
4338 }
Romain Guy06882f82009-06-10 13:36:04 -07004339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004340 public float getAnimationScale(int which) {
4341 switch (which) {
4342 case 0: return mWindowAnimationScale;
4343 case 1: return mTransitionAnimationScale;
4344 }
4345 return 0;
4346 }
Romain Guy06882f82009-06-10 13:36:04 -07004347
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 public float[] getAnimationScales() {
4349 return new float[] { mWindowAnimationScale, mTransitionAnimationScale };
4350 }
Romain Guy06882f82009-06-10 13:36:04 -07004351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004352 public int getSwitchState(int sw) {
4353 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4354 "getSwitchState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004355 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004356 }
4357 return KeyInputQueue.getSwitchState(sw);
4358 }
Romain Guy06882f82009-06-10 13:36:04 -07004359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 public int getSwitchStateForDevice(int devid, int sw) {
4361 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4362 "getSwitchStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004363 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004364 }
4365 return KeyInputQueue.getSwitchState(devid, sw);
4366 }
Romain Guy06882f82009-06-10 13:36:04 -07004367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004368 public int getScancodeState(int sw) {
4369 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4370 "getScancodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004371 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004373 return mQueue.getScancodeState(sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004374 }
Romain Guy06882f82009-06-10 13:36:04 -07004375
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 public int getScancodeStateForDevice(int devid, int sw) {
4377 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4378 "getScancodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004379 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004380 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004381 return mQueue.getScancodeState(devid, sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004382 }
Romain Guy06882f82009-06-10 13:36:04 -07004383
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004384 public int getTrackballScancodeState(int sw) {
4385 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4386 "getTrackballScancodeState()")) {
4387 throw new SecurityException("Requires READ_INPUT_STATE permission");
4388 }
4389 return mQueue.getTrackballScancodeState(sw);
4390 }
4391
4392 public int getDPadScancodeState(int sw) {
4393 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4394 "getDPadScancodeState()")) {
4395 throw new SecurityException("Requires READ_INPUT_STATE permission");
4396 }
4397 return mQueue.getDPadScancodeState(sw);
4398 }
4399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004400 public int getKeycodeState(int sw) {
4401 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4402 "getKeycodeState()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004403 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004404 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004405 return mQueue.getKeycodeState(sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004406 }
Romain Guy06882f82009-06-10 13:36:04 -07004407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004408 public int getKeycodeStateForDevice(int devid, int sw) {
4409 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4410 "getKeycodeStateForDevice()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004411 throw new SecurityException("Requires READ_INPUT_STATE permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004412 }
Dianne Hackborn6af0d502009-09-28 13:25:46 -07004413 return mQueue.getKeycodeState(devid, sw);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004414 }
Romain Guy06882f82009-06-10 13:36:04 -07004415
Dianne Hackborn1d62ea92009-11-17 12:49:50 -08004416 public int getTrackballKeycodeState(int sw) {
4417 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4418 "getTrackballKeycodeState()")) {
4419 throw new SecurityException("Requires READ_INPUT_STATE permission");
4420 }
4421 return mQueue.getTrackballKeycodeState(sw);
4422 }
4423
4424 public int getDPadKeycodeState(int sw) {
4425 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
4426 "getDPadKeycodeState()")) {
4427 throw new SecurityException("Requires READ_INPUT_STATE permission");
4428 }
4429 return mQueue.getDPadKeycodeState(sw);
4430 }
4431
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004432 public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
4433 return KeyInputQueue.hasKeys(keycodes, keyExists);
4434 }
Romain Guy06882f82009-06-10 13:36:04 -07004435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004436 public void enableScreenAfterBoot() {
4437 synchronized(mWindowMap) {
4438 if (mSystemBooted) {
4439 return;
4440 }
4441 mSystemBooted = true;
4442 }
Romain Guy06882f82009-06-10 13:36:04 -07004443
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004444 performEnableScreen();
4445 }
Romain Guy06882f82009-06-10 13:36:04 -07004446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004447 public void enableScreenIfNeededLocked() {
4448 if (mDisplayEnabled) {
4449 return;
4450 }
4451 if (!mSystemBooted) {
4452 return;
4453 }
4454 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
4455 }
Romain Guy06882f82009-06-10 13:36:04 -07004456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004457 public void performEnableScreen() {
4458 synchronized(mWindowMap) {
4459 if (mDisplayEnabled) {
4460 return;
4461 }
4462 if (!mSystemBooted) {
4463 return;
4464 }
Romain Guy06882f82009-06-10 13:36:04 -07004465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004466 // Don't enable the screen until all existing windows
4467 // have been drawn.
4468 final int N = mWindows.size();
4469 for (int i=0; i<N; i++) {
4470 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn5943c202010-04-12 21:36:49 -07004471 if (w.isVisibleLw() && !w.mObscured
4472 && (w.mOrientationChanging || !w.isDrawnLw())) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004473 return;
4474 }
4475 }
Romain Guy06882f82009-06-10 13:36:04 -07004476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004477 mDisplayEnabled = true;
4478 if (false) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004479 Slog.i(TAG, "ENABLING SCREEN!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004480 StringWriter sw = new StringWriter();
4481 PrintWriter pw = new PrintWriter(sw);
4482 this.dump(null, pw, null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004483 Slog.i(TAG, sw.toString());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004484 }
4485 try {
4486 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
4487 if (surfaceFlinger != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004488 //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004489 Parcel data = Parcel.obtain();
4490 data.writeInterfaceToken("android.ui.ISurfaceComposer");
4491 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
4492 data, null, 0);
4493 data.recycle();
4494 }
4495 } catch (RemoteException ex) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004496 Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004497 }
4498 }
Romain Guy06882f82009-06-10 13:36:04 -07004499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004500 mPolicy.enableScreenAfterBoot();
Romain Guy06882f82009-06-10 13:36:04 -07004501
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004502 // Make sure the last requested orientation has been applied.
Dianne Hackborn321ae682009-03-27 16:16:03 -07004503 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false,
4504 mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004505 }
Romain Guy06882f82009-06-10 13:36:04 -07004506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004507 public void setInTouchMode(boolean mode) {
4508 synchronized(mWindowMap) {
4509 mInTouchMode = mode;
4510 }
4511 }
4512
Romain Guy06882f82009-06-10 13:36:04 -07004513 public void setRotation(int rotation,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004514 boolean alwaysSendConfiguration, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004515 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004516 "setRotation()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07004517 throw new SecurityException("Requires SET_ORIENTATION permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004518 }
4519
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004520 setRotationUnchecked(rotation, alwaysSendConfiguration, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004521 }
Romain Guy06882f82009-06-10 13:36:04 -07004522
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004523 public void setRotationUnchecked(int rotation,
4524 boolean alwaysSendConfiguration, int animFlags) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004525 if(DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004526 "alwaysSendConfiguration set to "+alwaysSendConfiguration);
Romain Guy06882f82009-06-10 13:36:04 -07004527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004528 long origId = Binder.clearCallingIdentity();
4529 boolean changed;
4530 synchronized(mWindowMap) {
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004531 changed = setRotationUncheckedLocked(rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004532 }
Romain Guy06882f82009-06-10 13:36:04 -07004533
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004534 if (changed || alwaysSendConfiguration) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004535 sendNewConfiguration();
4536 }
Romain Guy06882f82009-06-10 13:36:04 -07004537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004538 Binder.restoreCallingIdentity(origId);
4539 }
Romain Guy06882f82009-06-10 13:36:04 -07004540
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004541 /**
4542 * Apply a new rotation to the screen, respecting the requests of
4543 * applications. Use WindowManagerPolicy.USE_LAST_ROTATION to simply
4544 * re-evaluate the desired rotation.
4545 *
4546 * Returns null if the rotation has been changed. In this case YOU
4547 * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
4548 */
Dianne Hackborn1e880db2009-03-27 16:04:08 -07004549 public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004550 boolean changed;
4551 if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
4552 rotation = mRequestedRotation;
4553 } else {
4554 mRequestedRotation = rotation;
Dianne Hackborn321ae682009-03-27 16:16:03 -07004555 mLastRotationFlags = animFlags;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004556 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08004557 if (DEBUG_ORIENTATION) Slog.v(TAG, "Overwriting rotation value from " + rotation);
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07004558 rotation = mPolicy.rotationForOrientationLw(mForcedAppOrientation,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004559 mRotation, mDisplayEnabled);
Joe Onorato8a9b2202010-02-26 18:56:32 -08004560 if (DEBUG_ORIENTATION) Slog.v(TAG, "new rotation is set to " + rotation);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004561 changed = mDisplayEnabled && mRotation != rotation;
Romain Guy06882f82009-06-10 13:36:04 -07004562
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004563 if (changed) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004564 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004565 "Rotation changed to " + rotation
4566 + " from " + mRotation
4567 + " (forceApp=" + mForcedAppOrientation
4568 + ", req=" + mRequestedRotation + ")");
4569 mRotation = rotation;
4570 mWindowsFreezingScreen = true;
4571 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
4572 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
4573 2000);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08004574 mWaitingForConfig = true;
4575 mLayoutNeeded = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004576 startFreezingDisplayLocked();
Joe Onorato8a9b2202010-02-26 18:56:32 -08004577 Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004578 mQueue.setOrientation(rotation);
4579 if (mDisplayEnabled) {
Dianne Hackborn321ae682009-03-27 16:16:03 -07004580 Surface.setOrientation(0, rotation, animFlags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004581 }
4582 for (int i=mWindows.size()-1; i>=0; i--) {
4583 WindowState w = (WindowState)mWindows.get(i);
4584 if (w.mSurface != null) {
4585 w.mOrientationChanging = true;
4586 }
4587 }
4588 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
4589 try {
4590 mRotationWatchers.get(i).onRotationChanged(rotation);
4591 } catch (RemoteException e) {
4592 }
4593 }
4594 } //end if changed
Romain Guy06882f82009-06-10 13:36:04 -07004595
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004596 return changed;
4597 }
Romain Guy06882f82009-06-10 13:36:04 -07004598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004599 public int getRotation() {
4600 return mRotation;
4601 }
4602
4603 public int watchRotation(IRotationWatcher watcher) {
4604 final IBinder watcherBinder = watcher.asBinder();
4605 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
4606 public void binderDied() {
4607 synchronized (mWindowMap) {
4608 for (int i=0; i<mRotationWatchers.size(); i++) {
4609 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07004610 IRotationWatcher removed = mRotationWatchers.remove(i);
4611 if (removed != null) {
4612 removed.asBinder().unlinkToDeath(this, 0);
4613 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004614 i--;
4615 }
4616 }
4617 }
4618 }
4619 };
Romain Guy06882f82009-06-10 13:36:04 -07004620
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004621 synchronized (mWindowMap) {
4622 try {
4623 watcher.asBinder().linkToDeath(dr, 0);
4624 mRotationWatchers.add(watcher);
4625 } catch (RemoteException e) {
4626 // Client died, no cleanup needed.
4627 }
Romain Guy06882f82009-06-10 13:36:04 -07004628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004629 return mRotation;
4630 }
4631 }
4632
4633 /**
4634 * Starts the view server on the specified port.
4635 *
4636 * @param port The port to listener to.
4637 *
4638 * @return True if the server was successfully started, false otherwise.
4639 *
4640 * @see com.android.server.ViewServer
4641 * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT
4642 */
4643 public boolean startViewServer(int port) {
Romain Guy06882f82009-06-10 13:36:04 -07004644 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004645 return false;
4646 }
4647
4648 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
4649 return false;
4650 }
4651
4652 if (port < 1024) {
4653 return false;
4654 }
4655
4656 if (mViewServer != null) {
4657 if (!mViewServer.isRunning()) {
4658 try {
4659 return mViewServer.start();
4660 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004661 Slog.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004662 }
4663 }
4664 return false;
4665 }
4666
4667 try {
4668 mViewServer = new ViewServer(this, port);
4669 return mViewServer.start();
4670 } catch (IOException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004671 Slog.w(TAG, "View server did not start");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004672 }
4673 return false;
4674 }
4675
Romain Guy06882f82009-06-10 13:36:04 -07004676 private boolean isSystemSecure() {
4677 return "1".equals(SystemProperties.get(SYSTEM_SECURE, "1")) &&
4678 "0".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"));
4679 }
4680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004681 /**
4682 * Stops the view server if it exists.
4683 *
4684 * @return True if the server stopped, false if it wasn't started or
4685 * couldn't be stopped.
4686 *
4687 * @see com.android.server.ViewServer
4688 */
4689 public boolean stopViewServer() {
Romain Guy06882f82009-06-10 13:36:04 -07004690 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004691 return false;
4692 }
4693
4694 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
4695 return false;
4696 }
4697
4698 if (mViewServer != null) {
4699 return mViewServer.stop();
4700 }
4701 return false;
4702 }
4703
4704 /**
4705 * Indicates whether the view server is running.
4706 *
4707 * @return True if the server is running, false otherwise.
4708 *
4709 * @see com.android.server.ViewServer
4710 */
4711 public boolean isViewServerRunning() {
Romain Guy06882f82009-06-10 13:36:04 -07004712 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004713 return false;
4714 }
4715
4716 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
4717 return false;
4718 }
4719
4720 return mViewServer != null && mViewServer.isRunning();
4721 }
4722
4723 /**
4724 * Lists all availble windows in the system. The listing is written in the
4725 * specified Socket's output stream with the following syntax:
4726 * windowHashCodeInHexadecimal windowName
4727 * Each line of the ouput represents a different window.
4728 *
4729 * @param client The remote client to send the listing to.
4730 * @return False if an error occured, true otherwise.
4731 */
4732 boolean viewServerListWindows(Socket client) {
Romain Guy06882f82009-06-10 13:36:04 -07004733 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004734 return false;
4735 }
4736
4737 boolean result = true;
4738
4739 Object[] windows;
4740 synchronized (mWindowMap) {
4741 windows = new Object[mWindows.size()];
4742 //noinspection unchecked
4743 windows = mWindows.toArray(windows);
4744 }
4745
4746 BufferedWriter out = null;
4747
4748 // Any uncaught exception will crash the system process
4749 try {
4750 OutputStream clientStream = client.getOutputStream();
4751 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
4752
4753 final int count = windows.length;
4754 for (int i = 0; i < count; i++) {
4755 final WindowState w = (WindowState) windows[i];
4756 out.write(Integer.toHexString(System.identityHashCode(w)));
4757 out.write(' ');
4758 out.append(w.mAttrs.getTitle());
4759 out.write('\n');
4760 }
4761
4762 out.write("DONE.\n");
4763 out.flush();
4764 } catch (Exception e) {
4765 result = false;
4766 } finally {
4767 if (out != null) {
4768 try {
4769 out.close();
4770 } catch (IOException e) {
4771 result = false;
4772 }
4773 }
4774 }
4775
4776 return result;
4777 }
4778
4779 /**
4780 * Sends a command to a target window. The result of the command, if any, will be
4781 * written in the output stream of the specified socket.
4782 *
4783 * The parameters must follow this syntax:
4784 * windowHashcode extra
4785 *
4786 * Where XX is the length in characeters of the windowTitle.
4787 *
4788 * The first parameter is the target window. The window with the specified hashcode
4789 * will be the target. If no target can be found, nothing happens. The extra parameters
4790 * will be delivered to the target window and as parameters to the command itself.
4791 *
4792 * @param client The remote client to sent the result, if any, to.
4793 * @param command The command to execute.
4794 * @param parameters The command parameters.
4795 *
4796 * @return True if the command was successfully delivered, false otherwise. This does
4797 * not indicate whether the command itself was successful.
4798 */
4799 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
Romain Guy06882f82009-06-10 13:36:04 -07004800 if (isSystemSecure()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004801 return false;
4802 }
4803
4804 boolean success = true;
4805 Parcel data = null;
4806 Parcel reply = null;
4807
4808 // Any uncaught exception will crash the system process
4809 try {
4810 // Find the hashcode of the window
4811 int index = parameters.indexOf(' ');
4812 if (index == -1) {
4813 index = parameters.length();
4814 }
4815 final String code = parameters.substring(0, index);
Romain Guy236092a2009-12-14 15:31:48 -08004816 int hashCode = (int) Long.parseLong(code, 16);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004817
4818 // Extract the command's parameter after the window description
4819 if (index < parameters.length()) {
4820 parameters = parameters.substring(index + 1);
4821 } else {
4822 parameters = "";
4823 }
4824
4825 final WindowManagerService.WindowState window = findWindow(hashCode);
4826 if (window == null) {
4827 return false;
4828 }
4829
4830 data = Parcel.obtain();
4831 data.writeInterfaceToken("android.view.IWindow");
4832 data.writeString(command);
4833 data.writeString(parameters);
4834 data.writeInt(1);
4835 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
4836
4837 reply = Parcel.obtain();
4838
4839 final IBinder binder = window.mClient.asBinder();
4840 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
4841 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
4842
4843 reply.readException();
4844
4845 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08004846 Slog.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004847 success = false;
4848 } finally {
4849 if (data != null) {
4850 data.recycle();
4851 }
4852 if (reply != null) {
4853 reply.recycle();
4854 }
4855 }
4856
4857 return success;
4858 }
4859
4860 private WindowState findWindow(int hashCode) {
4861 if (hashCode == -1) {
4862 return getFocusedWindow();
4863 }
4864
4865 synchronized (mWindowMap) {
4866 final ArrayList windows = mWindows;
4867 final int count = windows.size();
4868
4869 for (int i = 0; i < count; i++) {
4870 WindowState w = (WindowState) windows.get(i);
4871 if (System.identityHashCode(w) == hashCode) {
4872 return w;
4873 }
4874 }
4875 }
4876
4877 return null;
4878 }
4879
4880 /*
4881 * Instruct the Activity Manager to fetch the current configuration and broadcast
4882 * that to config-changed listeners if appropriate.
4883 */
4884 void sendNewConfiguration() {
4885 try {
4886 mActivityManager.updateConfiguration(null);
4887 } catch (RemoteException e) {
4888 }
4889 }
Romain Guy06882f82009-06-10 13:36:04 -07004890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004891 public Configuration computeNewConfiguration() {
4892 synchronized (mWindowMap) {
Dianne Hackbornc485a602009-03-24 22:39:49 -07004893 return computeNewConfigurationLocked();
4894 }
4895 }
Romain Guy06882f82009-06-10 13:36:04 -07004896
Dianne Hackbornc485a602009-03-24 22:39:49 -07004897 Configuration computeNewConfigurationLocked() {
4898 Configuration config = new Configuration();
4899 if (!computeNewConfigurationLocked(config)) {
4900 return null;
4901 }
Dianne Hackbornc485a602009-03-24 22:39:49 -07004902 return config;
4903 }
Romain Guy06882f82009-06-10 13:36:04 -07004904
Dianne Hackbornc485a602009-03-24 22:39:49 -07004905 boolean computeNewConfigurationLocked(Configuration config) {
4906 if (mDisplay == null) {
4907 return false;
4908 }
4909 mQueue.getInputConfiguration(config);
Christopher Tateb696aee2010-04-02 19:08:30 -07004910
4911 // Use the effective "visual" dimensions based on current rotation
4912 final boolean rotated = (mRotation == Surface.ROTATION_90
4913 || mRotation == Surface.ROTATION_270);
4914 final int dw = rotated ? mInitialDisplayHeight : mInitialDisplayWidth;
4915 final int dh = rotated ? mInitialDisplayWidth : mInitialDisplayHeight;
4916
Dianne Hackbornc485a602009-03-24 22:39:49 -07004917 int orientation = Configuration.ORIENTATION_SQUARE;
4918 if (dw < dh) {
4919 orientation = Configuration.ORIENTATION_PORTRAIT;
4920 } else if (dw > dh) {
4921 orientation = Configuration.ORIENTATION_LANDSCAPE;
4922 }
4923 config.orientation = orientation;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004924
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07004925 DisplayMetrics dm = new DisplayMetrics();
4926 mDisplay.getMetrics(dm);
4927 CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
4928
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004929 if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
Dianne Hackborn723738c2009-06-25 19:48:04 -07004930 // Note we only do this once because at this point we don't
4931 // expect the screen to change in this way at runtime, and want
4932 // to avoid all of this computation for every config change.
Dianne Hackborn723738c2009-06-25 19:48:04 -07004933 int longSize = dw;
4934 int shortSize = dh;
4935 if (longSize < shortSize) {
4936 int tmp = longSize;
4937 longSize = shortSize;
4938 shortSize = tmp;
4939 }
4940 longSize = (int)(longSize/dm.density);
4941 shortSize = (int)(shortSize/dm.density);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07004942
Dianne Hackborn723738c2009-06-25 19:48:04 -07004943 // These semi-magic numbers define our compatibility modes for
4944 // applications with different screens. Don't change unless you
4945 // make sure to test lots and lots of apps!
4946 if (longSize < 470) {
4947 // This is shorter than an HVGA normal density screen (which
4948 // is 480 pixels on its long side).
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004949 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
4950 | Configuration.SCREENLAYOUT_LONG_NO;
Dianne Hackborn723738c2009-06-25 19:48:04 -07004951 } else {
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004952 // Is this a large screen?
4953 if (longSize > 640 && shortSize >= 480) {
4954 // VGA or larger screens at medium density are the point
4955 // at which we consider it to be a large screen.
4956 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
4957 } else {
4958 mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004959
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004960 // If this screen is wider than normal HVGA, or taller
4961 // than FWVGA, then for old apps we want to run in size
4962 // compatibility mode.
4963 if (shortSize > 321 || longSize > 570) {
4964 mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
4965 }
4966 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004967
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004968 // Is this a long screen?
4969 if (((longSize*3)/5) >= (shortSize-1)) {
4970 // Anything wider than WVGA (5:3) is considering to be long.
4971 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
4972 } else {
4973 mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
4974 }
Dianne Hackborn723738c2009-06-25 19:48:04 -07004975 }
4976 }
Dianne Hackbornc4db95c2009-07-21 17:46:02 -07004977 config.screenLayout = mScreenLayout;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08004978
Dianne Hackbornc485a602009-03-24 22:39:49 -07004979 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
4980 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
4981 mPolicy.adjustConfigurationLw(config);
4982 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004983 }
Romain Guy06882f82009-06-10 13:36:04 -07004984
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004985 // -------------------------------------------------------------
4986 // Input Events and Focus Management
4987 // -------------------------------------------------------------
4988
4989 private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
Michael Chane96440f2009-05-06 10:27:36 -07004990 long curTime = SystemClock.uptimeMillis();
4991
Michael Chane10de972009-05-18 11:24:50 -07004992 if (eventType == TOUCH_EVENT || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT) {
Michael Chane96440f2009-05-06 10:27:36 -07004993 if (mLastTouchEventType == eventType &&
4994 (curTime - mLastUserActivityCallTime) < MIN_TIME_BETWEEN_USERACTIVITIES) {
4995 return;
4996 }
4997 mLastUserActivityCallTime = curTime;
4998 mLastTouchEventType = eventType;
4999 }
5000
5001 if (targetWin == null
5002 || targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
5003 mPowerManager.userActivity(curTime, false, eventType, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005004 }
5005 }
5006
5007 // tells if it's a cheek event or not -- this function is stateful
5008 private static final int EVENT_NONE = 0;
5009 private static final int EVENT_UNKNOWN = 0;
5010 private static final int EVENT_CHEEK = 0;
5011 private static final int EVENT_IGNORE_DURATION = 300; // ms
5012 private static final float CHEEK_THRESHOLD = 0.6f;
5013 private int mEventState = EVENT_NONE;
5014 private float mEventSize;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005016 private int eventType(MotionEvent ev) {
5017 float size = ev.getSize();
5018 switch (ev.getAction()) {
5019 case MotionEvent.ACTION_DOWN:
5020 mEventSize = size;
5021 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT;
5022 case MotionEvent.ACTION_UP:
5023 if (size > mEventSize) mEventSize = size;
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005024 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_UP_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005025 case MotionEvent.ACTION_MOVE:
5026 final int N = ev.getHistorySize();
5027 if (size > mEventSize) mEventSize = size;
5028 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5029 for (int i=0; i<N; i++) {
5030 size = ev.getHistoricalSize(i);
5031 if (size > mEventSize) mEventSize = size;
5032 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
5033 }
5034 if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) {
5035 return TOUCH_EVENT;
5036 } else {
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07005037 return LONG_TOUCH_EVENT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005038 }
5039 default:
5040 // not good
5041 return OTHER_EVENT;
5042 }
5043 }
5044
5045 /**
5046 * @return Returns true if event was dispatched, false if it was dropped for any reason
5047 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005048 private int dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005049 if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005050 "dispatchPointer " + ev);
5051
Michael Chan53071d62009-05-13 17:29:48 -07005052 if (MEASURE_LATENCY) {
5053 lt.sample("3 Wait for last dispatch ", System.nanoTime() - qev.whenNano);
5054 }
5055
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005056 Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005057 ev, true, false, pid, uid);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005058
Michael Chan53071d62009-05-13 17:29:48 -07005059 if (MEASURE_LATENCY) {
5060 lt.sample("3 Last dispatch finished ", System.nanoTime() - qev.whenNano);
5061 }
5062
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005063 int action = ev.getAction();
Romain Guy06882f82009-06-10 13:36:04 -07005064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 if (action == MotionEvent.ACTION_UP) {
5066 // let go of our target
5067 mKeyWaiter.mMotionTarget = null;
5068 mPowerManager.logPointerUpEvent();
5069 } else if (action == MotionEvent.ACTION_DOWN) {
5070 mPowerManager.logPointerDownEvent();
5071 }
5072
5073 if (targetObj == null) {
5074 // In this case we are either dropping the event, or have received
5075 // a move or up without a down. It is common to receive move
5076 // events in such a way, since this means the user is moving the
5077 // pointer without actually pressing down. All other cases should
5078 // be atypical, so let's log them.
Michael Chane96440f2009-05-06 10:27:36 -07005079 if (action != MotionEvent.ACTION_MOVE) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005080 Slog.w(TAG, "No window to dispatch pointer action " + ev.getAction());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005081 }
Dianne Hackborn6adba242009-11-10 11:10:09 -08005082 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005083 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005084 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005085 if (qev != null) {
5086 mQueue.recycleEvent(qev);
5087 }
5088 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005089 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005090 }
5091 if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborn6adba242009-11-10 11:10:09 -08005092 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005093 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), true);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005095 if (qev != null) {
5096 mQueue.recycleEvent(qev);
5097 }
5098 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005099 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 }
Romain Guy06882f82009-06-10 13:36:04 -07005101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005102 WindowState target = (WindowState)targetObj;
Romain Guy06882f82009-06-10 13:36:04 -07005103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005104 final long eventTime = ev.getEventTime();
Michael Chan53071d62009-05-13 17:29:48 -07005105 final long eventTimeNano = ev.getEventTimeNano();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005106
Joe Onorato8a9b2202010-02-26 18:56:32 -08005107 //Slog.i(TAG, "Sending " + ev + " to " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005108
5109 if (uid != 0 && uid != target.mSession.mUid) {
5110 if (mContext.checkPermission(
5111 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5112 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005113 Slog.w(TAG, "Permission denied: injecting pointer event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114 + pid + " uid " + uid + " to window " + target
5115 + " owned by uid " + target.mSession.mUid);
5116 if (qev != null) {
5117 mQueue.recycleEvent(qev);
5118 }
5119 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005120 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005121 }
5122 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005123
Michael Chan53071d62009-05-13 17:29:48 -07005124 if (MEASURE_LATENCY) {
5125 lt.sample("4 in dispatchPointer ", System.nanoTime() - eventTimeNano);
5126 }
5127
Romain Guy06882f82009-06-10 13:36:04 -07005128 if ((target.mAttrs.flags &
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005129 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
5130 //target wants to ignore fat touch events
5131 boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev);
5132 //explicit flag to return without processing event further
5133 boolean returnFlag = false;
5134 if((action == MotionEvent.ACTION_DOWN)) {
5135 mFatTouch = false;
5136 if(cheekPress) {
5137 mFatTouch = true;
5138 returnFlag = true;
5139 }
5140 } else {
5141 if(action == MotionEvent.ACTION_UP) {
5142 if(mFatTouch) {
5143 //earlier even was invalid doesnt matter if current up is cheekpress or not
5144 mFatTouch = false;
5145 returnFlag = true;
5146 } else if(cheekPress) {
5147 //cancel the earlier event
5148 ev.setAction(MotionEvent.ACTION_CANCEL);
5149 action = MotionEvent.ACTION_CANCEL;
5150 }
5151 } else if(action == MotionEvent.ACTION_MOVE) {
5152 if(mFatTouch) {
5153 //two cases here
5154 //an invalid down followed by 0 or moves(valid or invalid)
Romain Guy06882f82009-06-10 13:36:04 -07005155 //a valid down, invalid move, more moves. want to ignore till up
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005156 returnFlag = true;
5157 } else if(cheekPress) {
5158 //valid down followed by invalid moves
5159 //an invalid move have to cancel earlier action
5160 ev.setAction(MotionEvent.ACTION_CANCEL);
5161 action = MotionEvent.ACTION_CANCEL;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005162 if (DEBUG_INPUT) Slog.v(TAG, "Sending cancel for invalid ACTION_MOVE");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005163 //note that the subsequent invalid moves will not get here
5164 mFatTouch = true;
5165 }
5166 }
5167 } //else if action
5168 if(returnFlag) {
5169 //recycle que, ev
5170 if (qev != null) {
5171 mQueue.recycleEvent(qev);
5172 }
5173 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005174 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005175 }
5176 } //end if target
Michael Chane96440f2009-05-06 10:27:36 -07005177
Michael Chan9f028e62009-08-04 17:37:46 -07005178 // Enable this for testing the "right" value
5179 if (false && action == MotionEvent.ACTION_DOWN) {
Michael Chane96440f2009-05-06 10:27:36 -07005180 int max_events_per_sec = 35;
5181 try {
5182 max_events_per_sec = Integer.parseInt(SystemProperties
5183 .get("windowsmgr.max_events_per_sec"));
5184 if (max_events_per_sec < 1) {
5185 max_events_per_sec = 35;
5186 }
5187 } catch (NumberFormatException e) {
5188 }
5189 mMinWaitTimeBetweenTouchEvents = 1000 / max_events_per_sec;
5190 }
5191
5192 /*
5193 * Throttle events to minimize CPU usage when there's a flood of events
5194 * e.g. constant contact with the screen
5195 */
5196 if (action == MotionEvent.ACTION_MOVE) {
5197 long nextEventTime = mLastTouchEventTime + mMinWaitTimeBetweenTouchEvents;
5198 long now = SystemClock.uptimeMillis();
5199 if (now < nextEventTime) {
5200 try {
5201 Thread.sleep(nextEventTime - now);
5202 } catch (InterruptedException e) {
5203 }
5204 mLastTouchEventTime = nextEventTime;
5205 } else {
5206 mLastTouchEventTime = now;
5207 }
5208 }
5209
Michael Chan53071d62009-05-13 17:29:48 -07005210 if (MEASURE_LATENCY) {
5211 lt.sample("5 in dispatchPointer ", System.nanoTime() - eventTimeNano);
5212 }
5213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005214 synchronized(mWindowMap) {
Dianne Hackborn6adba242009-11-10 11:10:09 -08005215 if (!target.isVisibleLw()) {
5216 // During this motion dispatch, the target window has become
5217 // invisible.
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005218 dispatchPointerElsewhereLocked(null, null, ev, ev.getEventTime(), false);
Dianne Hackborn6adba242009-11-10 11:10:09 -08005219 if (qev != null) {
5220 mQueue.recycleEvent(qev);
5221 }
5222 ev.recycle();
5223 return INJECT_SUCCEEDED;
5224 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005226 if (qev != null && action == MotionEvent.ACTION_MOVE) {
5227 mKeyWaiter.bindTargetWindowLocked(target,
5228 KeyWaiter.RETURN_PENDING_POINTER, qev);
5229 ev = null;
5230 } else {
5231 if (action == MotionEvent.ACTION_DOWN) {
5232 WindowState out = mKeyWaiter.mOutsideTouchTargets;
5233 if (out != null) {
5234 MotionEvent oev = MotionEvent.obtain(ev);
5235 oev.setAction(MotionEvent.ACTION_OUTSIDE);
5236 do {
5237 final Rect frame = out.mFrame;
5238 oev.offsetLocation(-(float)frame.left, -(float)frame.top);
5239 try {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005240 out.mClient.dispatchPointer(oev, eventTime, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005241 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005242 Slog.i(TAG, "WINDOW DIED during outside motion dispatch: " + out);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005243 }
5244 oev.offsetLocation((float)frame.left, (float)frame.top);
5245 out = out.mNextOutsideTouch;
5246 } while (out != null);
5247 mKeyWaiter.mOutsideTouchTargets = null;
5248 }
5249 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005250
Dianne Hackborn90d2db32010-02-11 22:19:06 -08005251 dispatchPointerElsewhereLocked(target, null, ev, ev.getEventTime(), false);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005252
Dianne Hackborn6adba242009-11-10 11:10:09 -08005253 final Rect frame = target.mFrame;
5254 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
5255 mKeyWaiter.bindTargetWindowLocked(target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 }
5257 }
Romain Guy06882f82009-06-10 13:36:04 -07005258
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005259 // finally offset the event to the target's coordinate system and
5260 // dispatch the event.
5261 try {
5262 if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005263 Slog.v(TAG, "Delivering pointer " + qev + " to " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005264 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005265
Michael Chan53071d62009-05-13 17:29:48 -07005266 if (MEASURE_LATENCY) {
5267 lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
5268 }
5269
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005270 target.mClient.dispatchPointer(ev, eventTime, true);
Michael Chan53071d62009-05-13 17:29:48 -07005271
5272 if (MEASURE_LATENCY) {
5273 lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
5274 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07005275 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005276 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005277 Slog.i(TAG, "WINDOW DIED during motion dispatch: " + target);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005278 mKeyWaiter.mMotionTarget = null;
5279 try {
5280 removeWindow(target.mSession, target.mClient);
5281 } catch (java.util.NoSuchElementException ex) {
5282 // This will happen if the window has already been
5283 // removed.
5284 }
5285 }
Dianne Hackborncfaef692009-06-15 14:24:44 -07005286 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005287 }
Romain Guy06882f82009-06-10 13:36:04 -07005288
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005289 /**
5290 * @return Returns true if event was dispatched, false if it was dropped for any reason
5291 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005292 private int dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005293 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005294 TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">");
Romain Guy06882f82009-06-10 13:36:04 -07005295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005296 Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005297 ev, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005298 if (focusObj == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005299 Slog.w(TAG, "No focus window, dropping trackball: " + ev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005300 if (qev != null) {
5301 mQueue.recycleEvent(qev);
5302 }
5303 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005304 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005305 }
5306 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
5307 if (qev != null) {
5308 mQueue.recycleEvent(qev);
5309 }
5310 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005311 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005312 }
Romain Guy06882f82009-06-10 13:36:04 -07005313
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005314 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07005315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005316 if (uid != 0 && uid != focus.mSession.mUid) {
5317 if (mContext.checkPermission(
5318 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5319 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005320 Slog.w(TAG, "Permission denied: injecting key event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005321 + pid + " uid " + uid + " to window " + focus
5322 + " owned by uid " + focus.mSession.mUid);
5323 if (qev != null) {
5324 mQueue.recycleEvent(qev);
5325 }
5326 ev.recycle();
Dianne Hackborncfaef692009-06-15 14:24:44 -07005327 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005328 }
5329 }
Romain Guy06882f82009-06-10 13:36:04 -07005330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005331 final long eventTime = ev.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07005332
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005333 synchronized(mWindowMap) {
5334 if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) {
5335 mKeyWaiter.bindTargetWindowLocked(focus,
5336 KeyWaiter.RETURN_PENDING_TRACKBALL, qev);
5337 // We don't deliver movement events to the client, we hold
5338 // them and wait for them to call back.
5339 ev = null;
5340 } else {
5341 mKeyWaiter.bindTargetWindowLocked(focus);
5342 }
5343 }
Romain Guy06882f82009-06-10 13:36:04 -07005344
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005345 try {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07005346 focus.mClient.dispatchTrackball(ev, eventTime, true);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005347 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005348 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005349 Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005350 try {
5351 removeWindow(focus.mSession, focus.mClient);
5352 } catch (java.util.NoSuchElementException ex) {
5353 // This will happen if the window has already been
5354 // removed.
5355 }
5356 }
Romain Guy06882f82009-06-10 13:36:04 -07005357
Dianne Hackborncfaef692009-06-15 14:24:44 -07005358 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005359 }
Romain Guy06882f82009-06-10 13:36:04 -07005360
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005361 /**
5362 * @return Returns true if event was dispatched, false if it was dropped for any reason
5363 */
Dianne Hackborncfaef692009-06-15 14:24:44 -07005364 private int dispatchKey(KeyEvent event, int pid, int uid) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005365 if (DEBUG_INPUT) Slog.v(TAG, "Dispatch key: " + event);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005366
5367 Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005368 null, false, false, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005369 if (focusObj == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005370 Slog.w(TAG, "No focus window, dropping: " + event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005371 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005372 }
5373 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005374 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005375 }
Romain Guy06882f82009-06-10 13:36:04 -07005376
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07005377 // Okay we have finished waiting for the last event to be processed.
5378 // First off, if this is a repeat event, check to see if there is
5379 // a corresponding up event in the queue. If there is, we will
5380 // just drop the repeat, because it makes no sense to repeat after
5381 // the user has released a key. (This is especially important for
5382 // long presses.)
5383 if (event.getRepeatCount() > 0 && mQueue.hasKeyUpEvent(event)) {
5384 return INJECT_SUCCEEDED;
5385 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005386
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005387 WindowState focus = (WindowState)focusObj;
Romain Guy06882f82009-06-10 13:36:04 -07005388
Joe Onorato8a9b2202010-02-26 18:56:32 -08005389 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005390 TAG, "Dispatching to " + focus + ": " + event);
5391
5392 if (uid != 0 && uid != focus.mSession.mUid) {
5393 if (mContext.checkPermission(
5394 android.Manifest.permission.INJECT_EVENTS, pid, uid)
5395 != PackageManager.PERMISSION_GRANTED) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005396 Slog.w(TAG, "Permission denied: injecting key event from pid "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005397 + pid + " uid " + uid + " to window " + focus
5398 + " owned by uid " + focus.mSession.mUid);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005399 return INJECT_NO_PERMISSION;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005400 }
5401 }
Romain Guy06882f82009-06-10 13:36:04 -07005402
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005403 synchronized(mWindowMap) {
5404 mKeyWaiter.bindTargetWindowLocked(focus);
5405 }
5406
5407 // NOSHIP extra state logging
5408 mKeyWaiter.recordDispatchState(event, focus);
5409 // END NOSHIP
Romain Guy06882f82009-06-10 13:36:04 -07005410
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005411 try {
5412 if (DEBUG_INPUT || DEBUG_FOCUS) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005413 Slog.v(TAG, "Delivering key " + event.getKeyCode()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005414 + " to " + focus);
5415 }
5416 focus.mClient.dispatchKey(event);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005417 return INJECT_SUCCEEDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005418 } catch (android.os.RemoteException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005419 Slog.i(TAG, "WINDOW DIED during key dispatch: " + focus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005420 try {
5421 removeWindow(focus.mSession, focus.mClient);
5422 } catch (java.util.NoSuchElementException ex) {
5423 // This will happen if the window has already been
5424 // removed.
5425 }
5426 }
Romain Guy06882f82009-06-10 13:36:04 -07005427
Dianne Hackborncfaef692009-06-15 14:24:44 -07005428 return INJECT_FAILED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005429 }
Romain Guy06882f82009-06-10 13:36:04 -07005430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005431 public void pauseKeyDispatching(IBinder _token) {
5432 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5433 "pauseKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005434 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005435 }
5436
5437 synchronized (mWindowMap) {
5438 WindowToken token = mTokenMap.get(_token);
5439 if (token != null) {
5440 mKeyWaiter.pauseDispatchingLocked(token);
5441 }
5442 }
5443 }
5444
5445 public void resumeKeyDispatching(IBinder _token) {
5446 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5447 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005448 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005449 }
5450
5451 synchronized (mWindowMap) {
5452 WindowToken token = mTokenMap.get(_token);
5453 if (token != null) {
5454 mKeyWaiter.resumeDispatchingLocked(token);
5455 }
5456 }
5457 }
5458
5459 public void setEventDispatching(boolean enabled) {
5460 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
5461 "resumeKeyDispatching()")) {
Dianne Hackborncfaef692009-06-15 14:24:44 -07005462 throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005463 }
5464
5465 synchronized (mWindowMap) {
5466 mKeyWaiter.setEventDispatchingLocked(enabled);
5467 }
5468 }
Romain Guy06882f82009-06-10 13:36:04 -07005469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005470 /**
5471 * Injects a keystroke event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005472 *
5473 * @param ev A motion event describing the keystroke action. (Be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005474 * {@link SystemClock#uptimeMillis()} as the timebase.)
5475 * @param sync If true, wait for the event to be completed before returning to the caller.
5476 * @return Returns true if event was dispatched, false if it was dropped for any reason
5477 */
5478 public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
5479 long downTime = ev.getDownTime();
5480 long eventTime = ev.getEventTime();
5481
5482 int action = ev.getAction();
5483 int code = ev.getKeyCode();
5484 int repeatCount = ev.getRepeatCount();
5485 int metaState = ev.getMetaState();
5486 int deviceId = ev.getDeviceId();
5487 int scancode = ev.getScanCode();
5488
5489 if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
5490 if (downTime == 0) downTime = eventTime;
5491
5492 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
The Android Open Source Project10592532009-03-18 17:39:46 -07005493 deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005494
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005495 final int pid = Binder.getCallingPid();
5496 final int uid = Binder.getCallingUid();
5497 final long ident = Binder.clearCallingIdentity();
5498 final int result = dispatchKey(newEvent, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005499 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005500 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005501 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005502 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005503 switch (result) {
5504 case INJECT_NO_PERMISSION:
5505 throw new SecurityException(
Chander S Pechetty27f3de62010-02-10 22:14:00 +05305506 "Injecting to another application requires INJECT_EVENTS permission");
Dianne Hackborncfaef692009-06-15 14:24:44 -07005507 case INJECT_SUCCEEDED:
5508 return true;
5509 }
5510 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005511 }
5512
5513 /**
5514 * Inject a pointer (touch) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005515 *
5516 * @param ev A motion event describing the pointer (touch) action. (As noted in
5517 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005518 * {@link SystemClock#uptimeMillis()} as the timebase.)
5519 * @param sync If true, wait for the event to be completed before returning to the caller.
5520 * @return Returns true if event was dispatched, false if it was dropped for any reason
5521 */
5522 public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005523 final int pid = Binder.getCallingPid();
5524 final int uid = Binder.getCallingUid();
5525 final long ident = Binder.clearCallingIdentity();
5526 final int result = dispatchPointer(null, ev, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005527 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005528 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005529 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005530 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005531 switch (result) {
5532 case INJECT_NO_PERMISSION:
5533 throw new SecurityException(
Chander S Pechetty27f3de62010-02-10 22:14:00 +05305534 "Injecting to another application requires INJECT_EVENTS permission");
Dianne Hackborncfaef692009-06-15 14:24:44 -07005535 case INJECT_SUCCEEDED:
5536 return true;
5537 }
5538 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005539 }
Romain Guy06882f82009-06-10 13:36:04 -07005540
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005541 /**
5542 * Inject a trackball (navigation device) event into the UI.
Romain Guy06882f82009-06-10 13:36:04 -07005543 *
5544 * @param ev A motion event describing the trackball action. (As noted in
5545 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005546 * {@link SystemClock#uptimeMillis()} as the timebase.)
5547 * @param sync If true, wait for the event to be completed before returning to the caller.
5548 * @return Returns true if event was dispatched, false if it was dropped for any reason
5549 */
5550 public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005551 final int pid = Binder.getCallingPid();
5552 final int uid = Binder.getCallingUid();
5553 final long ident = Binder.clearCallingIdentity();
5554 final int result = dispatchTrackball(null, ev, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005555 if (sync) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005556 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true, pid, uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005557 }
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005558 Binder.restoreCallingIdentity(ident);
Dianne Hackborncfaef692009-06-15 14:24:44 -07005559 switch (result) {
5560 case INJECT_NO_PERMISSION:
5561 throw new SecurityException(
Chander S Pechetty27f3de62010-02-10 22:14:00 +05305562 "Injecting to another application requires INJECT_EVENTS permission");
Dianne Hackborncfaef692009-06-15 14:24:44 -07005563 case INJECT_SUCCEEDED:
5564 return true;
5565 }
5566 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005567 }
Romain Guy06882f82009-06-10 13:36:04 -07005568
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005569 private WindowState getFocusedWindow() {
5570 synchronized (mWindowMap) {
5571 return getFocusedWindowLocked();
5572 }
5573 }
5574
5575 private WindowState getFocusedWindowLocked() {
5576 return mCurrentFocus;
5577 }
Romain Guy06882f82009-06-10 13:36:04 -07005578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005579 /**
5580 * This class holds the state for dispatching key events. This state
5581 * is protected by the KeyWaiter instance, NOT by the window lock. You
5582 * can be holding the main window lock while acquire the KeyWaiter lock,
5583 * but not the other way around.
5584 */
5585 final class KeyWaiter {
5586 // NOSHIP debugging
5587 public class DispatchState {
5588 private KeyEvent event;
5589 private WindowState focus;
5590 private long time;
5591 private WindowState lastWin;
5592 private IBinder lastBinder;
5593 private boolean finished;
5594 private boolean gotFirstWindow;
5595 private boolean eventDispatching;
5596 private long timeToSwitch;
5597 private boolean wasFrozen;
5598 private boolean focusPaused;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005599 private WindowState curFocus;
Romain Guy06882f82009-06-10 13:36:04 -07005600
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005601 DispatchState(KeyEvent theEvent, WindowState theFocus) {
5602 focus = theFocus;
5603 event = theEvent;
5604 time = System.currentTimeMillis();
5605 // snapshot KeyWaiter state
5606 lastWin = mLastWin;
5607 lastBinder = mLastBinder;
5608 finished = mFinished;
5609 gotFirstWindow = mGotFirstWindow;
5610 eventDispatching = mEventDispatching;
5611 timeToSwitch = mTimeToSwitch;
5612 wasFrozen = mWasFrozen;
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005613 curFocus = mCurrentFocus;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005614 // cache the paused state at ctor time as well
5615 if (theFocus == null || theFocus.mToken == null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005616 focusPaused = false;
5617 } else {
5618 focusPaused = theFocus.mToken.paused;
5619 }
5620 }
Romain Guy06882f82009-06-10 13:36:04 -07005621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005622 public String toString() {
5623 return "{{" + event + " to " + focus + " @ " + time
5624 + " lw=" + lastWin + " lb=" + lastBinder
5625 + " fin=" + finished + " gfw=" + gotFirstWindow
5626 + " ed=" + eventDispatching + " tts=" + timeToSwitch
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005627 + " wf=" + wasFrozen + " fp=" + focusPaused
Christopher Tate46d45252010-02-09 15:48:57 -08005628 + " mcf=" + curFocus + "}}";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005629 }
5630 };
5631 private DispatchState mDispatchState = null;
5632 public void recordDispatchState(KeyEvent theEvent, WindowState theFocus) {
5633 mDispatchState = new DispatchState(theEvent, theFocus);
5634 }
5635 // END NOSHIP
5636
5637 public static final int RETURN_NOTHING = 0;
5638 public static final int RETURN_PENDING_POINTER = 1;
5639 public static final int RETURN_PENDING_TRACKBALL = 2;
Romain Guy06882f82009-06-10 13:36:04 -07005640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005641 final Object SKIP_TARGET_TOKEN = new Object();
5642 final Object CONSUMED_EVENT_TOKEN = new Object();
Romain Guy06882f82009-06-10 13:36:04 -07005643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005644 private WindowState mLastWin = null;
5645 private IBinder mLastBinder = null;
5646 private boolean mFinished = true;
5647 private boolean mGotFirstWindow = false;
5648 private boolean mEventDispatching = true;
5649 private long mTimeToSwitch = 0;
5650 /* package */ boolean mWasFrozen = false;
Romain Guy06882f82009-06-10 13:36:04 -07005651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005652 // Target of Motion events
5653 WindowState mMotionTarget;
Romain Guy06882f82009-06-10 13:36:04 -07005654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005655 // Windows above the target who would like to receive an "outside"
5656 // touch event for any down events outside of them.
5657 WindowState mOutsideTouchTargets;
5658
5659 /**
5660 * Wait for the last event dispatch to complete, then find the next
5661 * target that should receive the given event and wait for that one
5662 * to be ready to receive it.
5663 */
5664 Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev,
5665 MotionEvent nextMotion, boolean isPointerEvent,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005666 boolean failIfTimeout, int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005667 long startTime = SystemClock.uptimeMillis();
5668 long keyDispatchingTimeout = 5 * 1000;
5669 long waitedFor = 0;
5670
5671 while (true) {
5672 // Figure out which window we care about. It is either the
5673 // last window we are waiting to have process the event or,
5674 // if none, then the next window we think the event should go
5675 // to. Note: we retrieve mLastWin outside of the lock, so
5676 // it may change before we lock. Thus we must check it again.
5677 WindowState targetWin = mLastWin;
5678 boolean targetIsNew = targetWin == null;
Joe Onorato8a9b2202010-02-26 18:56:32 -08005679 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005680 TAG, "waitForLastKey: mFinished=" + mFinished +
5681 ", mLastWin=" + mLastWin);
5682 if (targetIsNew) {
5683 Object target = findTargetWindow(nextKey, qev, nextMotion,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005684 isPointerEvent, callingPid, callingUid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005685 if (target == SKIP_TARGET_TOKEN) {
5686 // The user has pressed a special key, and we are
5687 // dropping all pending events before it.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005688 if (DEBUG_INPUT) Slog.v(TAG, "Skipping: " + nextKey
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005689 + " " + nextMotion);
5690 return null;
5691 }
5692 if (target == CONSUMED_EVENT_TOKEN) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005693 if (DEBUG_INPUT) Slog.v(TAG, "Consumed: " + nextKey
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005694 + " " + nextMotion);
5695 return target;
5696 }
5697 targetWin = (WindowState)target;
5698 }
Romain Guy06882f82009-06-10 13:36:04 -07005699
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005700 AppWindowToken targetApp = null;
Romain Guy06882f82009-06-10 13:36:04 -07005701
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005702 // Now: is it okay to send the next event to this window?
5703 synchronized (this) {
5704 // First: did we come here based on the last window not
5705 // being null, but it changed by the time we got here?
5706 // If so, try again.
5707 if (!targetIsNew && mLastWin == null) {
5708 continue;
5709 }
Romain Guy06882f82009-06-10 13:36:04 -07005710
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005711 // We never dispatch events if not finished with the
5712 // last one, or the display is frozen.
5713 if (mFinished && !mDisplayFrozen) {
5714 // If event dispatching is disabled, then we
5715 // just consume the events.
5716 if (!mEventDispatching) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005717 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005718 "Skipping event; dispatching disabled: "
5719 + nextKey + " " + nextMotion);
5720 return null;
5721 }
5722 if (targetWin != null) {
5723 // If this is a new target, and that target is not
5724 // paused or unresponsive, then all looks good to
5725 // handle the event.
5726 if (targetIsNew && !targetWin.mToken.paused) {
5727 return targetWin;
5728 }
Romain Guy06882f82009-06-10 13:36:04 -07005729
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005730 // If we didn't find a target window, and there is no
5731 // focused app window, then just eat the events.
5732 } else if (mFocusedApp == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005733 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005734 "Skipping event; no focused app: "
5735 + nextKey + " " + nextMotion);
5736 return null;
5737 }
5738 }
Romain Guy06882f82009-06-10 13:36:04 -07005739
Joe Onorato8a9b2202010-02-26 18:56:32 -08005740 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005741 TAG, "Waiting for last key in " + mLastBinder
5742 + " target=" + targetWin
5743 + " mFinished=" + mFinished
5744 + " mDisplayFrozen=" + mDisplayFrozen
5745 + " targetIsNew=" + targetIsNew
5746 + " paused="
5747 + (targetWin != null ? targetWin.mToken.paused : false)
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005748 + " mFocusedApp=" + mFocusedApp
5749 + " mCurrentFocus=" + mCurrentFocus);
Romain Guy06882f82009-06-10 13:36:04 -07005750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005751 targetApp = targetWin != null
5752 ? targetWin.mAppToken : mFocusedApp;
Romain Guy06882f82009-06-10 13:36:04 -07005753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005754 long curTimeout = keyDispatchingTimeout;
5755 if (mTimeToSwitch != 0) {
5756 long now = SystemClock.uptimeMillis();
5757 if (mTimeToSwitch <= now) {
5758 // If an app switch key has been pressed, and we have
5759 // waited too long for the current app to finish
5760 // processing keys, then wait no more!
Christopher Tate136b1f92010-02-11 17:51:24 -08005761 doFinishedKeyLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005762 continue;
5763 }
5764 long switchTimeout = mTimeToSwitch - now;
5765 if (curTimeout > switchTimeout) {
5766 curTimeout = switchTimeout;
5767 }
5768 }
Romain Guy06882f82009-06-10 13:36:04 -07005769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005770 try {
5771 // after that continue
5772 // processing keys, so we don't get stuck.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005773 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005774 TAG, "Waiting for key dispatch: " + curTimeout);
5775 wait(curTimeout);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005776 if (DEBUG_INPUT) Slog.v(TAG, "Finished waiting @"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005777 + SystemClock.uptimeMillis() + " startTime="
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08005778 + startTime + " switchTime=" + mTimeToSwitch
5779 + " target=" + targetWin + " mLW=" + mLastWin
5780 + " mLB=" + mLastBinder + " fin=" + mFinished
5781 + " mCurrentFocus=" + mCurrentFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005782 } catch (InterruptedException e) {
5783 }
5784 }
5785
5786 // If we were frozen during configuration change, restart the
5787 // timeout checks from now; otherwise look at whether we timed
5788 // out before awakening.
5789 if (mWasFrozen) {
5790 waitedFor = 0;
5791 mWasFrozen = false;
5792 } else {
5793 waitedFor = SystemClock.uptimeMillis() - startTime;
5794 }
5795
5796 if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) {
5797 IApplicationToken at = null;
5798 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005799 Slog.w(TAG, "Key dispatching timed out sending to " +
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005800 (targetWin != null ? targetWin.mAttrs.getTitle()
Ken Shirriff8200b202010-02-04 13:34:37 -08005801 : "<null>: no window ready for key dispatch"));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005802 // NOSHIP debugging
Joe Onorato8a9b2202010-02-26 18:56:32 -08005803 Slog.w(TAG, "Previous dispatch state: " + mDispatchState);
5804 Slog.w(TAG, "Current dispatch state: " +
Ken Shirriff8200b202010-02-04 13:34:37 -08005805 new DispatchState(nextKey, targetWin));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005806 // END NOSHIP
5807 //dump();
5808 if (targetWin != null) {
5809 at = targetWin.getAppToken();
5810 } else if (targetApp != null) {
5811 at = targetApp.appToken;
5812 }
5813 }
5814
5815 boolean abort = true;
5816 if (at != null) {
5817 try {
5818 long timeout = at.getKeyDispatchingTimeout();
5819 if (timeout > waitedFor) {
5820 // we did not wait the proper amount of time for this application.
5821 // set the timeout to be the real timeout and wait again.
5822 keyDispatchingTimeout = timeout - waitedFor;
5823 continue;
5824 } else {
5825 abort = at.keyDispatchingTimedOut();
5826 }
5827 } catch (RemoteException ex) {
5828 }
5829 }
5830
5831 synchronized (this) {
5832 if (abort && (mLastWin == targetWin || targetWin == null)) {
5833 mFinished = true;
Romain Guy06882f82009-06-10 13:36:04 -07005834 if (mLastWin != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005835 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005836 "Window " + mLastWin +
5837 " timed out on key input");
5838 if (mLastWin.mToken.paused) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005839 Slog.w(TAG, "Un-pausing dispatching to this window");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005840 mLastWin.mToken.paused = false;
5841 }
5842 }
5843 if (mMotionTarget == targetWin) {
5844 mMotionTarget = null;
5845 }
5846 mLastWin = null;
5847 mLastBinder = null;
5848 if (failIfTimeout || targetWin == null) {
5849 return null;
5850 }
5851 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005852 Slog.w(TAG, "Continuing to wait for key to be dispatched");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005853 startTime = SystemClock.uptimeMillis();
5854 }
5855 }
5856 }
5857 }
5858 }
Romain Guy06882f82009-06-10 13:36:04 -07005859
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev,
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005861 MotionEvent nextMotion, boolean isPointerEvent,
5862 int callingPid, int callingUid) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005863 mOutsideTouchTargets = null;
Romain Guy06882f82009-06-10 13:36:04 -07005864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005865 if (nextKey != null) {
5866 // Find the target window for a normal key event.
5867 final int keycode = nextKey.getKeyCode();
5868 final int repeatCount = nextKey.getRepeatCount();
5869 final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP;
5870 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005872 if (!dispatch) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005873 if (callingUid == 0 ||
5874 mContext.checkPermission(
5875 android.Manifest.permission.INJECT_EVENTS,
5876 callingPid, callingUid)
5877 == PackageManager.PERMISSION_GRANTED) {
5878 mPolicy.interceptKeyTi(null, keycode,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07005879 nextKey.getMetaState(), down, repeatCount,
5880 nextKey.getFlags());
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005881 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08005882 Slog.w(TAG, "Event timeout during app switch: dropping "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005883 + nextKey);
5884 return SKIP_TARGET_TOKEN;
5885 }
Romain Guy06882f82009-06-10 13:36:04 -07005886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005887 // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")");
Romain Guy06882f82009-06-10 13:36:04 -07005888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005889 WindowState focus = null;
5890 synchronized(mWindowMap) {
5891 focus = getFocusedWindowLocked();
5892 }
Romain Guy06882f82009-06-10 13:36:04 -07005893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005894 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
Romain Guy06882f82009-06-10 13:36:04 -07005895
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005896 if (callingUid == 0 ||
5897 (focus != null && callingUid == focus.mSession.mUid) ||
5898 mContext.checkPermission(
5899 android.Manifest.permission.INJECT_EVENTS,
5900 callingPid, callingUid)
5901 == PackageManager.PERMISSION_GRANTED) {
5902 if (mPolicy.interceptKeyTi(focus,
Doug Zongkerab5c49c2009-12-04 10:31:43 -08005903 keycode, nextKey.getMetaState(), down, repeatCount,
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07005904 nextKey.getFlags())) {
Dianne Hackborn2bd33d72009-06-26 18:59:01 -07005905 return CONSUMED_EVENT_TOKEN;
5906 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005907 }
Romain Guy06882f82009-06-10 13:36:04 -07005908
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005909 return focus;
Romain Guy06882f82009-06-10 13:36:04 -07005910
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005911 } else if (!isPointerEvent) {
5912 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1);
5913 if (!dispatch) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005914 Slog.w(TAG, "Event timeout during app switch: dropping trackball "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005915 + nextMotion);
5916 return SKIP_TARGET_TOKEN;
5917 }
Romain Guy06882f82009-06-10 13:36:04 -07005918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005919 WindowState focus = null;
5920 synchronized(mWindowMap) {
5921 focus = getFocusedWindowLocked();
5922 }
Romain Guy06882f82009-06-10 13:36:04 -07005923
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005924 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
5925 return focus;
5926 }
Romain Guy06882f82009-06-10 13:36:04 -07005927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005928 if (nextMotion == null) {
5929 return SKIP_TARGET_TOKEN;
5930 }
Romain Guy06882f82009-06-10 13:36:04 -07005931
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005932 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(
5933 KeyEvent.KEYCODE_UNKNOWN);
5934 if (!dispatch) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005935 Slog.w(TAG, "Event timeout during app switch: dropping pointer "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005936 + nextMotion);
5937 return SKIP_TARGET_TOKEN;
5938 }
Romain Guy06882f82009-06-10 13:36:04 -07005939
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005940 // Find the target window for a pointer event.
5941 int action = nextMotion.getAction();
5942 final float xf = nextMotion.getX();
5943 final float yf = nextMotion.getY();
5944 final long eventTime = nextMotion.getEventTime();
Romain Guy06882f82009-06-10 13:36:04 -07005945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005946 final boolean screenWasOff = qev != null
5947 && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
Romain Guy06882f82009-06-10 13:36:04 -07005948
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005949 WindowState target = null;
Romain Guy06882f82009-06-10 13:36:04 -07005950
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005951 synchronized(mWindowMap) {
5952 synchronized (this) {
5953 if (action == MotionEvent.ACTION_DOWN) {
5954 if (mMotionTarget != null) {
5955 // this is weird, we got a pen down, but we thought it was
5956 // already down!
5957 // XXX: We should probably send an ACTION_UP to the current
5958 // target.
Joe Onorato8a9b2202010-02-26 18:56:32 -08005959 Slog.w(TAG, "Pointer down received while already down in: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005960 + mMotionTarget);
5961 mMotionTarget = null;
5962 }
Romain Guy06882f82009-06-10 13:36:04 -07005963
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005964 // ACTION_DOWN is special, because we need to lock next events to
5965 // the window we'll land onto.
5966 final int x = (int)xf;
5967 final int y = (int)yf;
Romain Guy06882f82009-06-10 13:36:04 -07005968
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005969 final ArrayList windows = mWindows;
5970 final int N = windows.size();
5971 WindowState topErrWindow = null;
5972 final Rect tmpRect = mTempRect;
5973 for (int i=N-1; i>=0; i--) {
5974 WindowState child = (WindowState)windows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08005975 //Slog.i(TAG, "Checking dispatch to: " + child);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005976 final int flags = child.mAttrs.flags;
5977 if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
5978 if (topErrWindow == null) {
5979 topErrWindow = child;
5980 }
5981 }
5982 if (!child.isVisibleLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005983 //Slog.i(TAG, "Not visible!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005984 continue;
5985 }
5986 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08005987 //Slog.i(TAG, "Not touchable!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005988 if ((flags & WindowManager.LayoutParams
5989 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
5990 child.mNextOutsideTouch = mOutsideTouchTargets;
5991 mOutsideTouchTargets = child;
5992 }
5993 continue;
5994 }
5995 tmpRect.set(child.mFrame);
5996 if (child.mTouchableInsets == ViewTreeObserver
5997 .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
5998 // The touch is inside of the window if it is
5999 // inside the frame, AND the content part of that
6000 // frame that was given by the application.
6001 tmpRect.left += child.mGivenContentInsets.left;
6002 tmpRect.top += child.mGivenContentInsets.top;
6003 tmpRect.right -= child.mGivenContentInsets.right;
6004 tmpRect.bottom -= child.mGivenContentInsets.bottom;
6005 } else if (child.mTouchableInsets == ViewTreeObserver
6006 .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
6007 // The touch is inside of the window if it is
6008 // inside the frame, AND the visible part of that
6009 // frame that was given by the application.
6010 tmpRect.left += child.mGivenVisibleInsets.left;
6011 tmpRect.top += child.mGivenVisibleInsets.top;
6012 tmpRect.right -= child.mGivenVisibleInsets.right;
6013 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
6014 }
6015 final int touchFlags = flags &
6016 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
6017 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
6018 if (tmpRect.contains(x, y) || touchFlags == 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006019 //Slog.i(TAG, "Using this target!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006020 if (!screenWasOff || (flags &
6021 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
6022 mMotionTarget = child;
6023 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006024 //Slog.i(TAG, "Waking, skip!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 mMotionTarget = null;
6026 }
6027 break;
6028 }
Romain Guy06882f82009-06-10 13:36:04 -07006029
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006030 if ((flags & WindowManager.LayoutParams
6031 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
6032 child.mNextOutsideTouch = mOutsideTouchTargets;
6033 mOutsideTouchTargets = child;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006034 //Slog.i(TAG, "Adding to outside target list: " + child);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006035 }
6036 }
6037
6038 // if there's an error window but it's not accepting
6039 // focus (typically because it is not yet visible) just
6040 // wait for it -- any other focused window may in fact
6041 // be in ANR state.
6042 if (topErrWindow != null && mMotionTarget != topErrWindow) {
6043 mMotionTarget = null;
6044 }
6045 }
Romain Guy06882f82009-06-10 13:36:04 -07006046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006047 target = mMotionTarget;
6048 }
6049 }
Romain Guy06882f82009-06-10 13:36:04 -07006050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006051 wakeupIfNeeded(target, eventType(nextMotion));
Romain Guy06882f82009-06-10 13:36:04 -07006052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006053 // Pointer events are a little different -- if there isn't a
6054 // target found for any event, then just drop it.
6055 return target != null ? target : SKIP_TARGET_TOKEN;
6056 }
Romain Guy06882f82009-06-10 13:36:04 -07006057
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006058 boolean checkShouldDispatchKey(int keycode) {
6059 synchronized (this) {
6060 if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) {
6061 mTimeToSwitch = 0;
6062 return true;
6063 }
6064 if (mTimeToSwitch != 0
6065 && mTimeToSwitch < SystemClock.uptimeMillis()) {
6066 return false;
6067 }
6068 return true;
6069 }
6070 }
Romain Guy06882f82009-06-10 13:36:04 -07006071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006072 void bindTargetWindowLocked(WindowState win,
6073 int pendingWhat, QueuedEvent pendingMotion) {
6074 synchronized (this) {
6075 bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion);
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 synchronized (this) {
6081 bindTargetWindowLockedLocked(win, RETURN_NOTHING, null);
6082 }
6083 }
6084
6085 void bindTargetWindowLockedLocked(WindowState win,
6086 int pendingWhat, QueuedEvent pendingMotion) {
6087 mLastWin = win;
6088 mLastBinder = win.mClient.asBinder();
6089 mFinished = false;
6090 if (pendingMotion != null) {
6091 final Session s = win.mSession;
6092 if (pendingWhat == RETURN_PENDING_POINTER) {
6093 releasePendingPointerLocked(s);
6094 s.mPendingPointerMove = pendingMotion;
6095 s.mPendingPointerWindow = win;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006096 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006097 "bindTargetToWindow " + s.mPendingPointerMove);
6098 } else if (pendingWhat == RETURN_PENDING_TRACKBALL) {
6099 releasePendingTrackballLocked(s);
6100 s.mPendingTrackballMove = pendingMotion;
6101 s.mPendingTrackballWindow = win;
6102 }
6103 }
6104 }
Romain Guy06882f82009-06-10 13:36:04 -07006105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006106 void releasePendingPointerLocked(Session s) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006107 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006108 "releasePendingPointer " + s.mPendingPointerMove);
6109 if (s.mPendingPointerMove != null) {
6110 mQueue.recycleEvent(s.mPendingPointerMove);
6111 s.mPendingPointerMove = null;
6112 }
6113 }
Romain Guy06882f82009-06-10 13:36:04 -07006114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006115 void releasePendingTrackballLocked(Session s) {
6116 if (s.mPendingTrackballMove != null) {
6117 mQueue.recycleEvent(s.mPendingTrackballMove);
6118 s.mPendingTrackballMove = null;
6119 }
6120 }
Romain Guy06882f82009-06-10 13:36:04 -07006121
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006122 MotionEvent finishedKey(Session session, IWindow client, boolean force,
6123 int returnWhat) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006124 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006125 TAG, "finishedKey: client=" + client + ", force=" + force);
6126
6127 if (client == null) {
6128 return null;
6129 }
6130
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006131 MotionEvent res = null;
6132 QueuedEvent qev = null;
6133 WindowState win = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006134
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006135 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006136 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006137 TAG, "finishedKey: client=" + client.asBinder()
6138 + ", force=" + force + ", last=" + mLastBinder
6139 + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
6140
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006141 if (returnWhat == RETURN_PENDING_POINTER) {
6142 qev = session.mPendingPointerMove;
6143 win = session.mPendingPointerWindow;
6144 session.mPendingPointerMove = null;
6145 session.mPendingPointerWindow = null;
6146 } else if (returnWhat == RETURN_PENDING_TRACKBALL) {
6147 qev = session.mPendingTrackballMove;
6148 win = session.mPendingTrackballWindow;
6149 session.mPendingTrackballMove = null;
6150 session.mPendingTrackballWindow = null;
6151 }
Romain Guy06882f82009-06-10 13:36:04 -07006152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006153 if (mLastBinder == client.asBinder()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006154 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006155 TAG, "finishedKey: last paused="
6156 + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
6157 if (mLastWin != null && (!mLastWin.mToken.paused || force
6158 || !mEventDispatching)) {
Christopher Tate136b1f92010-02-11 17:51:24 -08006159 doFinishedKeyLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006160 } else {
6161 // Make sure to wake up anyone currently waiting to
6162 // dispatch a key, so they can re-evaluate their
6163 // current situation.
6164 mFinished = true;
6165 notifyAll();
6166 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006167 }
Romain Guy06882f82009-06-10 13:36:04 -07006168
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006169 if (qev != null) {
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006170 res = (MotionEvent)qev.event;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006171 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006172 "Returning pending motion: " + res);
6173 mQueue.recycleEvent(qev);
6174 if (win != null && returnWhat == RETURN_PENDING_POINTER) {
6175 res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
6176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006177 }
Christopher Tate2624fbc2009-12-11 12:11:31 -08006178 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006179
Christopher Tate2624fbc2009-12-11 12:11:31 -08006180 if (res != null && returnWhat == RETURN_PENDING_POINTER) {
6181 synchronized (mWindowMap) {
Dianne Hackborn90d2db32010-02-11 22:19:06 -08006182 dispatchPointerElsewhereLocked(win, win, res, res.getEventTime(), false);
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006183 }
6184 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006185
Dianne Hackborn8df8b2b2009-08-17 15:15:18 -07006186 return res;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006187 }
6188
6189 void tickle() {
6190 synchronized (this) {
6191 notifyAll();
6192 }
6193 }
Romain Guy06882f82009-06-10 13:36:04 -07006194
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006195 void handleNewWindowLocked(WindowState newWindow) {
6196 if (!newWindow.canReceiveKeys()) {
6197 return;
6198 }
6199 synchronized (this) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006200 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006201 TAG, "New key dispatch window: win="
6202 + newWindow.mClient.asBinder()
6203 + ", last=" + mLastBinder
6204 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6205 + "), finished=" + mFinished + ", paused="
6206 + newWindow.mToken.paused);
6207
6208 // Displaying a window implicitly causes dispatching to
6209 // be unpaused. (This is to protect against bugs if someone
6210 // pauses dispatching but forgets to resume.)
6211 newWindow.mToken.paused = false;
6212
6213 mGotFirstWindow = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006214
6215 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006216 if (DEBUG_INPUT) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006217 "New SYSTEM_ERROR window; resetting state");
6218 mLastWin = null;
6219 mLastBinder = null;
6220 mMotionTarget = null;
6221 mFinished = true;
6222 } else if (mLastWin != null) {
6223 // If the new window is above the window we are
6224 // waiting on, then stop waiting and let key dispatching
6225 // start on the new guy.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006226 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006227 TAG, "Last win layer=" + mLastWin.mLayer
6228 + ", new win layer=" + newWindow.mLayer);
6229 if (newWindow.mLayer >= mLastWin.mLayer) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006230 // The new window is above the old; finish pending input to the last
6231 // window and start directing it to the new one.
6232 mLastWin.mToken.paused = false;
Christopher Tate136b1f92010-02-11 17:51:24 -08006233 doFinishedKeyLocked(false); // does a notifyAll()
6234 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006235 }
6236 }
6237
The Android Open Source Projectc474dec2009-03-04 09:49:09 -08006238 // Now that we've put a new window state in place, make the event waiter
6239 // take notice and retarget its attentions.
6240 notifyAll();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006241 }
6242 }
6243
6244 void pauseDispatchingLocked(WindowToken token) {
6245 synchronized (this)
6246 {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006247 if (DEBUG_INPUT) Slog.v(TAG, "Pausing WindowToken " + token);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006248 token.paused = true;
6249
6250 /*
6251 if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) {
6252 mPaused = true;
6253 } else {
6254 if (mLastWin == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006255 Slog.i(TAG, "Key dispatching not paused: no last window.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006256 } else if (mFinished) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006257 Slog.i(TAG, "Key dispatching not paused: finished last key.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006258 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006259 Slog.i(TAG, "Key dispatching not paused: window in higher layer.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006260 }
6261 }
6262 */
6263 }
6264 }
6265
6266 void resumeDispatchingLocked(WindowToken token) {
6267 synchronized (this) {
6268 if (token.paused) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006269 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006270 TAG, "Resuming WindowToken " + token
6271 + ", last=" + mLastBinder
6272 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
6273 + "), finished=" + mFinished + ", paused="
6274 + token.paused);
6275 token.paused = false;
6276 if (mLastWin != null && mLastWin.mToken == token && mFinished) {
Christopher Tate136b1f92010-02-11 17:51:24 -08006277 doFinishedKeyLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006278 } else {
6279 notifyAll();
6280 }
6281 }
6282 }
6283 }
6284
6285 void setEventDispatchingLocked(boolean enabled) {
6286 synchronized (this) {
6287 mEventDispatching = enabled;
6288 notifyAll();
6289 }
6290 }
Romain Guy06882f82009-06-10 13:36:04 -07006291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006292 void appSwitchComing() {
6293 synchronized (this) {
6294 // Don't wait for more than .5 seconds for app to finish
6295 // processing the pending events.
6296 long now = SystemClock.uptimeMillis() + 500;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006297 if (DEBUG_INPUT) Slog.v(TAG, "appSwitchComing: " + now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006298 if (mTimeToSwitch == 0 || now < mTimeToSwitch) {
6299 mTimeToSwitch = now;
6300 }
6301 notifyAll();
6302 }
6303 }
Romain Guy06882f82009-06-10 13:36:04 -07006304
Christopher Tate136b1f92010-02-11 17:51:24 -08006305 private final void doFinishedKeyLocked(boolean force) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006306 if (mLastWin != null) {
6307 releasePendingPointerLocked(mLastWin.mSession);
6308 releasePendingTrackballLocked(mLastWin.mSession);
6309 }
Romain Guy06882f82009-06-10 13:36:04 -07006310
Christopher Tate136b1f92010-02-11 17:51:24 -08006311 if (force || mLastWin == null || !mLastWin.mToken.paused
6312 || !mLastWin.isVisibleLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006313 // If the current window has been paused, we aren't -really-
6314 // finished... so let the waiters still wait.
6315 mLastWin = null;
6316 mLastBinder = null;
6317 }
6318 mFinished = true;
6319 notifyAll();
6320 }
6321 }
6322
6323 private class KeyQ extends KeyInputQueue
6324 implements KeyInputQueue.FilterCallback {
6325 PowerManager.WakeLock mHoldingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07006326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006327 KeyQ() {
Dianne Hackbornddca3ee2009-07-23 19:01:31 -07006328 super(mContext, WindowManagerService.this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
6330 mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
6331 "KEEP_SCREEN_ON_FLAG");
6332 mHoldingScreen.setReferenceCounted(false);
6333 }
6334
6335 @Override
6336 boolean preprocessEvent(InputDevice device, RawInputEvent event) {
6337 if (mPolicy.preprocessInputEventTq(event)) {
6338 return true;
6339 }
Romain Guy06882f82009-06-10 13:36:04 -07006340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006341 switch (event.type) {
6342 case RawInputEvent.EV_KEY: {
6343 // XXX begin hack
6344 if (DEBUG) {
6345 if (event.keycode == KeyEvent.KEYCODE_G) {
6346 if (event.value != 0) {
6347 // G down
6348 mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
6349 }
6350 return false;
6351 }
6352 if (event.keycode == KeyEvent.KEYCODE_D) {
6353 if (event.value != 0) {
6354 //dump();
6355 }
6356 return false;
6357 }
6358 }
6359 // XXX end hack
Romain Guy06882f82009-06-10 13:36:04 -07006360
Charles Mendis322591c2009-10-29 11:06:59 -07006361 boolean screenIsOff = !mPowerManager.isScreenOn();
6362 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006363 int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
Romain Guy06882f82009-06-10 13:36:04 -07006364
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006365 if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) {
6366 mPowerManager.goToSleep(event.when);
6367 }
6368
6369 if (screenIsOff) {
6370 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6371 }
6372 if (screenIsDim) {
6373 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6374 }
6375 if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
6376 mPowerManager.userActivity(event.when, false,
Michael Chane96440f2009-05-06 10:27:36 -07006377 LocalPowerManager.BUTTON_EVENT, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006378 }
Romain Guy06882f82009-06-10 13:36:04 -07006379
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006380 if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
6381 if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) {
6382 filterQueue(this);
6383 mKeyWaiter.appSwitchComing();
6384 }
6385 return true;
6386 } else {
6387 return false;
6388 }
6389 }
Romain Guy06882f82009-06-10 13:36:04 -07006390
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006391 case RawInputEvent.EV_REL: {
Charles Mendis322591c2009-10-29 11:06:59 -07006392 boolean screenIsOff = !mPowerManager.isScreenOn();
6393 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006394 if (screenIsOff) {
6395 if (!mPolicy.isWakeRelMovementTq(event.deviceId,
6396 device.classes, event)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006397 //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006398 return false;
6399 }
6400 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6401 }
6402 if (screenIsDim) {
6403 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6404 }
6405 return true;
6406 }
Romain Guy06882f82009-06-10 13:36:04 -07006407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006408 case RawInputEvent.EV_ABS: {
Charles Mendis322591c2009-10-29 11:06:59 -07006409 boolean screenIsOff = !mPowerManager.isScreenOn();
6410 boolean screenIsDim = !mPowerManager.isScreenBright();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006411 if (screenIsOff) {
6412 if (!mPolicy.isWakeAbsMovementTq(event.deviceId,
6413 device.classes, event)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006414 //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006415 return false;
6416 }
6417 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
6418 }
6419 if (screenIsDim) {
6420 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
6421 }
6422 return true;
6423 }
Romain Guy06882f82009-06-10 13:36:04 -07006424
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006425 default:
6426 return true;
6427 }
6428 }
6429
6430 public int filterEvent(QueuedEvent ev) {
6431 switch (ev.classType) {
6432 case RawInputEvent.CLASS_KEYBOARD:
6433 KeyEvent ke = (KeyEvent)ev.event;
6434 if (mPolicy.isMovementKeyTi(ke.getKeyCode())) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006435 Slog.w(TAG, "Dropping movement key during app switch: "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006436 + ke.getKeyCode() + ", action=" + ke.getAction());
6437 return FILTER_REMOVE;
6438 }
6439 return FILTER_ABORT;
6440 default:
6441 return FILTER_KEEP;
6442 }
6443 }
Romain Guy06882f82009-06-10 13:36:04 -07006444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006445 /**
6446 * Must be called with the main window manager lock held.
6447 */
6448 void setHoldScreenLocked(boolean holding) {
6449 boolean state = mHoldingScreen.isHeld();
6450 if (holding != state) {
6451 if (holding) {
6452 mHoldingScreen.acquire();
6453 } else {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07006454 mPolicy.screenOnStoppedLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006455 mHoldingScreen.release();
6456 }
6457 }
6458 }
Michael Chan53071d62009-05-13 17:29:48 -07006459 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006460
6461 public boolean detectSafeMode() {
6462 mSafeMode = mPolicy.detectSafeMode();
6463 return mSafeMode;
6464 }
Romain Guy06882f82009-06-10 13:36:04 -07006465
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006466 public void systemReady() {
6467 mPolicy.systemReady();
6468 }
Romain Guy06882f82009-06-10 13:36:04 -07006469
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006470 private final class InputDispatcherThread extends Thread {
6471 // Time to wait when there is nothing to do: 9999 seconds.
6472 static final int LONG_WAIT=9999*1000;
6473
6474 public InputDispatcherThread() {
6475 super("InputDispatcher");
6476 }
Romain Guy06882f82009-06-10 13:36:04 -07006477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006478 @Override
6479 public void run() {
6480 while (true) {
6481 try {
6482 process();
6483 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006484 Slog.e(TAG, "Exception in input dispatcher", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006485 }
6486 }
6487 }
Romain Guy06882f82009-06-10 13:36:04 -07006488
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006489 private void process() {
6490 android.os.Process.setThreadPriority(
6491 android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
Romain Guy06882f82009-06-10 13:36:04 -07006492
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006493 // The last key event we saw
6494 KeyEvent lastKey = null;
6495
6496 // Last keydown time for auto-repeating keys
6497 long lastKeyTime = SystemClock.uptimeMillis();
6498 long nextKeyTime = lastKeyTime+LONG_WAIT;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006499 long downTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006500
Romain Guy06882f82009-06-10 13:36:04 -07006501 // How many successive repeats we generated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006502 int keyRepeatCount = 0;
6503
6504 // Need to report that configuration has changed?
6505 boolean configChanged = false;
Romain Guy06882f82009-06-10 13:36:04 -07006506
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006507 while (true) {
6508 long curTime = SystemClock.uptimeMillis();
6509
Joe Onorato8a9b2202010-02-26 18:56:32 -08006510 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006511 TAG, "Waiting for next key: now=" + curTime
6512 + ", repeat @ " + nextKeyTime);
6513
6514 // Retrieve next event, waiting only as long as the next
6515 // repeat timeout. If the configuration has changed, then
6516 // don't wait at all -- we'll report the change as soon as
6517 // we have processed all events.
6518 QueuedEvent ev = mQueue.getEvent(
6519 (int)((!configChanged && curTime < nextKeyTime)
6520 ? (nextKeyTime-curTime) : 0));
6521
Joe Onorato8a9b2202010-02-26 18:56:32 -08006522 if (DEBUG_INPUT && ev != null) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006523 TAG, "Event: type=" + ev.classType + " data=" + ev.event);
6524
Michael Chan53071d62009-05-13 17:29:48 -07006525 if (MEASURE_LATENCY) {
6526 lt.sample("2 got event ", System.nanoTime() - ev.whenNano);
6527 }
6528
Mike Lockwood3d0ea722009-10-21 22:58:29 -04006529 if (lastKey != null && !mPolicy.allowKeyRepeat()) {
6530 // cancel key repeat at the request of the policy.
6531 lastKey = null;
6532 downTime = 0;
6533 lastKeyTime = curTime;
6534 nextKeyTime = curTime + LONG_WAIT;
6535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006536 try {
6537 if (ev != null) {
Michael Chan53071d62009-05-13 17:29:48 -07006538 curTime = SystemClock.uptimeMillis();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006539 int eventType;
6540 if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
6541 eventType = eventType((MotionEvent)ev.event);
6542 } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
6543 ev.classType == RawInputEvent.CLASS_TRACKBALL) {
6544 eventType = LocalPowerManager.BUTTON_EVENT;
6545 } else {
6546 eventType = LocalPowerManager.OTHER_EVENT;
6547 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07006548 try {
Michael Chan53071d62009-05-13 17:29:48 -07006549 if ((curTime - mLastBatteryStatsCallTime)
Michael Chane96440f2009-05-06 10:27:36 -07006550 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
Michael Chan53071d62009-05-13 17:29:48 -07006551 mLastBatteryStatsCallTime = curTime;
Michael Chane96440f2009-05-06 10:27:36 -07006552 mBatteryStats.noteInputEvent();
6553 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07006554 } catch (RemoteException e) {
6555 // Ignore
6556 }
Michael Chane10de972009-05-18 11:24:50 -07006557
Mike Lockwood5db42402009-11-30 14:51:51 -05006558 if (ev.classType == RawInputEvent.CLASS_CONFIGURATION_CHANGED) {
6559 // do not wake screen in this case
6560 } else if (eventType != TOUCH_EVENT
Michael Chane10de972009-05-18 11:24:50 -07006561 && eventType != LONG_TOUCH_EVENT
6562 && eventType != CHEEK_EVENT) {
6563 mPowerManager.userActivity(curTime, false,
6564 eventType, false);
6565 } else if (mLastTouchEventType != eventType
6566 || (curTime - mLastUserActivityCallTime)
6567 >= MIN_TIME_BETWEEN_USERACTIVITIES) {
6568 mLastUserActivityCallTime = curTime;
6569 mLastTouchEventType = eventType;
6570 mPowerManager.userActivity(curTime, false,
6571 eventType, false);
6572 }
6573
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006574 switch (ev.classType) {
6575 case RawInputEvent.CLASS_KEYBOARD:
6576 KeyEvent ke = (KeyEvent)ev.event;
6577 if (ke.isDown()) {
6578 lastKey = ke;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006579 downTime = curTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006580 keyRepeatCount = 0;
6581 lastKeyTime = curTime;
6582 nextKeyTime = lastKeyTime
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006583 + ViewConfiguration.getLongPressTimeout();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006584 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006585 TAG, "Received key down: first repeat @ "
6586 + nextKeyTime);
6587 } else {
6588 lastKey = null;
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006589 downTime = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006590 // Arbitrary long timeout.
6591 lastKeyTime = curTime;
6592 nextKeyTime = curTime + LONG_WAIT;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006593 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006594 TAG, "Received key up: ignore repeat @ "
6595 + nextKeyTime);
6596 }
6597 dispatchKey((KeyEvent)ev.event, 0, 0);
6598 mQueue.recycleEvent(ev);
6599 break;
6600 case RawInputEvent.CLASS_TOUCHSCREEN:
Joe Onorato8a9b2202010-02-26 18:56:32 -08006601 //Slog.i(TAG, "Read next event " + ev);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006602 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
6603 break;
6604 case RawInputEvent.CLASS_TRACKBALL:
6605 dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
6606 break;
6607 case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
6608 configChanged = true;
6609 break;
6610 default:
6611 mQueue.recycleEvent(ev);
6612 break;
6613 }
Romain Guy06882f82009-06-10 13:36:04 -07006614
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006615 } else if (configChanged) {
6616 configChanged = false;
6617 sendNewConfiguration();
Romain Guy06882f82009-06-10 13:36:04 -07006618
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006619 } else if (lastKey != null) {
6620 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07006621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006622 // Timeout occurred while key was down. If it is at or
6623 // past the key repeat time, dispatch the repeat.
Joe Onorato8a9b2202010-02-26 18:56:32 -08006624 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006625 TAG, "Key timeout: repeat=" + nextKeyTime
6626 + ", now=" + curTime);
6627 if (curTime < nextKeyTime) {
6628 continue;
6629 }
Romain Guy06882f82009-06-10 13:36:04 -07006630
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006631 lastKeyTime = nextKeyTime;
6632 nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY;
6633 keyRepeatCount++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08006634 if (DEBUG_INPUT) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006635 TAG, "Key repeat: count=" + keyRepeatCount
6636 + ", next @ " + nextKeyTime);
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006637 KeyEvent newEvent;
6638 if (downTime != 0 && (downTime
6639 + ViewConfiguration.getLongPressTimeout())
6640 <= curTime) {
6641 newEvent = KeyEvent.changeTimeRepeat(lastKey,
6642 curTime, keyRepeatCount,
6643 lastKey.getFlags() | KeyEvent.FLAG_LONG_PRESS);
6644 downTime = 0;
6645 } else {
6646 newEvent = KeyEvent.changeTimeRepeat(lastKey,
6647 curTime, keyRepeatCount);
6648 }
6649 dispatchKey(newEvent, 0, 0);
Romain Guy06882f82009-06-10 13:36:04 -07006650
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006651 } else {
6652 curTime = SystemClock.uptimeMillis();
Romain Guy06882f82009-06-10 13:36:04 -07006653
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006654 lastKeyTime = curTime;
6655 nextKeyTime = curTime + LONG_WAIT;
6656 }
Romain Guy06882f82009-06-10 13:36:04 -07006657
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006658 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006659 Slog.e(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006660 "Input thread received uncaught exception: " + e, e);
6661 }
6662 }
6663 }
6664 }
6665
6666 // -------------------------------------------------------------
6667 // Client Session State
6668 // -------------------------------------------------------------
6669
6670 private final class Session extends IWindowSession.Stub
6671 implements IBinder.DeathRecipient {
6672 final IInputMethodClient mClient;
6673 final IInputContext mInputContext;
6674 final int mUid;
6675 final int mPid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006676 final String mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006677 SurfaceSession mSurfaceSession;
6678 int mNumWindow = 0;
6679 boolean mClientDead = false;
Romain Guy06882f82009-06-10 13:36:04 -07006680
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006681 /**
6682 * Current pointer move event being dispatched to client window... must
6683 * hold key lock to access.
6684 */
6685 QueuedEvent mPendingPointerMove;
6686 WindowState mPendingPointerWindow;
Romain Guy06882f82009-06-10 13:36:04 -07006687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006688 /**
6689 * Current trackball move event being dispatched to client window... must
6690 * hold key lock to access.
6691 */
6692 QueuedEvent mPendingTrackballMove;
6693 WindowState mPendingTrackballWindow;
6694
6695 public Session(IInputMethodClient client, IInputContext inputContext) {
6696 mClient = client;
6697 mInputContext = inputContext;
6698 mUid = Binder.getCallingUid();
6699 mPid = Binder.getCallingPid();
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006700 StringBuilder sb = new StringBuilder();
6701 sb.append("Session{");
6702 sb.append(Integer.toHexString(System.identityHashCode(this)));
6703 sb.append(" uid ");
6704 sb.append(mUid);
6705 sb.append("}");
6706 mStringName = sb.toString();
Romain Guy06882f82009-06-10 13:36:04 -07006707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006708 synchronized (mWindowMap) {
6709 if (mInputMethodManager == null && mHaveInputMethods) {
6710 IBinder b = ServiceManager.getService(
6711 Context.INPUT_METHOD_SERVICE);
6712 mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
6713 }
6714 }
6715 long ident = Binder.clearCallingIdentity();
6716 try {
6717 // Note: it is safe to call in to the input method manager
6718 // here because we are not holding our lock.
6719 if (mInputMethodManager != null) {
6720 mInputMethodManager.addClient(client, inputContext,
6721 mUid, mPid);
6722 } else {
6723 client.setUsingInputMethod(false);
6724 }
6725 client.asBinder().linkToDeath(this, 0);
6726 } catch (RemoteException e) {
6727 // The caller has died, so we can just forget about this.
6728 try {
6729 if (mInputMethodManager != null) {
6730 mInputMethodManager.removeClient(client);
6731 }
6732 } catch (RemoteException ee) {
6733 }
6734 } finally {
6735 Binder.restoreCallingIdentity(ident);
6736 }
6737 }
Romain Guy06882f82009-06-10 13:36:04 -07006738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006739 @Override
6740 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
6741 throws RemoteException {
6742 try {
6743 return super.onTransact(code, data, reply, flags);
6744 } catch (RuntimeException e) {
6745 // Log all 'real' exceptions thrown to the caller
6746 if (!(e instanceof SecurityException)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006747 Slog.e(TAG, "Window Session Crash", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006748 }
6749 throw e;
6750 }
6751 }
6752
6753 public void binderDied() {
6754 // Note: it is safe to call in to the input method manager
6755 // here because we are not holding our lock.
6756 try {
6757 if (mInputMethodManager != null) {
6758 mInputMethodManager.removeClient(mClient);
6759 }
6760 } catch (RemoteException e) {
6761 }
6762 synchronized(mWindowMap) {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -07006763 mClient.asBinder().unlinkToDeath(this, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006764 mClientDead = true;
6765 killSessionLocked();
6766 }
6767 }
6768
6769 public int add(IWindow window, WindowManager.LayoutParams attrs,
6770 int viewVisibility, Rect outContentInsets) {
6771 return addWindow(this, window, attrs, viewVisibility, outContentInsets);
6772 }
Romain Guy06882f82009-06-10 13:36:04 -07006773
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006774 public void remove(IWindow window) {
6775 removeWindow(this, window);
6776 }
Romain Guy06882f82009-06-10 13:36:04 -07006777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006778 public int relayout(IWindow window, WindowManager.LayoutParams attrs,
6779 int requestedWidth, int requestedHeight, int viewFlags,
6780 boolean insetsPending, Rect outFrame, Rect outContentInsets,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07006781 Rect outVisibleInsets, Configuration outConfig, Surface outSurface) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006782 return relayoutWindow(this, window, attrs,
6783 requestedWidth, requestedHeight, viewFlags, insetsPending,
Dianne Hackborn694f79b2010-03-17 19:44:59 -07006784 outFrame, outContentInsets, outVisibleInsets, outConfig, outSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006785 }
Romain Guy06882f82009-06-10 13:36:04 -07006786
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006787 public void setTransparentRegion(IWindow window, Region region) {
6788 setTransparentRegionWindow(this, window, region);
6789 }
Romain Guy06882f82009-06-10 13:36:04 -07006790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006791 public void setInsets(IWindow window, int touchableInsets,
6792 Rect contentInsets, Rect visibleInsets) {
6793 setInsetsWindow(this, window, touchableInsets, contentInsets,
6794 visibleInsets);
6795 }
Romain Guy06882f82009-06-10 13:36:04 -07006796
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006797 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
6798 getWindowDisplayFrame(this, window, outDisplayFrame);
6799 }
Romain Guy06882f82009-06-10 13:36:04 -07006800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006801 public void finishDrawing(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006802 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006803 TAG, "IWindow finishDrawing called for " + window);
6804 finishDrawingWindow(this, window);
6805 }
6806
6807 public void finishKey(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006808 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006809 TAG, "IWindow finishKey called for " + window);
6810 mKeyWaiter.finishedKey(this, window, false,
6811 KeyWaiter.RETURN_NOTHING);
6812 }
6813
6814 public MotionEvent getPendingPointerMove(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006815 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006816 TAG, "IWindow getPendingMotionEvent called for " + window);
6817 return mKeyWaiter.finishedKey(this, window, false,
6818 KeyWaiter.RETURN_PENDING_POINTER);
6819 }
Romain Guy06882f82009-06-10 13:36:04 -07006820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006821 public MotionEvent getPendingTrackballMove(IWindow window) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006822 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006823 TAG, "IWindow getPendingMotionEvent called for " + window);
6824 return mKeyWaiter.finishedKey(this, window, false,
6825 KeyWaiter.RETURN_PENDING_TRACKBALL);
6826 }
6827
6828 public void setInTouchMode(boolean mode) {
6829 synchronized(mWindowMap) {
6830 mInTouchMode = mode;
6831 }
6832 }
6833
6834 public boolean getInTouchMode() {
6835 synchronized(mWindowMap) {
6836 return mInTouchMode;
6837 }
6838 }
6839
6840 public boolean performHapticFeedback(IWindow window, int effectId,
6841 boolean always) {
6842 synchronized(mWindowMap) {
6843 long ident = Binder.clearCallingIdentity();
6844 try {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07006845 return mPolicy.performHapticFeedbackLw(
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006846 windowForClientLocked(this, window, true),
6847 effectId, always);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006848 } finally {
6849 Binder.restoreCallingIdentity(ident);
6850 }
6851 }
6852 }
Romain Guy06882f82009-06-10 13:36:04 -07006853
Marco Nelissenbf6956b2009-11-09 15:21:13 -08006854 public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006855 synchronized(mWindowMap) {
6856 long ident = Binder.clearCallingIdentity();
6857 try {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006858 setWindowWallpaperPositionLocked(
6859 windowForClientLocked(this, window, true),
Marco Nelissenbf6956b2009-11-09 15:21:13 -08006860 x, y, xStep, yStep);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07006861 } finally {
6862 Binder.restoreCallingIdentity(ident);
6863 }
6864 }
6865 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006866
Dianne Hackborn19382ac2009-09-11 21:13:37 -07006867 public void wallpaperOffsetsComplete(IBinder window) {
6868 WindowManagerService.this.wallpaperOffsetsComplete(window);
6869 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006870
Dianne Hackborn75804932009-10-20 20:15:20 -07006871 public Bundle sendWallpaperCommand(IBinder window, String action, int x, int y,
6872 int z, Bundle extras, boolean sync) {
6873 synchronized(mWindowMap) {
6874 long ident = Binder.clearCallingIdentity();
6875 try {
6876 return sendWindowWallpaperCommandLocked(
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006877 windowForClientLocked(this, window, true),
Dianne Hackborn75804932009-10-20 20:15:20 -07006878 action, x, y, z, extras, sync);
6879 } finally {
6880 Binder.restoreCallingIdentity(ident);
6881 }
6882 }
6883 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006884
Dianne Hackborn75804932009-10-20 20:15:20 -07006885 public void wallpaperCommandComplete(IBinder window, Bundle result) {
6886 WindowManagerService.this.wallpaperCommandComplete(window, result);
6887 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08006888
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006889 void windowAddedLocked() {
6890 if (mSurfaceSession == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006891 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006892 TAG, "First window added to " + this + ", creating SurfaceSession");
6893 mSurfaceSession = new SurfaceSession();
Joe Onorato8a9b2202010-02-26 18:56:32 -08006894 if (SHOW_TRANSACTIONS) Slog.i(
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07006895 TAG, " NEW SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006896 mSessions.add(this);
6897 }
6898 mNumWindow++;
6899 }
6900
6901 void windowRemovedLocked() {
6902 mNumWindow--;
6903 killSessionLocked();
6904 }
Romain Guy06882f82009-06-10 13:36:04 -07006905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006906 void killSessionLocked() {
6907 if (mNumWindow <= 0 && mClientDead) {
6908 mSessions.remove(this);
6909 if (mSurfaceSession != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006910 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006911 TAG, "Last window removed from " + this
6912 + ", destroying " + mSurfaceSession);
Joe Onorato8a9b2202010-02-26 18:56:32 -08006913 if (SHOW_TRANSACTIONS) Slog.i(
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07006914 TAG, " KILL SURFACE SESSION " + mSurfaceSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006915 try {
6916 mSurfaceSession.kill();
6917 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08006918 Slog.w(TAG, "Exception thrown when killing surface session "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006919 + mSurfaceSession + " in session " + this
6920 + ": " + e.toString());
6921 }
6922 mSurfaceSession = null;
6923 }
6924 }
6925 }
Romain Guy06882f82009-06-10 13:36:04 -07006926
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006927 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006928 pw.print(prefix); pw.print("mNumWindow="); pw.print(mNumWindow);
6929 pw.print(" mClientDead="); pw.print(mClientDead);
6930 pw.print(" mSurfaceSession="); pw.println(mSurfaceSession);
6931 if (mPendingPointerWindow != null || mPendingPointerMove != null) {
6932 pw.print(prefix);
6933 pw.print("mPendingPointerWindow="); pw.print(mPendingPointerWindow);
6934 pw.print(" mPendingPointerMove="); pw.println(mPendingPointerMove);
6935 }
6936 if (mPendingTrackballWindow != null || mPendingTrackballMove != null) {
6937 pw.print(prefix);
6938 pw.print("mPendingTrackballWindow="); pw.print(mPendingTrackballWindow);
6939 pw.print(" mPendingTrackballMove="); pw.println(mPendingTrackballMove);
6940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006941 }
6942
6943 @Override
6944 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07006945 return mStringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006946 }
6947 }
6948
6949 // -------------------------------------------------------------
6950 // Client Window State
6951 // -------------------------------------------------------------
6952
6953 private final class WindowState implements WindowManagerPolicy.WindowState {
6954 final Session mSession;
6955 final IWindow mClient;
6956 WindowToken mToken;
The Android Open Source Project10592532009-03-18 17:39:46 -07006957 WindowToken mRootToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006958 AppWindowToken mAppToken;
6959 AppWindowToken mTargetAppToken;
6960 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
6961 final DeathRecipient mDeathRecipient;
6962 final WindowState mAttachedWindow;
6963 final ArrayList mChildWindows = new ArrayList();
6964 final int mBaseLayer;
6965 final int mSubLayer;
6966 final boolean mLayoutAttached;
6967 final boolean mIsImWindow;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07006968 final boolean mIsWallpaper;
6969 final boolean mIsFloatingLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006970 int mViewVisibility;
6971 boolean mPolicyVisibility = true;
6972 boolean mPolicyVisibilityAfterAnim = true;
6973 boolean mAppFreezing;
6974 Surface mSurface;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07006975 boolean mReportDestroySurface;
6976 boolean mSurfacePendingDestroy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006977 boolean mAttachedHidden; // is our parent window hidden?
6978 boolean mLastHidden; // was this window last hidden?
Dianne Hackborn759a39e2009-08-09 17:20:27 -07006979 boolean mWallpaperVisible; // for wallpaper, what was last vis report?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006980 int mRequestedWidth;
6981 int mRequestedHeight;
6982 int mLastRequestedWidth;
6983 int mLastRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006984 int mLayer;
6985 int mAnimLayer;
6986 int mLastLayer;
6987 boolean mHaveFrame;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07006988 boolean mObscured;
Dianne Hackborn93e462b2009-09-15 22:50:40 -07006989 boolean mTurnOnScreen;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006990
6991 WindowState mNextOutsideTouch;
Romain Guy06882f82009-06-10 13:36:04 -07006992
Dianne Hackborne36d6e22010-02-17 19:46:25 -08006993 int mLayoutSeq = -1;
6994
6995 Configuration mConfiguration = null;
6996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006997 // Actual frame shown on-screen (may be modified by animation)
6998 final Rect mShownFrame = new Rect();
6999 final Rect mLastShownFrame = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007001 /**
Dianne Hackbornac3587d2010-03-11 11:12:11 -08007002 * Set when we have changed the size of the surface, to know that
7003 * we must tell them application to resize (and thus redraw itself).
7004 */
7005 boolean mSurfaceResized;
7006
7007 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007008 * Insets that determine the actually visible area
7009 */
7010 final Rect mVisibleInsets = new Rect();
7011 final Rect mLastVisibleInsets = new Rect();
7012 boolean mVisibleInsetsChanged;
7013
7014 /**
7015 * Insets that are covered by system windows
7016 */
7017 final Rect mContentInsets = new Rect();
7018 final Rect mLastContentInsets = new Rect();
7019 boolean mContentInsetsChanged;
7020
7021 /**
7022 * Set to true if we are waiting for this window to receive its
7023 * given internal insets before laying out other windows based on it.
7024 */
7025 boolean mGivenInsetsPending;
Romain Guy06882f82009-06-10 13:36:04 -07007026
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007027 /**
7028 * These are the content insets that were given during layout for
7029 * this window, to be applied to windows behind it.
7030 */
7031 final Rect mGivenContentInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007033 /**
7034 * These are the visible insets that were given during layout for
7035 * this window, to be applied to windows behind it.
7036 */
7037 final Rect mGivenVisibleInsets = new Rect();
Romain Guy06882f82009-06-10 13:36:04 -07007038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007039 /**
7040 * Flag indicating whether the touchable region should be adjusted by
7041 * the visible insets; if false the area outside the visible insets is
7042 * NOT touchable, so we must use those to adjust the frame during hit
7043 * tests.
7044 */
7045 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
Romain Guy06882f82009-06-10 13:36:04 -07007046
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007047 // Current transformation being applied.
7048 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
7049 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
7050 float mHScale=1, mVScale=1;
7051 float mLastHScale=1, mLastVScale=1;
7052 final Matrix mTmpMatrix = new Matrix();
7053
7054 // "Real" frame that the application sees.
7055 final Rect mFrame = new Rect();
7056 final Rect mLastFrame = new Rect();
7057
7058 final Rect mContainingFrame = new Rect();
7059 final Rect mDisplayFrame = new Rect();
7060 final Rect mContentFrame = new Rect();
7061 final Rect mVisibleFrame = new Rect();
7062
7063 float mShownAlpha = 1;
7064 float mAlpha = 1;
7065 float mLastAlpha = 1;
7066
7067 // Set to true if, when the window gets displayed, it should perform
7068 // an enter animation.
7069 boolean mEnterAnimationPending;
7070
7071 // Currently running animation.
7072 boolean mAnimating;
7073 boolean mLocalAnimating;
7074 Animation mAnimation;
7075 boolean mAnimationIsEntrance;
7076 boolean mHasTransformation;
7077 boolean mHasLocalTransformation;
7078 final Transformation mTransformation = new Transformation();
7079
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007080 // If a window showing a wallpaper: the requested offset for the
7081 // wallpaper; if a wallpaper window: the currently applied offset.
7082 float mWallpaperX = -1;
7083 float mWallpaperY = -1;
Marco Nelissenbf6956b2009-11-09 15:21:13 -08007084
7085 // If a window showing a wallpaper: what fraction of the offset
7086 // range corresponds to a full virtual screen.
7087 float mWallpaperXStep = -1;
7088 float mWallpaperYStep = -1;
7089
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07007090 // Wallpaper windows: pixels offset based on above variables.
7091 int mXOffset;
7092 int mYOffset;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007093
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007094 // This is set after IWindowSession.relayout() has been called at
7095 // least once for the window. It allows us to detect the situation
7096 // where we don't yet have a surface, but should have one soon, so
7097 // we can give the window focus before waiting for the relayout.
7098 boolean mRelayoutCalled;
Romain Guy06882f82009-06-10 13:36:04 -07007099
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007100 // This is set after the Surface has been created but before the
7101 // window has been drawn. During this time the surface is hidden.
7102 boolean mDrawPending;
7103
7104 // This is set after the window has finished drawing for the first
7105 // time but before its surface is shown. The surface will be
7106 // displayed when the next layout is run.
7107 boolean mCommitDrawPending;
7108
7109 // This is set during the time after the window's drawing has been
7110 // committed, and before its surface is actually shown. It is used
7111 // to delay showing the surface until all windows in a token are ready
7112 // to be shown.
7113 boolean mReadyToShow;
Romain Guy06882f82009-06-10 13:36:04 -07007114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007115 // Set when the window has been shown in the screen the first time.
7116 boolean mHasDrawn;
7117
7118 // Currently running an exit animation?
7119 boolean mExiting;
7120
7121 // Currently on the mDestroySurface list?
7122 boolean mDestroying;
Romain Guy06882f82009-06-10 13:36:04 -07007123
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007124 // Completely remove from window manager after exit animation?
7125 boolean mRemoveOnExit;
7126
7127 // Set when the orientation is changing and this window has not yet
7128 // been updated for the new orientation.
7129 boolean mOrientationChanging;
Romain Guy06882f82009-06-10 13:36:04 -07007130
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007131 // Is this window now (or just being) removed?
7132 boolean mRemoved;
Romain Guy06882f82009-06-10 13:36:04 -07007133
Dianne Hackborn16064f92010-03-25 00:47:24 -07007134 // For debugging, this is the last information given to the surface flinger.
7135 boolean mSurfaceShown;
7136 int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
7137 int mSurfaceLayer;
7138 float mSurfaceAlpha;
7139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007140 WindowState(Session s, IWindow c, WindowToken token,
7141 WindowState attachedWindow, WindowManager.LayoutParams a,
7142 int viewVisibility) {
7143 mSession = s;
7144 mClient = c;
7145 mToken = token;
7146 mAttrs.copyFrom(a);
7147 mViewVisibility = viewVisibility;
7148 DeathRecipient deathRecipient = new DeathRecipient();
7149 mAlpha = a.alpha;
Joe Onorato8a9b2202010-02-26 18:56:32 -08007150 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007151 TAG, "Window " + this + " client=" + c.asBinder()
7152 + " token=" + token + " (" + mAttrs.token + ")");
7153 try {
7154 c.asBinder().linkToDeath(deathRecipient, 0);
7155 } catch (RemoteException e) {
7156 mDeathRecipient = null;
7157 mAttachedWindow = null;
7158 mLayoutAttached = false;
7159 mIsImWindow = false;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007160 mIsWallpaper = false;
7161 mIsFloatingLayer = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007162 mBaseLayer = 0;
7163 mSubLayer = 0;
7164 return;
7165 }
7166 mDeathRecipient = deathRecipient;
Romain Guy06882f82009-06-10 13:36:04 -07007167
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007168 if ((mAttrs.type >= FIRST_SUB_WINDOW &&
7169 mAttrs.type <= LAST_SUB_WINDOW)) {
7170 // The multiplier here is to reserve space for multiple
7171 // windows in the same type layer.
7172 mBaseLayer = mPolicy.windowTypeToLayerLw(
7173 attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
7174 + TYPE_LAYER_OFFSET;
7175 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
7176 mAttachedWindow = attachedWindow;
7177 mAttachedWindow.mChildWindows.add(this);
7178 mLayoutAttached = mAttrs.type !=
7179 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
7180 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
7181 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007182 mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
7183 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007184 } else {
7185 // The multiplier here is to reserve space for multiple
7186 // windows in the same type layer.
7187 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
7188 * TYPE_LAYER_MULTIPLIER
7189 + TYPE_LAYER_OFFSET;
7190 mSubLayer = 0;
7191 mAttachedWindow = null;
7192 mLayoutAttached = false;
7193 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
7194 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07007195 mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
7196 mIsFloatingLayer = mIsImWindow || mIsWallpaper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007197 }
7198
7199 WindowState appWin = this;
7200 while (appWin.mAttachedWindow != null) {
7201 appWin = mAttachedWindow;
7202 }
7203 WindowToken appToken = appWin.mToken;
7204 while (appToken.appWindowToken == null) {
7205 WindowToken parent = mTokenMap.get(appToken.token);
7206 if (parent == null || appToken == parent) {
7207 break;
7208 }
7209 appToken = parent;
7210 }
The Android Open Source Project10592532009-03-18 17:39:46 -07007211 mRootToken = appToken;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007212 mAppToken = appToken.appWindowToken;
7213
7214 mSurface = null;
7215 mRequestedWidth = 0;
7216 mRequestedHeight = 0;
7217 mLastRequestedWidth = 0;
7218 mLastRequestedHeight = 0;
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007219 mXOffset = 0;
7220 mYOffset = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007221 mLayer = 0;
7222 mAnimLayer = 0;
7223 mLastLayer = 0;
7224 }
7225
7226 void attach() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007227 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007228 TAG, "Attaching " + this + " token=" + mToken
7229 + ", list=" + mToken.windows);
7230 mSession.windowAddedLocked();
7231 }
7232
7233 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
7234 mHaveFrame = true;
7235
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007236 final Rect container = mContainingFrame;
7237 container.set(pf);
7238
7239 final Rect display = mDisplayFrame;
7240 display.set(df);
7241
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07007242 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007243 container.intersect(mCompatibleScreenFrame);
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07007244 if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
7245 display.intersect(mCompatibleScreenFrame);
7246 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07007247 }
7248
7249 final int pw = container.right - container.left;
7250 final int ph = container.bottom - container.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007251
7252 int w,h;
7253 if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
7254 w = mAttrs.width < 0 ? pw : mAttrs.width;
7255 h = mAttrs.height< 0 ? ph : mAttrs.height;
7256 } else {
Romain Guy980a9382010-01-08 15:06:28 -08007257 w = mAttrs.width == mAttrs.MATCH_PARENT ? pw : mRequestedWidth;
7258 h = mAttrs.height== mAttrs.MATCH_PARENT ? ph : mRequestedHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007259 }
Romain Guy06882f82009-06-10 13:36:04 -07007260
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007261 final Rect content = mContentFrame;
7262 content.set(cf);
Romain Guy06882f82009-06-10 13:36:04 -07007263
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007264 final Rect visible = mVisibleFrame;
7265 visible.set(vf);
Romain Guy06882f82009-06-10 13:36:04 -07007266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007267 final Rect frame = mFrame;
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07007268 final int fw = frame.width();
7269 final int fh = frame.height();
Romain Guy06882f82009-06-10 13:36:04 -07007270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007271 //System.out.println("In: w=" + w + " h=" + h + " container=" +
7272 // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
7273
7274 Gravity.apply(mAttrs.gravity, w, h, container,
7275 (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
7276 (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
7277
7278 //System.out.println("Out: " + mFrame);
7279
7280 // Now make sure the window fits in the overall display.
7281 Gravity.applyDisplay(mAttrs.gravity, df, frame);
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007282
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007283 // Make sure the content and visible frames are inside of the
7284 // final window frame.
7285 if (content.left < frame.left) content.left = frame.left;
7286 if (content.top < frame.top) content.top = frame.top;
7287 if (content.right > frame.right) content.right = frame.right;
7288 if (content.bottom > frame.bottom) content.bottom = frame.bottom;
7289 if (visible.left < frame.left) visible.left = frame.left;
7290 if (visible.top < frame.top) visible.top = frame.top;
7291 if (visible.right > frame.right) visible.right = frame.right;
7292 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007294 final Rect contentInsets = mContentInsets;
7295 contentInsets.left = content.left-frame.left;
7296 contentInsets.top = content.top-frame.top;
7297 contentInsets.right = frame.right-content.right;
7298 contentInsets.bottom = frame.bottom-content.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007299
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007300 final Rect visibleInsets = mVisibleInsets;
7301 visibleInsets.left = visible.left-frame.left;
7302 visibleInsets.top = visible.top-frame.top;
7303 visibleInsets.right = frame.right-visible.right;
7304 visibleInsets.bottom = frame.bottom-visible.bottom;
Romain Guy06882f82009-06-10 13:36:04 -07007305
Dianne Hackborn284ac932009-08-28 10:34:25 -07007306 if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
7307 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
Dianne Hackborn19382ac2009-09-11 21:13:37 -07007308 mDisplay.getHeight(), false);
Dianne Hackborne9e9bca2009-08-18 15:08:22 -07007309 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007310
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007311 if (localLOGV) {
7312 //if ("com.google.android.youtube".equals(mAttrs.packageName)
7313 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007314 Slog.v(TAG, "Resolving (mRequestedWidth="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007315 + mRequestedWidth + ", mRequestedheight="
7316 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
7317 + "): frame=" + mFrame.toShortString()
7318 + " ci=" + contentInsets.toShortString()
7319 + " vi=" + visibleInsets.toShortString());
7320 //}
7321 }
7322 }
Romain Guy06882f82009-06-10 13:36:04 -07007323
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007324 public Rect getFrameLw() {
7325 return mFrame;
7326 }
7327
7328 public Rect getShownFrameLw() {
7329 return mShownFrame;
7330 }
7331
7332 public Rect getDisplayFrameLw() {
7333 return mDisplayFrame;
7334 }
7335
7336 public Rect getContentFrameLw() {
7337 return mContentFrame;
7338 }
7339
7340 public Rect getVisibleFrameLw() {
7341 return mVisibleFrame;
7342 }
7343
7344 public boolean getGivenInsetsPendingLw() {
7345 return mGivenInsetsPending;
7346 }
7347
7348 public Rect getGivenContentInsetsLw() {
7349 return mGivenContentInsets;
7350 }
Romain Guy06882f82009-06-10 13:36:04 -07007351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007352 public Rect getGivenVisibleInsetsLw() {
7353 return mGivenVisibleInsets;
7354 }
Romain Guy06882f82009-06-10 13:36:04 -07007355
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007356 public WindowManager.LayoutParams getAttrs() {
7357 return mAttrs;
7358 }
7359
7360 public int getSurfaceLayer() {
7361 return mLayer;
7362 }
Romain Guy06882f82009-06-10 13:36:04 -07007363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007364 public IApplicationToken getAppToken() {
7365 return mAppToken != null ? mAppToken.appToken : null;
7366 }
7367
7368 public boolean hasAppShownWindows() {
7369 return mAppToken != null ? mAppToken.firstWindowDrawn : false;
7370 }
7371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007372 public void setAnimation(Animation anim) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007373 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007374 TAG, "Setting animation in " + this + ": " + anim);
7375 mAnimating = false;
7376 mLocalAnimating = false;
7377 mAnimation = anim;
7378 mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
7379 mAnimation.scaleCurrentDuration(mWindowAnimationScale);
7380 }
7381
7382 public void clearAnimation() {
7383 if (mAnimation != null) {
7384 mAnimating = true;
7385 mLocalAnimating = false;
7386 mAnimation = null;
7387 }
7388 }
Romain Guy06882f82009-06-10 13:36:04 -07007389
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007390 Surface createSurfaceLocked() {
7391 if (mSurface == null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007392 mReportDestroySurface = false;
7393 mSurfacePendingDestroy = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007394 mDrawPending = true;
7395 mCommitDrawPending = false;
7396 mReadyToShow = false;
7397 if (mAppToken != null) {
7398 mAppToken.allDrawn = false;
7399 }
7400
7401 int flags = 0;
Mathias Agopian317a6282009-08-13 17:29:02 -07007402 if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007403 flags |= Surface.PUSH_BUFFERS;
7404 }
7405
7406 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
7407 flags |= Surface.SECURE;
7408 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007409 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007410 TAG, "Creating surface in session "
7411 + mSession.mSurfaceSession + " window " + this
7412 + " w=" + mFrame.width()
7413 + " h=" + mFrame.height() + " format="
7414 + mAttrs.format + " flags=" + flags);
7415
7416 int w = mFrame.width();
7417 int h = mFrame.height();
7418 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
7419 // for a scaled surface, we always want the requested
7420 // size.
7421 w = mRequestedWidth;
7422 h = mRequestedHeight;
7423 }
7424
Romain Guy9825ec62009-10-01 00:58:09 -07007425 // Something is wrong and SurfaceFlinger will not like this,
7426 // try to revert to sane values
7427 if (w <= 0) w = 1;
7428 if (h <= 0) h = 1;
7429
Dianne Hackborn16064f92010-03-25 00:47:24 -07007430 mSurfaceShown = false;
7431 mSurfaceLayer = 0;
7432 mSurfaceAlpha = 1;
7433 mSurfaceX = 0;
7434 mSurfaceY = 0;
7435 mSurfaceW = w;
7436 mSurfaceH = h;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007437 try {
7438 mSurface = new Surface(
Romain Guy06882f82009-06-10 13:36:04 -07007439 mSession.mSurfaceSession, mSession.mPid,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -08007440 mAttrs.getTitle().toString(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007441 0, w, h, mAttrs.format, flags);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007442 if (SHOW_TRANSACTIONS) Slog.i(TAG, " CREATE SURFACE "
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007443 + mSurface + " IN SESSION "
7444 + mSession.mSurfaceSession
7445 + ": pid=" + mSession.mPid + " format="
7446 + mAttrs.format + " flags=0x"
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007447 + Integer.toHexString(flags)
7448 + " / " + this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007449 } catch (Surface.OutOfResourcesException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007450 Slog.w(TAG, "OutOfResourcesException creating surface");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007451 reclaimSomeSurfaceMemoryLocked(this, "create");
7452 return null;
7453 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007454 Slog.e(TAG, "Exception creating surface", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007455 return null;
7456 }
Romain Guy06882f82009-06-10 13:36:04 -07007457
Joe Onorato8a9b2202010-02-26 18:56:32 -08007458 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007459 TAG, "Got surface: " + mSurface
7460 + ", set left=" + mFrame.left + " top=" + mFrame.top
7461 + ", animLayer=" + mAnimLayer);
7462 if (SHOW_TRANSACTIONS) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007463 Slog.i(TAG, ">>> OPEN TRANSACTION");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007464 if (SHOW_TRANSACTIONS) logSurface(this,
7465 "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
7466 mFrame.width() + "x" + mFrame.height() + "), layer=" +
7467 mAnimLayer + " HIDE", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007468 }
7469 Surface.openTransaction();
7470 try {
7471 try {
Dianne Hackborn16064f92010-03-25 00:47:24 -07007472 mSurfaceX = mFrame.left + mXOffset;
Dianne Hackborn529bef62010-03-25 11:48:43 -07007473 mSurfaceY = mFrame.top + mYOffset;
Dianne Hackborn16064f92010-03-25 00:47:24 -07007474 mSurface.setPosition(mSurfaceX, mSurfaceY);
7475 mSurfaceLayer = mAnimLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007476 mSurface.setLayer(mAnimLayer);
Dianne Hackborn16064f92010-03-25 00:47:24 -07007477 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007478 mSurface.hide();
7479 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007480 if (SHOW_TRANSACTIONS) logSurface(this, "DITHER", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007481 mSurface.setFlags(Surface.SURFACE_DITHER,
7482 Surface.SURFACE_DITHER);
7483 }
7484 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007485 Slog.w(TAG, "Error creating surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007486 reclaimSomeSurfaceMemoryLocked(this, "create-init");
7487 }
7488 mLastHidden = true;
7489 } finally {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007490 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007491 Surface.closeTransaction();
7492 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007493 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007494 TAG, "Created surface " + this);
7495 }
7496 return mSurface;
7497 }
Romain Guy06882f82009-06-10 13:36:04 -07007498
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007499 void destroySurfaceLocked() {
7500 // Window is no longer on-screen, so can no longer receive
7501 // key events... if we were waiting for it to finish
7502 // handling a key event, the wait is over!
7503 mKeyWaiter.finishedKey(mSession, mClient, true,
7504 KeyWaiter.RETURN_NOTHING);
7505 mKeyWaiter.releasePendingPointerLocked(mSession);
7506 mKeyWaiter.releasePendingTrackballLocked(mSession);
7507
7508 if (mAppToken != null && this == mAppToken.startingWindow) {
7509 mAppToken.startingDisplayed = false;
7510 }
Romain Guy06882f82009-06-10 13:36:04 -07007511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007512 if (mSurface != null) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007513 mDrawPending = false;
7514 mCommitDrawPending = false;
7515 mReadyToShow = false;
7516
7517 int i = mChildWindows.size();
7518 while (i > 0) {
7519 i--;
7520 WindowState c = (WindowState)mChildWindows.get(i);
7521 c.mAttachedHidden = true;
7522 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007523
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07007524 if (mReportDestroySurface) {
7525 mReportDestroySurface = false;
7526 mSurfacePendingDestroy = true;
7527 try {
7528 mClient.dispatchGetNewSurface();
7529 // We'll really destroy on the next time around.
7530 return;
7531 } catch (RemoteException e) {
7532 }
7533 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007534
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007535 try {
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007536 if (DEBUG_VISIBILITY) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007537 RuntimeException e = null;
7538 if (!HIDE_STACK_CRAWLS) {
7539 e = new RuntimeException();
7540 e.fillInStackTrace();
7541 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007542 Slog.w(TAG, "Window " + this + " destroying surface "
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007543 + mSurface + ", session " + mSession, e);
7544 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007545 if (SHOW_TRANSACTIONS) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007546 RuntimeException e = null;
7547 if (!HIDE_STACK_CRAWLS) {
7548 e = new RuntimeException();
7549 e.fillInStackTrace();
7550 }
7551 if (SHOW_TRANSACTIONS) logSurface(this, "DESTROY", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007552 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07007553 mSurface.destroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007554 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007555 Slog.w(TAG, "Exception thrown when destroying Window " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007556 + " surface " + mSurface + " session " + mSession
7557 + ": " + e.toString());
7558 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007559
Dianne Hackborn16064f92010-03-25 00:47:24 -07007560 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007561 mSurface = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007562 }
7563 }
7564
7565 boolean finishDrawingLocked() {
7566 if (mDrawPending) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007567 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007568 TAG, "finishDrawingLocked: " + mSurface);
7569 mCommitDrawPending = true;
7570 mDrawPending = false;
7571 return true;
7572 }
7573 return false;
7574 }
7575
7576 // This must be called while inside a transaction.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007577 boolean commitFinishDrawingLocked(long currentTime) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007578 //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007579 if (!mCommitDrawPending) {
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007580 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007581 }
7582 mCommitDrawPending = false;
7583 mReadyToShow = true;
7584 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
7585 final AppWindowToken atoken = mAppToken;
7586 if (atoken == null || atoken.allDrawn || starting) {
7587 performShowLocked();
7588 }
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07007589 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007590 }
7591
7592 // This must be called while inside a transaction.
7593 boolean performShowLocked() {
7594 if (DEBUG_VISIBILITY) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007595 RuntimeException e = null;
7596 if (!HIDE_STACK_CRAWLS) {
7597 e = new RuntimeException();
7598 e.fillInStackTrace();
7599 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007600 Slog.v(TAG, "performShow on " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007601 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
7602 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
7603 }
7604 if (mReadyToShow && isReadyForDisplay()) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007605 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) logSurface(this,
7606 "SHOW (performShowLocked)", null);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007607 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007608 + " during animation: policyVis=" + mPolicyVisibility
7609 + " attHidden=" + mAttachedHidden
7610 + " tok.hiddenRequested="
7611 + (mAppToken != null ? mAppToken.hiddenRequested : false)
Dianne Hackborn248b1882009-09-16 16:46:44 -07007612 + " tok.hidden="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007613 + (mAppToken != null ? mAppToken.hidden : false)
7614 + " animating=" + mAnimating
7615 + " tok animating="
7616 + (mAppToken != null ? mAppToken.animating : false));
7617 if (!showSurfaceRobustlyLocked(this)) {
7618 return false;
7619 }
7620 mLastAlpha = -1;
7621 mHasDrawn = true;
7622 mLastHidden = false;
7623 mReadyToShow = false;
7624 enableScreenIfNeededLocked();
7625
7626 applyEnterAnimationLocked(this);
Romain Guy06882f82009-06-10 13:36:04 -07007627
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007628 int i = mChildWindows.size();
7629 while (i > 0) {
7630 i--;
7631 WindowState c = (WindowState)mChildWindows.get(i);
Dianne Hackbornf09c1a22010-04-22 15:59:21 -07007632 if (c.mAttachedHidden) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007633 c.mAttachedHidden = false;
Dianne Hackbornf09c1a22010-04-22 15:59:21 -07007634 if (c.mSurface != null) {
7635 c.performShowLocked();
7636 // It hadn't been shown, which means layout not
7637 // performed on it, so now we want to make sure to
7638 // do a layout. If called from within the transaction
7639 // loop, this will cause it to restart with a new
7640 // layout.
7641 mLayoutNeeded = true;
7642 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007643 }
7644 }
Romain Guy06882f82009-06-10 13:36:04 -07007645
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007646 if (mAttrs.type != TYPE_APPLICATION_STARTING
7647 && mAppToken != null) {
7648 mAppToken.firstWindowDrawn = true;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007649
Dianne Hackborn248b1882009-09-16 16:46:44 -07007650 if (mAppToken.startingData != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007651 if (DEBUG_STARTING_WINDOW || DEBUG_ANIM) Slog.v(TAG,
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007652 "Finish starting " + mToken
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007653 + ": first real window is shown, no animation");
Dianne Hackborn248b1882009-09-16 16:46:44 -07007654 // If this initial window is animating, stop it -- we
7655 // will do an animation to reveal it from behind the
7656 // starting window, so there is no need for it to also
7657 // be doing its own stuff.
7658 if (mAnimation != null) {
7659 mAnimation = null;
7660 // Make sure we clean up the animation.
7661 mAnimating = true;
7662 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007663 mFinishedStarting.add(mAppToken);
7664 mH.sendEmptyMessage(H.FINISHED_STARTING);
7665 }
7666 mAppToken.updateReportedVisibilityLocked();
7667 }
7668 }
7669 return true;
7670 }
Romain Guy06882f82009-06-10 13:36:04 -07007671
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007672 // This must be called while inside a transaction. Returns true if
7673 // there is more animation to run.
7674 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -08007675 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007676 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07007677
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007678 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
7679 mHasTransformation = true;
7680 mHasLocalTransformation = true;
7681 if (!mLocalAnimating) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007682 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007683 TAG, "Starting animation in " + this +
7684 " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
7685 " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
7686 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
7687 mAnimation.setStartTime(currentTime);
7688 mLocalAnimating = true;
7689 mAnimating = true;
7690 }
7691 mTransformation.clear();
7692 final boolean more = mAnimation.getTransformation(
7693 currentTime, mTransformation);
Joe Onorato8a9b2202010-02-26 18:56:32 -08007694 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007695 TAG, "Stepped animation in " + this +
7696 ": more=" + more + ", xform=" + mTransformation);
7697 if (more) {
7698 // we're not done!
7699 return true;
7700 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007701 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007702 TAG, "Finished animation in " + this +
7703 " @ " + currentTime);
7704 mAnimation = null;
7705 //WindowManagerService.this.dump();
7706 }
7707 mHasLocalTransformation = false;
7708 if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007709 && mAppToken.animation != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007710 // When our app token is animating, we kind-of pretend like
7711 // we are as well. Note the mLocalAnimating mAnimationIsEntrance
7712 // part of this check means that we will only do this if
7713 // our window is not currently exiting, or it is not
7714 // locally animating itself. The idea being that one that
7715 // is exiting and doing a local animation should be removed
7716 // once that animation is done.
7717 mAnimating = true;
7718 mHasTransformation = true;
7719 mTransformation.clear();
7720 return false;
7721 } else if (mHasTransformation) {
7722 // Little trick to get through the path below to act like
7723 // we have finished an animation.
7724 mAnimating = true;
7725 } else if (isAnimating()) {
7726 mAnimating = true;
7727 }
7728 } else if (mAnimation != null) {
7729 // If the display is frozen, and there is a pending animation,
7730 // clear it and make sure we run the cleanup code.
7731 mAnimating = true;
7732 mLocalAnimating = true;
7733 mAnimation = null;
7734 }
Romain Guy06882f82009-06-10 13:36:04 -07007735
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007736 if (!mAnimating && !mLocalAnimating) {
7737 return false;
7738 }
7739
Joe Onorato8a9b2202010-02-26 18:56:32 -08007740 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007741 TAG, "Animation done in " + this + ": exiting=" + mExiting
7742 + ", reportedVisible="
7743 + (mAppToken != null ? mAppToken.reportedVisible : false));
Romain Guy06882f82009-06-10 13:36:04 -07007744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007745 mAnimating = false;
7746 mLocalAnimating = false;
7747 mAnimation = null;
7748 mAnimLayer = mLayer;
7749 if (mIsImWindow) {
7750 mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007751 } else if (mIsWallpaper) {
7752 mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007753 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08007754 if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007755 + " anim layer: " + mAnimLayer);
7756 mHasTransformation = false;
7757 mHasLocalTransformation = false;
Dianne Hackbornb601ce12010-03-01 23:36:02 -08007758 if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
7759 if (DEBUG_VISIBILITY) {
7760 Slog.v(TAG, "Policy visibility changing after anim in " + this + ": "
7761 + mPolicyVisibilityAfterAnim);
7762 }
7763 mPolicyVisibility = mPolicyVisibilityAfterAnim;
7764 if (!mPolicyVisibility) {
7765 if (mCurrentFocus == this) {
7766 mFocusMayChange = true;
7767 }
7768 // Window is no longer visible -- make sure if we were waiting
7769 // for it to be displayed before enabling the display, that
7770 // we allow the display to be enabled now.
7771 enableScreenIfNeededLocked();
7772 }
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -08007773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007774 mTransformation.clear();
7775 if (mHasDrawn
7776 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
7777 && mAppToken != null
7778 && mAppToken.firstWindowDrawn
7779 && mAppToken.startingData != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007780 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007781 + mToken + ": first real window done animating");
7782 mFinishedStarting.add(mAppToken);
7783 mH.sendEmptyMessage(H.FINISHED_STARTING);
7784 }
Romain Guy06882f82009-06-10 13:36:04 -07007785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007786 finishExit();
7787
7788 if (mAppToken != null) {
7789 mAppToken.updateReportedVisibilityLocked();
7790 }
7791
7792 return false;
7793 }
7794
7795 void finishExit() {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007796 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007797 TAG, "finishExit in " + this
7798 + ": exiting=" + mExiting
7799 + " remove=" + mRemoveOnExit
7800 + " windowAnimating=" + isWindowAnimating());
Romain Guy06882f82009-06-10 13:36:04 -07007801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007802 final int N = mChildWindows.size();
7803 for (int i=0; i<N; i++) {
7804 ((WindowState)mChildWindows.get(i)).finishExit();
7805 }
Romain Guy06882f82009-06-10 13:36:04 -07007806
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007807 if (!mExiting) {
7808 return;
7809 }
Romain Guy06882f82009-06-10 13:36:04 -07007810
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007811 if (isWindowAnimating()) {
7812 return;
7813 }
7814
Joe Onorato8a9b2202010-02-26 18:56:32 -08007815 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007816 TAG, "Exit animation finished in " + this
7817 + ": remove=" + mRemoveOnExit);
7818 if (mSurface != null) {
7819 mDestroySurface.add(this);
7820 mDestroying = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08007821 if (SHOW_TRANSACTIONS) logSurface(this, "HIDE (finishExit)", null);
Dianne Hackborn16064f92010-03-25 00:47:24 -07007822 mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007823 try {
7824 mSurface.hide();
7825 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007826 Slog.w(TAG, "Error hiding surface in " + this, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007827 }
7828 mLastHidden = true;
7829 mKeyWaiter.releasePendingPointerLocked(mSession);
7830 }
7831 mExiting = false;
7832 if (mRemoveOnExit) {
7833 mPendingRemove.add(this);
7834 mRemoveOnExit = false;
7835 }
7836 }
Romain Guy06882f82009-06-10 13:36:04 -07007837
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007838 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
7839 if (dsdx < .99999f || dsdx > 1.00001f) return false;
7840 if (dtdy < .99999f || dtdy > 1.00001f) return false;
7841 if (dtdx < -.000001f || dtdx > .000001f) return false;
7842 if (dsdy < -.000001f || dsdy > .000001f) return false;
7843 return true;
7844 }
Romain Guy06882f82009-06-10 13:36:04 -07007845
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007846 void computeShownFrameLocked() {
7847 final boolean selfTransformation = mHasLocalTransformation;
7848 Transformation attachedTransformation =
7849 (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
7850 ? mAttachedWindow.mTransformation : null;
7851 Transformation appTransformation =
7852 (mAppToken != null && mAppToken.hasTransformation)
7853 ? mAppToken.transformation : null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007854
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007855 // Wallpapers are animated based on the "real" window they
7856 // are currently targeting.
Dianne Hackborn3be63c02009-08-20 19:31:38 -07007857 if (mAttrs.type == TYPE_WALLPAPER && mLowerWallpaperTarget == null
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07007858 && mWallpaperTarget != null) {
Dianne Hackborn5baba162009-09-23 17:01:12 -07007859 if (mWallpaperTarget.mHasLocalTransformation &&
7860 mWallpaperTarget.mAnimation != null &&
7861 !mWallpaperTarget.mAnimation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007862 attachedTransformation = mWallpaperTarget.mTransformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07007863 if (DEBUG_WALLPAPER && attachedTransformation != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007864 Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
Dianne Hackborn5baba162009-09-23 17:01:12 -07007865 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007866 }
7867 if (mWallpaperTarget.mAppToken != null &&
Dianne Hackborn5baba162009-09-23 17:01:12 -07007868 mWallpaperTarget.mAppToken.hasTransformation &&
7869 mWallpaperTarget.mAppToken.animation != null &&
7870 !mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007871 appTransformation = mWallpaperTarget.mAppToken.transformation;
Dianne Hackborn5baba162009-09-23 17:01:12 -07007872 if (DEBUG_WALLPAPER && appTransformation != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007873 Slog.v(TAG, "WP target app xform: " + appTransformation);
Dianne Hackborn5baba162009-09-23 17:01:12 -07007874 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07007875 }
Dianne Hackborn759a39e2009-08-09 17:20:27 -07007876 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08007877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007878 if (selfTransformation || attachedTransformation != null
7879 || appTransformation != null) {
Romain Guy06882f82009-06-10 13:36:04 -07007880 // cache often used attributes locally
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007881 final Rect frame = mFrame;
7882 final float tmpFloats[] = mTmpFloats;
7883 final Matrix tmpMatrix = mTmpMatrix;
7884
7885 // Compute the desired transformation.
Dianne Hackborn65c23872009-09-18 17:47:02 -07007886 tmpMatrix.setTranslate(0, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007887 if (selfTransformation) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007888 tmpMatrix.postConcat(mTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007889 }
Dianne Hackborn65c23872009-09-18 17:47:02 -07007890 tmpMatrix.postTranslate(frame.left, frame.top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007891 if (attachedTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007892 tmpMatrix.postConcat(attachedTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007893 }
7894 if (appTransformation != null) {
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07007895 tmpMatrix.postConcat(appTransformation.getMatrix());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007896 }
7897
7898 // "convert" it into SurfaceFlinger's format
7899 // (a 2x2 matrix + an offset)
7900 // Here we must not transform the position of the surface
7901 // since it is already included in the transformation.
Joe Onorato8a9b2202010-02-26 18:56:32 -08007902 //Slog.i(TAG, "Transform: " + matrix);
Romain Guy06882f82009-06-10 13:36:04 -07007903
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007904 tmpMatrix.getValues(tmpFloats);
7905 mDsDx = tmpFloats[Matrix.MSCALE_X];
7906 mDtDx = tmpFloats[Matrix.MSKEW_X];
7907 mDsDy = tmpFloats[Matrix.MSKEW_Y];
7908 mDtDy = tmpFloats[Matrix.MSCALE_Y];
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007909 int x = (int)tmpFloats[Matrix.MTRANS_X] + mXOffset;
7910 int y = (int)tmpFloats[Matrix.MTRANS_Y] + mYOffset;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007911 int w = frame.width();
7912 int h = frame.height();
7913 mShownFrame.set(x, y, x+w, y+h);
7914
7915 // Now set the alpha... but because our current hardware
7916 // can't do alpha transformation on a non-opaque surface,
7917 // turn it off if we are running an animation that is also
7918 // transforming since it is more important to have that
7919 // animation be smooth.
7920 mShownAlpha = mAlpha;
7921 if (!mLimitedAlphaCompositing
7922 || (!PixelFormat.formatHasAlpha(mAttrs.format)
7923 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
7924 && x == frame.left && y == frame.top))) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007925 //Slog.i(TAG, "Applying alpha transform");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007926 if (selfTransformation) {
7927 mShownAlpha *= mTransformation.getAlpha();
7928 }
7929 if (attachedTransformation != null) {
7930 mShownAlpha *= attachedTransformation.getAlpha();
7931 }
7932 if (appTransformation != null) {
7933 mShownAlpha *= appTransformation.getAlpha();
7934 }
7935 } else {
Joe Onorato8a9b2202010-02-26 18:56:32 -08007936 //Slog.i(TAG, "Not applying alpha transform");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007937 }
Romain Guy06882f82009-06-10 13:36:04 -07007938
Joe Onorato8a9b2202010-02-26 18:56:32 -08007939 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007940 TAG, "Continuing animation in " + this +
7941 ": " + mShownFrame +
7942 ", alpha=" + mTransformation.getAlpha());
7943 return;
7944 }
Romain Guy06882f82009-06-10 13:36:04 -07007945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007946 mShownFrame.set(mFrame);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07007947 if (mXOffset != 0 || mYOffset != 0) {
7948 mShownFrame.offset(mXOffset, mYOffset);
7949 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007950 mShownAlpha = mAlpha;
7951 mDsDx = 1;
7952 mDtDx = 0;
7953 mDsDy = 0;
7954 mDtDy = 1;
7955 }
Romain Guy06882f82009-06-10 13:36:04 -07007956
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007957 /**
7958 * Is this window visible? It is not visible if there is no
7959 * surface, or we are in the process of running an exit animation
7960 * that will remove the surface, or its app token has been hidden.
7961 */
7962 public boolean isVisibleLw() {
7963 final AppWindowToken atoken = mAppToken;
7964 return mSurface != null && mPolicyVisibility && !mAttachedHidden
7965 && (atoken == null || !atoken.hiddenRequested)
7966 && !mExiting && !mDestroying;
7967 }
7968
7969 /**
Dianne Hackborn3d163f072009-10-07 21:26:57 -07007970 * Like {@link #isVisibleLw}, but also counts a window that is currently
7971 * "hidden" behind the keyguard as visible. This allows us to apply
7972 * things like window flags that impact the keyguard.
7973 * XXX I am starting to think we need to have ANOTHER visibility flag
7974 * for this "hidden behind keyguard" state rather than overloading
7975 * mPolicyVisibility. Ungh.
7976 */
7977 public boolean isVisibleOrBehindKeyguardLw() {
7978 final AppWindowToken atoken = mAppToken;
7979 return mSurface != null && !mAttachedHidden
7980 && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
Dianne Hackborn5943c202010-04-12 21:36:49 -07007981 && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending))
Dianne Hackborn3d163f072009-10-07 21:26:57 -07007982 && !mExiting && !mDestroying;
7983 }
7984
7985 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007986 * Is this window visible, ignoring its app token? It is not visible
7987 * if there is no surface, or we are in the process of running an exit animation
7988 * that will remove the surface.
7989 */
7990 public boolean isWinVisibleLw() {
7991 final AppWindowToken atoken = mAppToken;
7992 return mSurface != null && mPolicyVisibility && !mAttachedHidden
7993 && (atoken == null || !atoken.hiddenRequested || atoken.animating)
7994 && !mExiting && !mDestroying;
7995 }
7996
7997 /**
7998 * The same as isVisible(), but follows the current hidden state of
7999 * the associated app token, not the pending requested hidden state.
8000 */
8001 boolean isVisibleNow() {
8002 return mSurface != null && mPolicyVisibility && !mAttachedHidden
The Android Open Source Project10592532009-03-18 17:39:46 -07008003 && !mRootToken.hidden && !mExiting && !mDestroying;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008004 }
8005
8006 /**
8007 * Same as isVisible(), but we also count it as visible between the
8008 * call to IWindowSession.add() and the first relayout().
8009 */
8010 boolean isVisibleOrAdding() {
8011 final AppWindowToken atoken = mAppToken;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008012 return ((mSurface != null && !mReportDestroySurface)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008013 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
8014 && mPolicyVisibility && !mAttachedHidden
8015 && (atoken == null || !atoken.hiddenRequested)
8016 && !mExiting && !mDestroying;
8017 }
8018
8019 /**
8020 * Is this window currently on-screen? It is on-screen either if it
8021 * is visible or it is currently running an animation before no longer
8022 * being visible.
8023 */
8024 boolean isOnScreen() {
8025 final AppWindowToken atoken = mAppToken;
8026 if (atoken != null) {
8027 return mSurface != null && mPolicyVisibility && !mDestroying
8028 && ((!mAttachedHidden && !atoken.hiddenRequested)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008029 || mAnimation != null || atoken.animation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008030 } else {
8031 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008032 && (!mAttachedHidden || mAnimation != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008033 }
8034 }
Romain Guy06882f82009-06-10 13:36:04 -07008035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008036 /**
8037 * Like isOnScreen(), but we don't return true if the window is part
8038 * of a transition that has not yet been started.
8039 */
8040 boolean isReadyForDisplay() {
Dianne Hackborna8f60182009-09-01 19:01:50 -07008041 if (mRootToken.waitingToShow &&
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07008042 mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Dianne Hackborna8f60182009-09-01 19:01:50 -07008043 return false;
8044 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008045 final AppWindowToken atoken = mAppToken;
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008046 final boolean animating = atoken != null
8047 ? (atoken.animation != null) : false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008048 return mSurface != null && mPolicyVisibility && !mDestroying
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008049 && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
8050 && !mRootToken.hidden)
Dianne Hackborn0cd48872009-08-13 18:51:59 -07008051 || mAnimation != null || animating);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008052 }
8053
8054 /** Is the window or its container currently animating? */
8055 boolean isAnimating() {
8056 final WindowState attached = mAttachedWindow;
8057 final AppWindowToken atoken = mAppToken;
8058 return mAnimation != null
8059 || (attached != null && attached.mAnimation != null)
Romain Guy06882f82009-06-10 13:36:04 -07008060 || (atoken != null &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008061 (atoken.animation != null
8062 || atoken.inPendingTransaction));
8063 }
8064
8065 /** Is this window currently animating? */
8066 boolean isWindowAnimating() {
8067 return mAnimation != null;
8068 }
8069
8070 /**
8071 * Like isOnScreen, but returns false if the surface hasn't yet
8072 * been drawn.
8073 */
8074 public boolean isDisplayedLw() {
8075 final AppWindowToken atoken = mAppToken;
8076 return mSurface != null && mPolicyVisibility && !mDestroying
8077 && !mDrawPending && !mCommitDrawPending
8078 && ((!mAttachedHidden &&
8079 (atoken == null || !atoken.hiddenRequested))
8080 || mAnimating);
8081 }
8082
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008083 /**
8084 * Returns true if the window has a surface that it has drawn a
Dianne Hackborn5943c202010-04-12 21:36:49 -07008085 * complete UI in to. Note that this returns true if the orientation
8086 * is changing even if the window hasn't redrawn because we don't want
8087 * to stop things from executing during that time.
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008088 */
8089 public boolean isDrawnLw() {
8090 final AppWindowToken atoken = mAppToken;
8091 return mSurface != null && !mDestroying
Dianne Hackborn5943c202010-04-12 21:36:49 -07008092 && (mOrientationChanging || (!mDrawPending && !mCommitDrawPending));
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008093 }
8094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008095 public boolean fillsScreenLw(int screenWidth, int screenHeight,
8096 boolean shownFrame, boolean onlyOpaque) {
8097 if (mSurface == null) {
8098 return false;
8099 }
8100 if (mAppToken != null && !mAppToken.appFullscreen) {
8101 return false;
8102 }
8103 if (onlyOpaque && mAttrs.format != PixelFormat.OPAQUE) {
8104 return false;
8105 }
8106 final Rect frame = shownFrame ? mShownFrame : mFrame;
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008107
8108 if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
8109 return frame.left <= mCompatibleScreenFrame.left &&
8110 frame.top <= mCompatibleScreenFrame.top &&
8111 frame.right >= mCompatibleScreenFrame.right &&
8112 frame.bottom >= mCompatibleScreenFrame.bottom;
8113 } else {
8114 return frame.left <= 0 && frame.top <= 0
8115 && frame.right >= screenWidth
8116 && frame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008117 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008118 }
Romain Guy06882f82009-06-10 13:36:04 -07008119
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008120 /**
Dianne Hackborn25994b42009-09-04 14:21:19 -07008121 * Return true if the window is opaque and fully drawn. This indicates
8122 * it may obscure windows behind it.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008123 */
8124 boolean isOpaqueDrawn() {
Dianne Hackborn25994b42009-09-04 14:21:19 -07008125 return (mAttrs.format == PixelFormat.OPAQUE
8126 || mAttrs.type == TYPE_WALLPAPER)
8127 && mSurface != null && mAnimation == null
8128 && (mAppToken == null || mAppToken.animation == null)
8129 && !mDrawPending && !mCommitDrawPending;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008130 }
8131
8132 boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
8133 return
8134 // only if the application is requesting compatible window
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008135 (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
8136 // only if it's visible
8137 mHasDrawn && mViewVisibility == View.VISIBLE &&
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008138 // and only if the application fills the compatible screen
8139 mFrame.left <= mCompatibleScreenFrame.left &&
8140 mFrame.top <= mCompatibleScreenFrame.top &&
8141 mFrame.right >= mCompatibleScreenFrame.right &&
8142 mFrame.bottom >= mCompatibleScreenFrame.bottom &&
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -07008143 // and starting window do not need background filler
Mitsuru Oshimad2967e22009-07-20 14:01:43 -07008144 mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -07008145 }
8146
8147 boolean isFullscreen(int screenWidth, int screenHeight) {
8148 return mFrame.left <= 0 && mFrame.top <= 0 &&
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07008149 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008150 }
8151
8152 void removeLocked() {
8153 if (mAttachedWindow != null) {
8154 mAttachedWindow.mChildWindows.remove(this);
8155 }
8156 destroySurfaceLocked();
8157 mSession.windowRemovedLocked();
8158 try {
8159 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
8160 } catch (RuntimeException e) {
8161 // Ignore if it has already been removed (usually because
8162 // we are doing this as part of processing a death note.)
8163 }
8164 }
8165
8166 private class DeathRecipient implements IBinder.DeathRecipient {
8167 public void binderDied() {
8168 try {
8169 synchronized(mWindowMap) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008170 WindowState win = windowForClientLocked(mSession, mClient, false);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008171 Slog.i(TAG, "WIN DEATH: " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008172 if (win != null) {
8173 removeWindowLocked(mSession, win);
8174 }
8175 }
8176 } catch (IllegalArgumentException ex) {
8177 // This will happen if the window has already been
8178 // removed.
8179 }
8180 }
8181 }
8182
8183 /** Returns true if this window desires key events. */
8184 public final boolean canReceiveKeys() {
8185 return isVisibleOrAdding()
8186 && (mViewVisibility == View.VISIBLE)
8187 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
8188 }
8189
8190 public boolean hasDrawnLw() {
8191 return mHasDrawn;
8192 }
8193
8194 public boolean showLw(boolean doAnimation) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008195 return showLw(doAnimation, true);
8196 }
8197
8198 boolean showLw(boolean doAnimation, boolean requestAnim) {
8199 if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
8200 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008201 }
Dianne Hackbornb601ce12010-03-01 23:36:02 -08008202 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008203 if (doAnimation) {
8204 if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
8205 + mPolicyVisibility + " mAnimation=" + mAnimation);
8206 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8207 doAnimation = false;
8208 } else if (mPolicyVisibility && mAnimation == null) {
8209 // Check for the case where we are currently visible and
8210 // not animating; we do not want to do animation at such a
8211 // point to become visible when we already are.
8212 doAnimation = false;
8213 }
8214 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008215 mPolicyVisibility = true;
8216 mPolicyVisibilityAfterAnim = true;
8217 if (doAnimation) {
8218 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
8219 }
8220 if (requestAnim) {
8221 requestAnimationLocked(0);
8222 }
8223 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008224 }
8225
8226 public boolean hideLw(boolean doAnimation) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008227 return hideLw(doAnimation, true);
8228 }
8229
8230 boolean hideLw(boolean doAnimation, boolean requestAnim) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008231 if (doAnimation) {
8232 if (mDisplayFrozen || !mPolicy.isScreenOn()) {
8233 doAnimation = false;
8234 }
8235 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008236 boolean current = doAnimation ? mPolicyVisibilityAfterAnim
8237 : mPolicyVisibility;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008238 if (!current) {
8239 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008240 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008241 if (doAnimation) {
8242 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
8243 if (mAnimation == null) {
8244 doAnimation = false;
8245 }
8246 }
8247 if (doAnimation) {
8248 mPolicyVisibilityAfterAnim = false;
8249 } else {
Dianne Hackbornb601ce12010-03-01 23:36:02 -08008250 if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008251 mPolicyVisibilityAfterAnim = false;
8252 mPolicyVisibility = false;
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -08008253 // Window is no longer visible -- make sure if we were waiting
8254 // for it to be displayed before enabling the display, that
8255 // we allow the display to be enabled now.
8256 enableScreenIfNeededLocked();
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08008257 if (mCurrentFocus == this) {
8258 mFocusMayChange = true;
8259 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07008260 }
8261 if (requestAnim) {
8262 requestAnimationLocked(0);
8263 }
8264 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008265 }
8266
8267 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008268 pw.print(prefix); pw.print("mSession="); pw.print(mSession);
8269 pw.print(" mClient="); pw.println(mClient.asBinder());
8270 pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
8271 if (mAttachedWindow != null || mLayoutAttached) {
8272 pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
8273 pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
8274 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -07008275 if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
8276 pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
8277 pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008278 pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
8279 pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008280 }
8281 pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
8282 pw.print(" mSubLayer="); pw.print(mSubLayer);
8283 pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
8284 pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
8285 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
8286 pw.print("="); pw.print(mAnimLayer);
8287 pw.print(" mLastLayer="); pw.println(mLastLayer);
8288 if (mSurface != null) {
8289 pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
Dianne Hackborn16064f92010-03-25 00:47:24 -07008290 pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
8291 pw.print(" layer="); pw.print(mSurfaceLayer);
8292 pw.print(" alpha="); pw.print(mSurfaceAlpha);
8293 pw.print(" rect=("); pw.print(mSurfaceX);
8294 pw.print(","); pw.print(mSurfaceY);
8295 pw.print(") "); pw.print(mSurfaceW);
8296 pw.print(" x "); pw.println(mSurfaceH);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008297 }
8298 pw.print(prefix); pw.print("mToken="); pw.println(mToken);
8299 pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
8300 if (mAppToken != null) {
8301 pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
8302 }
8303 if (mTargetAppToken != null) {
8304 pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
8305 }
8306 pw.print(prefix); pw.print("mViewVisibility=0x");
8307 pw.print(Integer.toHexString(mViewVisibility));
8308 pw.print(" mLastHidden="); pw.print(mLastHidden);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07008309 pw.print(" mHaveFrame="); pw.print(mHaveFrame);
8310 pw.print(" mObscured="); pw.println(mObscured);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008311 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
8312 pw.print(prefix); pw.print("mPolicyVisibility=");
8313 pw.print(mPolicyVisibility);
8314 pw.print(" mPolicyVisibilityAfterAnim=");
8315 pw.print(mPolicyVisibilityAfterAnim);
8316 pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
8317 }
Dianne Hackborn9b52a212009-12-11 14:51:35 -08008318 if (!mRelayoutCalled) {
8319 pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
8320 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008321 pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008322 pw.print(" h="); pw.print(mRequestedHeight);
8323 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008324 if (mXOffset != 0 || mYOffset != 0) {
8325 pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
8326 pw.print(" y="); pw.println(mYOffset);
8327 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008328 pw.print(prefix); pw.print("mGivenContentInsets=");
8329 mGivenContentInsets.printShortString(pw);
8330 pw.print(" mGivenVisibleInsets=");
8331 mGivenVisibleInsets.printShortString(pw);
8332 pw.println();
8333 if (mTouchableInsets != 0 || mGivenInsetsPending) {
8334 pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
8335 pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
8336 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008337 pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008338 pw.print(prefix); pw.print("mShownFrame=");
8339 mShownFrame.printShortString(pw);
8340 pw.print(" last="); mLastShownFrame.printShortString(pw);
8341 pw.println();
8342 pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
8343 pw.print(" last="); mLastFrame.printShortString(pw);
8344 pw.println();
8345 pw.print(prefix); pw.print("mContainingFrame=");
8346 mContainingFrame.printShortString(pw);
8347 pw.print(" mDisplayFrame=");
8348 mDisplayFrame.printShortString(pw);
8349 pw.println();
8350 pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
8351 pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
8352 pw.println();
8353 pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
8354 pw.print(" last="); mLastContentInsets.printShortString(pw);
8355 pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
8356 pw.print(" last="); mLastVisibleInsets.printShortString(pw);
8357 pw.println();
8358 if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
8359 pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
8360 pw.print(" mAlpha="); pw.print(mAlpha);
8361 pw.print(" mLastAlpha="); pw.println(mLastAlpha);
8362 }
8363 if (mAnimating || mLocalAnimating || mAnimationIsEntrance
8364 || mAnimation != null) {
8365 pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
8366 pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
8367 pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
8368 pw.print(" mAnimation="); pw.println(mAnimation);
8369 }
8370 if (mHasTransformation || mHasLocalTransformation) {
8371 pw.print(prefix); pw.print("XForm: has=");
8372 pw.print(mHasTransformation);
8373 pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
8374 pw.print(" "); mTransformation.printShortString(pw);
8375 pw.println();
8376 }
8377 pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
8378 pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
8379 pw.print(" mReadyToShow="); pw.print(mReadyToShow);
8380 pw.print(" mHasDrawn="); pw.println(mHasDrawn);
8381 if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
8382 pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
8383 pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
8384 pw.print(" mDestroying="); pw.print(mDestroying);
8385 pw.print(" mRemoved="); pw.println(mRemoved);
8386 }
Dianne Hackborn93e462b2009-09-15 22:50:40 -07008387 if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008388 pw.print(prefix); pw.print("mOrientationChanging=");
8389 pw.print(mOrientationChanging);
Dianne Hackborn93e462b2009-09-15 22:50:40 -07008390 pw.print(" mAppFreezing="); pw.print(mAppFreezing);
8391 pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008392 }
Mitsuru Oshima589cebe2009-07-22 20:38:58 -07008393 if (mHScale != 1 || mVScale != 1) {
8394 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
8395 pw.print(" mVScale="); pw.println(mVScale);
8396 }
Dianne Hackborn72c82ab2009-08-11 21:13:54 -07008397 if (mWallpaperX != -1 || mWallpaperY != -1) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008398 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
8399 pw.print(" mWallpaperY="); pw.println(mWallpaperY);
8400 }
Marco Nelissenbf6956b2009-11-09 15:21:13 -08008401 if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
8402 pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
8403 pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
8404 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008405 }
8406
8407 @Override
8408 public String toString() {
8409 return "Window{"
8410 + Integer.toHexString(System.identityHashCode(this))
8411 + " " + mAttrs.getTitle() + " paused=" + mToken.paused + "}";
8412 }
8413 }
Romain Guy06882f82009-06-10 13:36:04 -07008414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008415 // -------------------------------------------------------------
8416 // Window Token State
8417 // -------------------------------------------------------------
8418
8419 class WindowToken {
8420 // The actual token.
8421 final IBinder token;
8422
8423 // The type of window this token is for, as per WindowManager.LayoutParams.
8424 final int windowType;
Romain Guy06882f82009-06-10 13:36:04 -07008425
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008426 // Set if this token was explicitly added by a client, so should
8427 // not be removed when all windows are removed.
8428 final boolean explicit;
Romain Guy06882f82009-06-10 13:36:04 -07008429
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008430 // For printing.
8431 String stringName;
Romain Guy06882f82009-06-10 13:36:04 -07008432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008433 // If this is an AppWindowToken, this is non-null.
8434 AppWindowToken appWindowToken;
Romain Guy06882f82009-06-10 13:36:04 -07008435
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008436 // All of the windows associated with this token.
8437 final ArrayList<WindowState> windows = new ArrayList<WindowState>();
8438
8439 // Is key dispatching paused for this token?
8440 boolean paused = false;
8441
8442 // Should this token's windows be hidden?
8443 boolean hidden;
8444
8445 // Temporary for finding which tokens no longer have visible windows.
8446 boolean hasVisible;
8447
Dianne Hackborna8f60182009-09-01 19:01:50 -07008448 // Set to true when this token is in a pending transaction where it
8449 // will be shown.
8450 boolean waitingToShow;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008451
Dianne Hackborna8f60182009-09-01 19:01:50 -07008452 // Set to true when this token is in a pending transaction where it
8453 // will be hidden.
8454 boolean waitingToHide;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008455
Dianne Hackborna8f60182009-09-01 19:01:50 -07008456 // Set to true when this token is in a pending transaction where its
8457 // windows will be put to the bottom of the list.
8458 boolean sendingToBottom;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008459
Dianne Hackborna8f60182009-09-01 19:01:50 -07008460 // Set to true when this token is in a pending transaction where its
8461 // windows will be put to the top of the list.
8462 boolean sendingToTop;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008463
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008464 WindowToken(IBinder _token, int type, boolean _explicit) {
8465 token = _token;
8466 windowType = type;
8467 explicit = _explicit;
8468 }
8469
8470 void dump(PrintWriter pw, String prefix) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008471 pw.print(prefix); pw.print("token="); pw.println(token);
8472 pw.print(prefix); pw.print("windows="); pw.println(windows);
8473 pw.print(prefix); pw.print("windowType="); pw.print(windowType);
8474 pw.print(" hidden="); pw.print(hidden);
8475 pw.print(" hasVisible="); pw.println(hasVisible);
Dianne Hackborna8f60182009-09-01 19:01:50 -07008476 if (waitingToShow || waitingToHide || sendingToBottom || sendingToTop) {
8477 pw.print(prefix); pw.print("waitingToShow="); pw.print(waitingToShow);
8478 pw.print(" waitingToHide="); pw.print(waitingToHide);
8479 pw.print(" sendingToBottom="); pw.print(sendingToBottom);
8480 pw.print(" sendingToTop="); pw.println(sendingToTop);
8481 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008482 }
8483
8484 @Override
8485 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008486 if (stringName == null) {
8487 StringBuilder sb = new StringBuilder();
8488 sb.append("WindowToken{");
8489 sb.append(Integer.toHexString(System.identityHashCode(this)));
8490 sb.append(" token="); sb.append(token); sb.append('}');
8491 stringName = sb.toString();
8492 }
8493 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008494 }
8495 };
8496
8497 class AppWindowToken extends WindowToken {
8498 // Non-null only for application tokens.
8499 final IApplicationToken appToken;
8500
8501 // All of the windows and child windows that are included in this
8502 // application token. Note this list is NOT sorted!
8503 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
8504
8505 int groupId = -1;
8506 boolean appFullscreen;
8507 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
Romain Guy06882f82009-06-10 13:36:04 -07008508
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509 // These are used for determining when all windows associated with
8510 // an activity have been drawn, so they can be made visible together
8511 // at the same time.
8512 int lastTransactionSequence = mTransactionSequence-1;
8513 int numInterestingWindows;
8514 int numDrawnWindows;
8515 boolean inPendingTransaction;
8516 boolean allDrawn;
Romain Guy06882f82009-06-10 13:36:04 -07008517
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008518 // Is this token going to be hidden in a little while? If so, it
8519 // won't be taken into account for setting the screen orientation.
8520 boolean willBeHidden;
Romain Guy06882f82009-06-10 13:36:04 -07008521
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008522 // Is this window's surface needed? This is almost like hidden, except
8523 // it will sometimes be true a little earlier: when the token has
8524 // been shown, but is still waiting for its app transition to execute
8525 // before making its windows shown.
8526 boolean hiddenRequested;
Romain Guy06882f82009-06-10 13:36:04 -07008527
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008528 // Have we told the window clients to hide themselves?
8529 boolean clientHidden;
Romain Guy06882f82009-06-10 13:36:04 -07008530
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008531 // Last visibility state we reported to the app token.
8532 boolean reportedVisible;
8533
8534 // Set to true when the token has been removed from the window mgr.
8535 boolean removed;
8536
8537 // Have we been asked to have this token keep the screen frozen?
8538 boolean freezingScreen;
Romain Guy06882f82009-06-10 13:36:04 -07008539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008540 boolean animating;
8541 Animation animation;
8542 boolean hasTransformation;
8543 final Transformation transformation = new Transformation();
Romain Guy06882f82009-06-10 13:36:04 -07008544
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008545 // Offset to the window of all layers in the token, for use by
8546 // AppWindowToken animations.
8547 int animLayerAdjustment;
Romain Guy06882f82009-06-10 13:36:04 -07008548
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008549 // Information about an application starting window if displayed.
8550 StartingData startingData;
8551 WindowState startingWindow;
8552 View startingView;
8553 boolean startingDisplayed;
8554 boolean startingMoved;
8555 boolean firstWindowDrawn;
8556
8557 AppWindowToken(IApplicationToken _token) {
8558 super(_token.asBinder(),
8559 WindowManager.LayoutParams.TYPE_APPLICATION, true);
8560 appWindowToken = this;
8561 appToken = _token;
8562 }
Romain Guy06882f82009-06-10 13:36:04 -07008563
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008564 public void setAnimation(Animation anim) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008565 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008566 TAG, "Setting animation in " + this + ": " + anim);
8567 animation = anim;
8568 animating = false;
8569 anim.restrictDuration(MAX_ANIMATION_DURATION);
8570 anim.scaleCurrentDuration(mTransitionAnimationScale);
8571 int zorder = anim.getZAdjustment();
8572 int adj = 0;
8573 if (zorder == Animation.ZORDER_TOP) {
8574 adj = TYPE_LAYER_OFFSET;
8575 } else if (zorder == Animation.ZORDER_BOTTOM) {
8576 adj = -TYPE_LAYER_OFFSET;
8577 }
Romain Guy06882f82009-06-10 13:36:04 -07008578
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008579 if (animLayerAdjustment != adj) {
8580 animLayerAdjustment = adj;
8581 updateLayers();
8582 }
8583 }
Romain Guy06882f82009-06-10 13:36:04 -07008584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008585 public void setDummyAnimation() {
8586 if (animation == null) {
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 dummy animation in " + this);
8589 animation = sDummyAnimation;
8590 }
8591 }
8592
8593 public void clearAnimation() {
8594 if (animation != null) {
8595 animation = null;
8596 animating = true;
8597 }
8598 }
Romain Guy06882f82009-06-10 13:36:04 -07008599
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008600 void updateLayers() {
8601 final int N = allAppWindows.size();
8602 final int adj = animLayerAdjustment;
8603 for (int i=0; i<N; i++) {
8604 WindowState w = allAppWindows.get(i);
8605 w.mAnimLayer = w.mLayer + adj;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008606 if (DEBUG_LAYERS) Slog.v(TAG, "Updating layer " + w + ": "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008607 + w.mAnimLayer);
8608 if (w == mInputMethodTarget) {
8609 setInputMethodAnimLayerAdjustment(adj);
8610 }
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008611 if (w == mWallpaperTarget && mLowerWallpaperTarget == null) {
Dianne Hackbornc8a0a752009-08-10 23:05:49 -07008612 setWallpaperAnimLayerAdjustmentLocked(adj);
Dianne Hackborn759a39e2009-08-09 17:20:27 -07008613 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008614 }
8615 }
Romain Guy06882f82009-06-10 13:36:04 -07008616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008617 void sendAppVisibilityToClients() {
8618 final int N = allAppWindows.size();
8619 for (int i=0; i<N; i++) {
8620 WindowState win = allAppWindows.get(i);
8621 if (win == startingWindow && clientHidden) {
8622 // Don't hide the starting window.
8623 continue;
8624 }
8625 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008626 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008627 "Setting visibility of " + win + ": " + (!clientHidden));
8628 win.mClient.dispatchAppVisibility(!clientHidden);
8629 } catch (RemoteException e) {
8630 }
8631 }
8632 }
Romain Guy06882f82009-06-10 13:36:04 -07008633
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008634 void showAllWindowsLocked() {
8635 final int NW = allAppWindows.size();
8636 for (int i=0; i<NW; i++) {
8637 WindowState w = allAppWindows.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008638 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008639 "performing show on: " + w);
8640 w.performShowLocked();
8641 }
8642 }
Romain Guy06882f82009-06-10 13:36:04 -07008643
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008644 // This must be called while inside a transaction.
8645 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -08008646 if (!mDisplayFrozen && mPolicy.isScreenOn()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008647 // We will run animations as long as the display isn't frozen.
Romain Guy06882f82009-06-10 13:36:04 -07008648
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008649 if (animation == sDummyAnimation) {
8650 // This guy is going to animate, but not yet. For now count
Dianne Hackborn3be63c02009-08-20 19:31:38 -07008651 // it as not animating for purposes of scheduling transactions;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008652 // when it is really time to animate, this will be set to
8653 // a real animation and the next call will execute normally.
8654 return false;
8655 }
Romain Guy06882f82009-06-10 13:36:04 -07008656
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008657 if ((allDrawn || animating || startingDisplayed) && animation != null) {
8658 if (!animating) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008659 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008660 TAG, "Starting animation in " + this +
8661 " @ " + currentTime + ": dw=" + dw + " dh=" + dh
8662 + " scale=" + mTransitionAnimationScale
8663 + " allDrawn=" + allDrawn + " animating=" + animating);
8664 animation.initialize(dw, dh, dw, dh);
8665 animation.setStartTime(currentTime);
8666 animating = true;
8667 }
8668 transformation.clear();
8669 final boolean more = animation.getTransformation(
8670 currentTime, transformation);
Joe Onorato8a9b2202010-02-26 18:56:32 -08008671 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008672 TAG, "Stepped animation in " + this +
8673 ": more=" + more + ", xform=" + transformation);
8674 if (more) {
8675 // we're done!
8676 hasTransformation = true;
8677 return true;
8678 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08008679 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008680 TAG, "Finished animation in " + this +
8681 " @ " + currentTime);
8682 animation = null;
8683 }
8684 } else if (animation != null) {
8685 // If the display is frozen, and there is a pending animation,
8686 // clear it and make sure we run the cleanup code.
8687 animating = true;
8688 animation = null;
8689 }
8690
8691 hasTransformation = false;
Romain Guy06882f82009-06-10 13:36:04 -07008692
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008693 if (!animating) {
8694 return false;
8695 }
8696
8697 clearAnimation();
8698 animating = false;
8699 if (mInputMethodTarget != null && mInputMethodTarget.mAppToken == this) {
8700 moveInputMethodWindowsIfNeededLocked(true);
8701 }
Romain Guy06882f82009-06-10 13:36:04 -07008702
Joe Onorato8a9b2202010-02-26 18:56:32 -08008703 if (DEBUG_ANIM) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008704 TAG, "Animation done in " + this
8705 + ": reportedVisible=" + reportedVisible);
8706
8707 transformation.clear();
8708 if (animLayerAdjustment != 0) {
8709 animLayerAdjustment = 0;
8710 updateLayers();
8711 }
Romain Guy06882f82009-06-10 13:36:04 -07008712
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008713 final int N = windows.size();
8714 for (int i=0; i<N; i++) {
8715 ((WindowState)windows.get(i)).finishExit();
8716 }
8717 updateReportedVisibilityLocked();
Romain Guy06882f82009-06-10 13:36:04 -07008718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008719 return false;
8720 }
8721
8722 void updateReportedVisibilityLocked() {
8723 if (appToken == null) {
8724 return;
8725 }
Romain Guy06882f82009-06-10 13:36:04 -07008726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008727 int numInteresting = 0;
8728 int numVisible = 0;
8729 boolean nowGone = true;
Romain Guy06882f82009-06-10 13:36:04 -07008730
Joe Onorato8a9b2202010-02-26 18:56:32 -08008731 if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008732 final int N = allAppWindows.size();
8733 for (int i=0; i<N; i++) {
8734 WindowState win = allAppWindows.get(i);
Dianne Hackborn6cf67fa2009-12-21 16:46:34 -08008735 if (win == startingWindow || win.mAppFreezing
8736 || win.mViewVisibility != View.VISIBLE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008737 continue;
8738 }
8739 if (DEBUG_VISIBILITY) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008740 Slog.v(TAG, "Win " + win + ": isDrawn="
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008741 + win.isDrawnLw()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008742 + ", isAnimating=" + win.isAnimating());
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008743 if (!win.isDrawnLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008744 Slog.v(TAG, "Not displayed: s=" + win.mSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008745 + " pv=" + win.mPolicyVisibility
8746 + " dp=" + win.mDrawPending
8747 + " cdp=" + win.mCommitDrawPending
8748 + " ah=" + win.mAttachedHidden
8749 + " th="
8750 + (win.mAppToken != null
8751 ? win.mAppToken.hiddenRequested : false)
8752 + " a=" + win.mAnimating);
8753 }
8754 }
8755 numInteresting++;
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07008756 if (win.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008757 if (!win.isAnimating()) {
8758 numVisible++;
8759 }
8760 nowGone = false;
8761 } else if (win.isAnimating()) {
8762 nowGone = false;
8763 }
8764 }
Romain Guy06882f82009-06-10 13:36:04 -07008765
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008766 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008767 if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008768 + numInteresting + " visible=" + numVisible);
8769 if (nowVisible != reportedVisible) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008770 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008771 TAG, "Visibility changed in " + this
8772 + ": vis=" + nowVisible);
8773 reportedVisible = nowVisible;
8774 Message m = mH.obtainMessage(
8775 H.REPORT_APPLICATION_TOKEN_WINDOWS,
8776 nowVisible ? 1 : 0,
8777 nowGone ? 1 : 0,
8778 this);
8779 mH.sendMessage(m);
8780 }
8781 }
Romain Guy06882f82009-06-10 13:36:04 -07008782
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07008783 WindowState findMainWindow() {
8784 int j = windows.size();
8785 while (j > 0) {
8786 j--;
8787 WindowState win = windows.get(j);
8788 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
8789 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
8790 return win;
8791 }
8792 }
8793 return null;
8794 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08008795
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008796 void dump(PrintWriter pw, String prefix) {
8797 super.dump(pw, prefix);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008798 if (appToken != null) {
8799 pw.print(prefix); pw.println("app=true");
8800 }
8801 if (allAppWindows.size() > 0) {
8802 pw.print(prefix); pw.print("allAppWindows="); pw.println(allAppWindows);
8803 }
8804 pw.print(prefix); pw.print("groupId="); pw.print(groupId);
Dianne Hackborna8f60182009-09-01 19:01:50 -07008805 pw.print(" appFullscreen="); pw.print(appFullscreen);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008806 pw.print(" requestedOrientation="); pw.println(requestedOrientation);
8807 pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
8808 pw.print(" clientHidden="); pw.print(clientHidden);
8809 pw.print(" willBeHidden="); pw.print(willBeHidden);
8810 pw.print(" reportedVisible="); pw.println(reportedVisible);
8811 if (paused || freezingScreen) {
8812 pw.print(prefix); pw.print("paused="); pw.print(paused);
8813 pw.print(" freezingScreen="); pw.println(freezingScreen);
8814 }
8815 if (numInterestingWindows != 0 || numDrawnWindows != 0
8816 || inPendingTransaction || allDrawn) {
8817 pw.print(prefix); pw.print("numInterestingWindows=");
8818 pw.print(numInterestingWindows);
8819 pw.print(" numDrawnWindows="); pw.print(numDrawnWindows);
8820 pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
8821 pw.print(" allDrawn="); pw.println(allDrawn);
8822 }
8823 if (animating || animation != null) {
8824 pw.print(prefix); pw.print("animating="); pw.print(animating);
8825 pw.print(" animation="); pw.println(animation);
8826 }
8827 if (animLayerAdjustment != 0) {
8828 pw.print(prefix); pw.print("animLayerAdjustment="); pw.println(animLayerAdjustment);
8829 }
8830 if (hasTransformation) {
8831 pw.print(prefix); pw.print("hasTransformation="); pw.print(hasTransformation);
8832 pw.print(" transformation="); transformation.printShortString(pw);
8833 pw.println();
8834 }
8835 if (startingData != null || removed || firstWindowDrawn) {
8836 pw.print(prefix); pw.print("startingData="); pw.print(startingData);
8837 pw.print(" removed="); pw.print(removed);
8838 pw.print(" firstWindowDrawn="); pw.println(firstWindowDrawn);
8839 }
8840 if (startingWindow != null || startingView != null
8841 || startingDisplayed || startingMoved) {
8842 pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
8843 pw.print(" startingView="); pw.print(startingView);
8844 pw.print(" startingDisplayed="); pw.print(startingDisplayed);
8845 pw.print(" startingMoved"); pw.println(startingMoved);
8846 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008847 }
8848
8849 @Override
8850 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07008851 if (stringName == null) {
8852 StringBuilder sb = new StringBuilder();
8853 sb.append("AppWindowToken{");
8854 sb.append(Integer.toHexString(System.identityHashCode(this)));
8855 sb.append(" token="); sb.append(token); sb.append('}');
8856 stringName = sb.toString();
8857 }
8858 return stringName;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008859 }
8860 }
Romain Guy06882f82009-06-10 13:36:04 -07008861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008862 // -------------------------------------------------------------
8863 // DummyAnimation
8864 // -------------------------------------------------------------
8865
8866 // This is an animation that does nothing: it just immediately finishes
8867 // itself every time it is called. It is used as a stub animation in cases
8868 // where we want to synchronize multiple things that may be animating.
8869 static final class DummyAnimation extends Animation {
8870 public boolean getTransformation(long currentTime, Transformation outTransformation) {
8871 return false;
8872 }
8873 }
8874 static final Animation sDummyAnimation = new DummyAnimation();
Romain Guy06882f82009-06-10 13:36:04 -07008875
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008876 // -------------------------------------------------------------
8877 // Async Handler
8878 // -------------------------------------------------------------
8879
8880 static final class StartingData {
8881 final String pkg;
8882 final int theme;
8883 final CharSequence nonLocalizedLabel;
8884 final int labelRes;
8885 final int icon;
Romain Guy06882f82009-06-10 13:36:04 -07008886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008887 StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
8888 int _labelRes, int _icon) {
8889 pkg = _pkg;
8890 theme = _theme;
8891 nonLocalizedLabel = _nonLocalizedLabel;
8892 labelRes = _labelRes;
8893 icon = _icon;
8894 }
8895 }
8896
8897 private final class H extends Handler {
8898 public static final int REPORT_FOCUS_CHANGE = 2;
8899 public static final int REPORT_LOSING_FOCUS = 3;
8900 public static final int ANIMATE = 4;
8901 public static final int ADD_STARTING = 5;
8902 public static final int REMOVE_STARTING = 6;
8903 public static final int FINISHED_STARTING = 7;
8904 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008905 public static final int WINDOW_FREEZE_TIMEOUT = 11;
8906 public static final int HOLD_SCREEN_CHANGED = 12;
8907 public static final int APP_TRANSITION_TIMEOUT = 13;
8908 public static final int PERSIST_ANIMATION_SCALE = 14;
8909 public static final int FORCE_GC = 15;
8910 public static final int ENABLE_SCREEN = 16;
8911 public static final int APP_FREEZE_TIMEOUT = 17;
Dianne Hackborne36d6e22010-02-17 19:46:25 -08008912 public static final int SEND_NEW_CONFIGURATION = 18;
Romain Guy06882f82009-06-10 13:36:04 -07008913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008914 private Session mLastReportedHold;
Romain Guy06882f82009-06-10 13:36:04 -07008915
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008916 public H() {
8917 }
Romain Guy06882f82009-06-10 13:36:04 -07008918
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008919 @Override
8920 public void handleMessage(Message msg) {
8921 switch (msg.what) {
8922 case REPORT_FOCUS_CHANGE: {
8923 WindowState lastFocus;
8924 WindowState newFocus;
Romain Guy06882f82009-06-10 13:36:04 -07008925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008926 synchronized(mWindowMap) {
8927 lastFocus = mLastFocus;
8928 newFocus = mCurrentFocus;
8929 if (lastFocus == newFocus) {
8930 // Focus is not changing, so nothing to do.
8931 return;
8932 }
8933 mLastFocus = newFocus;
Joe Onorato8a9b2202010-02-26 18:56:32 -08008934 //Slog.i(TAG, "Focus moving from " + lastFocus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008935 // + " to " + newFocus);
8936 if (newFocus != null && lastFocus != null
8937 && !newFocus.isDisplayedLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008938 //Slog.i(TAG, "Delaying loss of focus...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008939 mLosingFocus.add(lastFocus);
8940 lastFocus = null;
8941 }
8942 }
8943
8944 if (lastFocus != newFocus) {
8945 //System.out.println("Changing focus from " + lastFocus
8946 // + " to " + newFocus);
8947 if (newFocus != null) {
8948 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008949 //Slog.i(TAG, "Gaining focus: " + newFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008950 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
8951 } catch (RemoteException e) {
8952 // Ignore if process has died.
8953 }
8954 }
8955
8956 if (lastFocus != null) {
8957 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008958 //Slog.i(TAG, "Losing focus: " + lastFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008959 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
8960 } catch (RemoteException e) {
8961 // Ignore if process has died.
8962 }
8963 }
8964 }
8965 } break;
8966
8967 case REPORT_LOSING_FOCUS: {
8968 ArrayList<WindowState> losers;
Romain Guy06882f82009-06-10 13:36:04 -07008969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008970 synchronized(mWindowMap) {
8971 losers = mLosingFocus;
8972 mLosingFocus = new ArrayList<WindowState>();
8973 }
8974
8975 final int N = losers.size();
8976 for (int i=0; i<N; i++) {
8977 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08008978 //Slog.i(TAG, "Losing delayed focus: " + losers.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008979 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
8980 } catch (RemoteException e) {
8981 // Ignore if process has died.
8982 }
8983 }
8984 } break;
8985
8986 case ANIMATE: {
8987 synchronized(mWindowMap) {
8988 mAnimationPending = false;
8989 performLayoutAndPlaceSurfacesLocked();
8990 }
8991 } break;
8992
8993 case ADD_STARTING: {
8994 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
8995 final StartingData sd = wtoken.startingData;
8996
8997 if (sd == null) {
8998 // Animation has been canceled... do nothing.
8999 return;
9000 }
Romain Guy06882f82009-06-10 13:36:04 -07009001
Joe Onorato8a9b2202010-02-26 18:56:32 -08009002 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Add starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009003 + wtoken + ": pkg=" + sd.pkg);
Romain Guy06882f82009-06-10 13:36:04 -07009004
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009005 View view = null;
9006 try {
9007 view = mPolicy.addStartingWindow(
9008 wtoken.token, sd.pkg,
9009 sd.theme, sd.nonLocalizedLabel, sd.labelRes,
9010 sd.icon);
9011 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009012 Slog.w(TAG, "Exception when adding starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009013 }
9014
9015 if (view != null) {
9016 boolean abort = false;
9017
9018 synchronized(mWindowMap) {
9019 if (wtoken.removed || wtoken.startingData == null) {
9020 // If the window was successfully added, then
9021 // we need to remove it.
9022 if (wtoken.startingWindow != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009023 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009024 "Aborted starting " + wtoken
9025 + ": removed=" + wtoken.removed
9026 + " startingData=" + wtoken.startingData);
9027 wtoken.startingWindow = null;
9028 wtoken.startingData = null;
9029 abort = true;
9030 }
9031 } else {
9032 wtoken.startingView = view;
9033 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009034 if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009035 "Added starting " + wtoken
9036 + ": startingWindow="
9037 + wtoken.startingWindow + " startingView="
9038 + wtoken.startingView);
9039 }
9040
9041 if (abort) {
9042 try {
9043 mPolicy.removeStartingWindow(wtoken.token, view);
9044 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009045 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009046 }
9047 }
9048 }
9049 } break;
9050
9051 case REMOVE_STARTING: {
9052 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9053 IBinder token = null;
9054 View view = null;
9055 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009056 if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Remove starting "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009057 + wtoken + ": startingWindow="
9058 + wtoken.startingWindow + " startingView="
9059 + wtoken.startingView);
9060 if (wtoken.startingWindow != null) {
9061 view = wtoken.startingView;
9062 token = wtoken.token;
9063 wtoken.startingData = null;
9064 wtoken.startingView = null;
9065 wtoken.startingWindow = null;
9066 }
9067 }
9068 if (view != null) {
9069 try {
9070 mPolicy.removeStartingWindow(token, view);
9071 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009072 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009073 }
9074 }
9075 } break;
9076
9077 case FINISHED_STARTING: {
9078 IBinder token = null;
9079 View view = null;
9080 while (true) {
9081 synchronized (mWindowMap) {
9082 final int N = mFinishedStarting.size();
9083 if (N <= 0) {
9084 break;
9085 }
9086 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
9087
Joe Onorato8a9b2202010-02-26 18:56:32 -08009088 if (DEBUG_STARTING_WINDOW) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009089 "Finished starting " + wtoken
9090 + ": startingWindow=" + wtoken.startingWindow
9091 + " startingView=" + wtoken.startingView);
9092
9093 if (wtoken.startingWindow == null) {
9094 continue;
9095 }
9096
9097 view = wtoken.startingView;
9098 token = wtoken.token;
9099 wtoken.startingData = null;
9100 wtoken.startingView = null;
9101 wtoken.startingWindow = null;
9102 }
9103
9104 try {
9105 mPolicy.removeStartingWindow(token, view);
9106 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009107 Slog.w(TAG, "Exception when removing starting window", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009108 }
9109 }
9110 } break;
9111
9112 case REPORT_APPLICATION_TOKEN_WINDOWS: {
9113 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
9114
9115 boolean nowVisible = msg.arg1 != 0;
9116 boolean nowGone = msg.arg2 != 0;
9117
9118 try {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009119 if (DEBUG_VISIBILITY) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009120 TAG, "Reporting visible in " + wtoken
9121 + " visible=" + nowVisible
9122 + " gone=" + nowGone);
9123 if (nowVisible) {
9124 wtoken.appToken.windowsVisible();
9125 } else {
9126 wtoken.appToken.windowsGone();
9127 }
9128 } catch (RemoteException ex) {
9129 }
9130 } break;
Romain Guy06882f82009-06-10 13:36:04 -07009131
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009132 case WINDOW_FREEZE_TIMEOUT: {
9133 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009134 Slog.w(TAG, "Window freeze timeout expired.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009135 int i = mWindows.size();
9136 while (i > 0) {
9137 i--;
9138 WindowState w = (WindowState)mWindows.get(i);
9139 if (w.mOrientationChanging) {
9140 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009141 Slog.w(TAG, "Force clearing orientation change: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009142 }
9143 }
9144 performLayoutAndPlaceSurfacesLocked();
9145 }
9146 break;
9147 }
Romain Guy06882f82009-06-10 13:36:04 -07009148
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009149 case HOLD_SCREEN_CHANGED: {
9150 Session oldHold;
9151 Session newHold;
9152 synchronized (mWindowMap) {
9153 oldHold = mLastReportedHold;
9154 newHold = (Session)msg.obj;
9155 mLastReportedHold = newHold;
9156 }
Romain Guy06882f82009-06-10 13:36:04 -07009157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009158 if (oldHold != newHold) {
9159 try {
9160 if (oldHold != null) {
9161 mBatteryStats.noteStopWakelock(oldHold.mUid,
9162 "window",
9163 BatteryStats.WAKE_TYPE_WINDOW);
9164 }
9165 if (newHold != null) {
9166 mBatteryStats.noteStartWakelock(newHold.mUid,
9167 "window",
9168 BatteryStats.WAKE_TYPE_WINDOW);
9169 }
9170 } catch (RemoteException e) {
9171 }
9172 }
9173 break;
9174 }
Romain Guy06882f82009-06-10 13:36:04 -07009175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009176 case APP_TRANSITION_TIMEOUT: {
9177 synchronized (mWindowMap) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009178 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009179 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009180 "*** APP TRANSITION TIMEOUT");
9181 mAppTransitionReady = true;
9182 mAppTransitionTimeout = true;
9183 performLayoutAndPlaceSurfacesLocked();
9184 }
9185 }
9186 break;
9187 }
Romain Guy06882f82009-06-10 13:36:04 -07009188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009189 case PERSIST_ANIMATION_SCALE: {
9190 Settings.System.putFloat(mContext.getContentResolver(),
9191 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
9192 Settings.System.putFloat(mContext.getContentResolver(),
9193 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
9194 break;
9195 }
Romain Guy06882f82009-06-10 13:36:04 -07009196
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009197 case FORCE_GC: {
9198 synchronized(mWindowMap) {
9199 if (mAnimationPending) {
9200 // If we are animating, don't do the gc now but
9201 // delay a bit so we don't interrupt the animation.
9202 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
9203 2000);
9204 return;
9205 }
9206 // If we are currently rotating the display, it will
9207 // schedule a new message when done.
9208 if (mDisplayFrozen) {
9209 return;
9210 }
9211 mFreezeGcPending = 0;
9212 }
9213 Runtime.getRuntime().gc();
9214 break;
9215 }
Romain Guy06882f82009-06-10 13:36:04 -07009216
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009217 case ENABLE_SCREEN: {
9218 performEnableScreen();
9219 break;
9220 }
Romain Guy06882f82009-06-10 13:36:04 -07009221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009222 case APP_FREEZE_TIMEOUT: {
9223 synchronized (mWindowMap) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009224 Slog.w(TAG, "App freeze timeout expired.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009225 int i = mAppTokens.size();
9226 while (i > 0) {
9227 i--;
9228 AppWindowToken tok = mAppTokens.get(i);
9229 if (tok.freezingScreen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009230 Slog.w(TAG, "Force clearing freeze: " + tok);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009231 unsetAppFreezingScreenLocked(tok, true, true);
9232 }
9233 }
9234 }
9235 break;
9236 }
Romain Guy06882f82009-06-10 13:36:04 -07009237
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009238 case SEND_NEW_CONFIGURATION: {
9239 removeMessages(SEND_NEW_CONFIGURATION);
9240 sendNewConfiguration();
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07009241 break;
9242 }
Romain Guy06882f82009-06-10 13:36:04 -07009243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009244 }
9245 }
9246 }
9247
9248 // -------------------------------------------------------------
9249 // IWindowManager API
9250 // -------------------------------------------------------------
9251
9252 public IWindowSession openSession(IInputMethodClient client,
9253 IInputContext inputContext) {
9254 if (client == null) throw new IllegalArgumentException("null client");
9255 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
9256 return new Session(client, inputContext);
9257 }
9258
9259 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
9260 synchronized (mWindowMap) {
9261 // The focus for the client is the window immediately below
9262 // where we would place the input method window.
9263 int idx = findDesiredInputMethodWindowIndexLocked(false);
9264 WindowState imFocus;
9265 if (idx > 0) {
9266 imFocus = (WindowState)mWindows.get(idx-1);
9267 if (imFocus != null) {
9268 if (imFocus.mSession.mClient != null &&
9269 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
9270 return true;
9271 }
9272 }
9273 }
9274 }
9275 return false;
9276 }
Romain Guy06882f82009-06-10 13:36:04 -07009277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009278 // -------------------------------------------------------------
9279 // Internals
9280 // -------------------------------------------------------------
9281
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009282 final WindowState windowForClientLocked(Session session, IWindow client,
9283 boolean throwOnError) {
9284 return windowForClientLocked(session, client.asBinder(), throwOnError);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009285 }
Romain Guy06882f82009-06-10 13:36:04 -07009286
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009287 final WindowState windowForClientLocked(Session session, IBinder client,
9288 boolean throwOnError) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009289 WindowState win = mWindowMap.get(client);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009290 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009291 TAG, "Looking up client " + client + ": " + win);
9292 if (win == null) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009293 RuntimeException ex = new IllegalArgumentException(
9294 "Requested window " + client + " does not exist");
9295 if (throwOnError) {
9296 throw ex;
9297 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009298 Slog.w(TAG, "Failed looking up window", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009299 return null;
9300 }
9301 if (session != null && win.mSession != session) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009302 RuntimeException ex = new IllegalArgumentException(
9303 "Requested window " + client + " is in session " +
9304 win.mSession + ", not " + session);
9305 if (throwOnError) {
9306 throw ex;
9307 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009308 Slog.w(TAG, "Failed looking up window", ex);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009309 return null;
9310 }
9311
9312 return win;
9313 }
9314
Dianne Hackborna8f60182009-09-01 19:01:50 -07009315 final void rebuildAppWindowListLocked() {
9316 int NW = mWindows.size();
9317 int i;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009318 int lastWallpaper = -1;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009319 int numRemoved = 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009320
Dianne Hackborna8f60182009-09-01 19:01:50 -07009321 // First remove all existing app windows.
9322 i=0;
9323 while (i < NW) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009324 WindowState w = (WindowState)mWindows.get(i);
9325 if (w.mAppToken != null) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009326 WindowState win = (WindowState)mWindows.remove(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009327 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009328 "Rebuild removing window: " + win);
Dianne Hackborna8f60182009-09-01 19:01:50 -07009329 NW--;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009330 numRemoved++;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009331 continue;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009332 } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER
9333 && lastWallpaper == i-1) {
9334 lastWallpaper = i;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009335 }
9336 i++;
9337 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009338
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009339 // The wallpaper window(s) typically live at the bottom of the stack,
9340 // so skip them before adding app tokens.
9341 lastWallpaper++;
9342 i = lastWallpaper;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009343
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009344 // First add all of the exiting app tokens... these are no longer
9345 // in the main app list, but still have windows shown. We put them
9346 // in the back because now that the animation is over we no longer
9347 // will care about them.
9348 int NT = mExitingAppTokens.size();
Dianne Hackborna8f60182009-09-01 19:01:50 -07009349 for (int j=0; j<NT; j++) {
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009350 i = reAddAppWindowsLocked(i, mExitingAppTokens.get(j));
9351 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009352
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009353 // And add in the still active app tokens in Z order.
9354 NT = mAppTokens.size();
9355 for (int j=0; j<NT; j++) {
9356 i = reAddAppWindowsLocked(i, mAppTokens.get(j));
Dianne Hackborna8f60182009-09-01 19:01:50 -07009357 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009358
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009359 i -= lastWallpaper;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009360 if (i != numRemoved) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009361 Slog.w(TAG, "Rebuild removed " + numRemoved
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009362 + " windows but added " + i);
9363 }
Dianne Hackborna8f60182009-09-01 19:01:50 -07009364 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009366 private final void assignLayersLocked() {
9367 int N = mWindows.size();
9368 int curBaseLayer = 0;
9369 int curLayer = 0;
9370 int i;
Romain Guy06882f82009-06-10 13:36:04 -07009371
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009372 for (i=0; i<N; i++) {
9373 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn7341d7a2009-08-14 11:37:52 -07009374 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
9375 || (i > 0 && w.mIsWallpaper)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009376 curLayer += WINDOW_LAYER_MULTIPLIER;
9377 w.mLayer = curLayer;
9378 } else {
9379 curBaseLayer = curLayer = w.mBaseLayer;
9380 w.mLayer = curLayer;
9381 }
9382 if (w.mTargetAppToken != null) {
9383 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
9384 } else if (w.mAppToken != null) {
9385 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
9386 } else {
9387 w.mAnimLayer = w.mLayer;
9388 }
9389 if (w.mIsImWindow) {
9390 w.mAnimLayer += mInputMethodAnimLayerAdjustment;
Dianne Hackborn759a39e2009-08-09 17:20:27 -07009391 } else if (w.mIsWallpaper) {
9392 w.mAnimLayer += mWallpaperAnimLayerAdjustment;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009393 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009394 if (DEBUG_LAYERS) Slog.v(TAG, "Assign layer " + w + ": "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009395 + w.mAnimLayer);
9396 //System.out.println(
9397 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
9398 }
9399 }
9400
9401 private boolean mInLayout = false;
9402 private final void performLayoutAndPlaceSurfacesLocked() {
9403 if (mInLayout) {
Dave Bortcfe65242009-04-09 14:51:04 -07009404 if (DEBUG) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009405 throw new RuntimeException("Recursive call!");
9406 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009407 Slog.w(TAG, "performLayoutAndPlaceSurfacesLocked called while in layout");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009408 return;
9409 }
9410
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009411 if (mWaitingForConfig) {
9412 // Our configuration has changed (most likely rotation), but we
9413 // don't yet have the complete configuration to report to
9414 // applications. Don't do any window layout until we have it.
9415 return;
9416 }
9417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009418 boolean recoveringMemory = false;
9419 if (mForceRemoves != null) {
9420 recoveringMemory = true;
9421 // Wait a little it for things to settle down, and off we go.
9422 for (int i=0; i<mForceRemoves.size(); i++) {
9423 WindowState ws = mForceRemoves.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009424 Slog.i(TAG, "Force removing: " + ws);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009425 removeWindowInnerLocked(ws.mSession, ws);
9426 }
9427 mForceRemoves = null;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009428 Slog.w(TAG, "Due to memory failure, waiting a bit for next layout");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009429 Object tmp = new Object();
9430 synchronized (tmp) {
9431 try {
9432 tmp.wait(250);
9433 } catch (InterruptedException e) {
9434 }
9435 }
9436 }
Romain Guy06882f82009-06-10 13:36:04 -07009437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009438 mInLayout = true;
9439 try {
9440 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
Romain Guy06882f82009-06-10 13:36:04 -07009441
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009442 int i = mPendingRemove.size()-1;
9443 if (i >= 0) {
9444 while (i >= 0) {
9445 WindowState w = mPendingRemove.get(i);
9446 removeWindowInnerLocked(w.mSession, w);
9447 i--;
9448 }
9449 mPendingRemove.clear();
9450
9451 mInLayout = false;
9452 assignLayersLocked();
9453 mLayoutNeeded = true;
9454 performLayoutAndPlaceSurfacesLocked();
9455
9456 } else {
9457 mInLayout = false;
9458 if (mLayoutNeeded) {
9459 requestAnimationLocked(0);
9460 }
9461 }
9462 } catch (RuntimeException e) {
9463 mInLayout = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009464 Slog.e(TAG, "Unhandled exception while layout out windows", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009465 }
9466 }
9467
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009468 private final int performLayoutLockedInner() {
9469 if (!mLayoutNeeded) {
9470 return 0;
9471 }
9472
9473 mLayoutNeeded = false;
9474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009475 final int dw = mDisplay.getWidth();
9476 final int dh = mDisplay.getHeight();
9477
9478 final int N = mWindows.size();
9479 int i;
9480
Joe Onorato8a9b2202010-02-26 18:56:32 -08009481 if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed="
Dianne Hackborn9b52a212009-12-11 14:51:35 -08009482 + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
9483
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009484 mPolicy.beginLayoutLw(dw, dh);
Romain Guy06882f82009-06-10 13:36:04 -07009485
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009486 int seq = mLayoutSeq+1;
9487 if (seq < 0) seq = 0;
9488 mLayoutSeq = seq;
9489
9490 // First perform layout of any root windows (not attached
9491 // to another window).
9492 int topAttached = -1;
9493 for (i = N-1; i >= 0; i--) {
9494 WindowState win = (WindowState) mWindows.get(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009495
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009496 // Don't do layout of a window if it is not visible, or
9497 // soon won't be visible, to avoid wasting time and funky
9498 // changes while a window is animating away.
9499 final AppWindowToken atoken = win.mAppToken;
9500 final boolean gone = win.mViewVisibility == View.GONE
9501 || !win.mRelayoutCalled
9502 || win.mRootToken.hidden
9503 || (atoken != null && atoken.hiddenRequested)
9504 || win.mAttachedHidden
9505 || win.mExiting || win.mDestroying;
9506
9507 if (!win.mLayoutAttached) {
9508 if (DEBUG_LAYOUT) Slog.v(TAG, "First pass " + win
9509 + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
9510 + " mLayoutAttached=" + win.mLayoutAttached);
9511 if (DEBUG_LAYOUT && gone) Slog.v(TAG, " (mViewVisibility="
9512 + win.mViewVisibility + " mRelayoutCalled="
9513 + win.mRelayoutCalled + " hidden="
9514 + win.mRootToken.hidden + " hiddenRequested="
9515 + (atoken != null && atoken.hiddenRequested)
9516 + " mAttachedHidden=" + win.mAttachedHidden);
9517 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009518
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009519 // If this view is GONE, then skip it -- keep the current
9520 // frame, and let the caller know so they can ignore it
9521 // if they want. (We do the normal layout for INVISIBLE
9522 // windows, since that means "perform layout as normal,
9523 // just don't display").
9524 if (!gone || !win.mHaveFrame) {
Dianne Hackborne36d6e22010-02-17 19:46:25 -08009525 if (!win.mLayoutAttached) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009526 mPolicy.layoutWindowLw(win, win.mAttrs, null);
9527 win.mLayoutSeq = seq;
9528 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
9529 + win.mFrame + " mContainingFrame="
9530 + win.mContainingFrame + " mDisplayFrame="
9531 + win.mDisplayFrame);
9532 } else {
9533 if (topAttached < 0) topAttached = i;
Dianne Hackborn9bfb7072009-09-22 11:37:40 -07009534 }
Dianne Hackborn958b9ad2009-03-31 18:00:36 -07009535 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009536 }
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009537
9538 // Now perform layout of attached windows, which usually
9539 // depend on the position of the window they are attached to.
9540 // XXX does not deal with windows that are attached to windows
9541 // that are themselves attached.
9542 for (i = topAttached; i >= 0; i--) {
9543 WindowState win = (WindowState) mWindows.get(i);
9544
9545 // If this view is GONE, then skip it -- keep the current
9546 // frame, and let the caller know so they can ignore it
9547 // if they want. (We do the normal layout for INVISIBLE
9548 // windows, since that means "perform layout as normal,
9549 // just don't display").
9550 if (win.mLayoutAttached) {
9551 if (DEBUG_LAYOUT) Slog.v(TAG, "Second pass " + win
9552 + " mHaveFrame=" + win.mHaveFrame
9553 + " mViewVisibility=" + win.mViewVisibility
9554 + " mRelayoutCalled=" + win.mRelayoutCalled);
9555 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
9556 || !win.mHaveFrame) {
9557 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
9558 win.mLayoutSeq = seq;
9559 if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
9560 + win.mFrame + " mContainingFrame="
9561 + win.mContainingFrame + " mDisplayFrame="
9562 + win.mDisplayFrame);
9563 }
9564 }
9565 }
9566
9567 return mPolicy.finishLayoutLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009568 }
Romain Guy06882f82009-06-10 13:36:04 -07009569
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009570 private final void performLayoutAndPlaceSurfacesLockedInner(
9571 boolean recoveringMemory) {
9572 final long currentTime = SystemClock.uptimeMillis();
9573 final int dw = mDisplay.getWidth();
9574 final int dh = mDisplay.getHeight();
9575
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009576 int i;
9577
Dianne Hackbornb601ce12010-03-01 23:36:02 -08009578 if (mFocusMayChange) {
9579 mFocusMayChange = false;
9580 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
9581 }
9582
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009583 if (mFxSession == null) {
9584 mFxSession = new SurfaceSession();
9585 }
Romain Guy06882f82009-06-10 13:36:04 -07009586
Joe Onorato8a9b2202010-02-26 18:56:32 -08009587 if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009588
9589 // Initialize state of exiting tokens.
9590 for (i=mExitingTokens.size()-1; i>=0; i--) {
9591 mExitingTokens.get(i).hasVisible = false;
9592 }
9593
9594 // Initialize state of exiting applications.
9595 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
9596 mExitingAppTokens.get(i).hasVisible = false;
9597 }
9598
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009599 boolean orientationChangeComplete = true;
9600 Session holdScreen = null;
9601 float screenBrightness = -1;
Mike Lockwoodfb73f792009-11-20 11:31:18 -05009602 float buttonBrightness = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009603 boolean focusDisplayed = false;
9604 boolean animating = false;
9605
9606 Surface.openTransaction();
9607 try {
Dianne Hackbornde2606d2009-12-18 16:53:55 -08009608 boolean wallpaperForceHidingChanged = false;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009609 int repeats = 0;
9610 int changes = 0;
9611
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009612 do {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009613 repeats++;
9614 if (repeats > 6) {
9615 Slog.w(TAG, "Animation repeat aborted after too many iterations");
9616 mLayoutNeeded = false;
9617 break;
9618 }
9619
9620 if ((changes&(WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER
9621 | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG
9622 | WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT)) != 0) {
9623 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
9624 if ((adjustWallpaperWindowsLocked()&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
9625 assignLayersLocked();
9626 mLayoutNeeded = true;
9627 }
9628 }
9629 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
9630 if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
9631 if (updateOrientationFromAppTokensLocked()) {
9632 mLayoutNeeded = true;
9633 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
9634 }
9635 }
9636 if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT) != 0) {
9637 mLayoutNeeded = true;
9638 }
9639 }
9640
9641 // FIRST LOOP: Perform a layout, if needed.
9642 if (repeats < 4) {
9643 changes = performLayoutLockedInner();
9644 if (changes != 0) {
9645 continue;
9646 }
9647 } else {
9648 Slog.w(TAG, "Layout repeat skipped after too many iterations");
9649 changes = 0;
9650 }
9651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009652 final int transactionSequence = ++mTransactionSequence;
9653
9654 // Update animations of all applications, including those
9655 // associated with exiting/removed apps
9656 boolean tokensAnimating = false;
9657 final int NAT = mAppTokens.size();
9658 for (i=0; i<NAT; i++) {
9659 if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
9660 tokensAnimating = true;
9661 }
9662 }
9663 final int NEAT = mExitingAppTokens.size();
9664 for (i=0; i<NEAT; i++) {
9665 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
9666 tokensAnimating = true;
9667 }
9668 }
9669
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009670 // SECOND LOOP: Execute animations and update visibility of windows.
9671
Joe Onorato8a9b2202010-02-26 18:56:32 -08009672 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: seq="
Dianne Hackbornde2606d2009-12-18 16:53:55 -08009673 + transactionSequence + " tokensAnimating="
9674 + tokensAnimating);
9675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009676 animating = tokensAnimating;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009677
9678 boolean tokenMayBeDrawn = false;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009679 boolean wallpaperMayChange = false;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009680 boolean forceHiding = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009681
9682 mPolicy.beginAnimationLw(dw, dh);
9683
Dianne Hackbornbdd52b22009-09-02 21:46:19 -07009684 final int N = mWindows.size();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009685
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009686 for (i=N-1; i>=0; i--) {
9687 WindowState w = (WindowState)mWindows.get(i);
9688
9689 final WindowManager.LayoutParams attrs = w.mAttrs;
9690
9691 if (w.mSurface != null) {
9692 // Execute animation.
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009693 if (w.commitFinishDrawingLocked(currentTime)) {
9694 if ((w.mAttrs.flags
9695 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009696 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -07009697 "First draw done in potential wallpaper target " + w);
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009698 wallpaperMayChange = true;
9699 }
9700 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009701
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009702 boolean wasAnimating = w.mAnimating;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009703 if (w.stepAnimationLocked(currentTime, dw, dh)) {
9704 animating = true;
9705 //w.dump(" ");
9706 }
Dianne Hackborn6136b7e2009-09-18 01:53:49 -07009707 if (wasAnimating && !w.mAnimating && mWallpaperTarget == w) {
9708 wallpaperMayChange = true;
9709 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009710
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009711 if (mPolicy.doesForceHide(w, attrs)) {
9712 if (!wasAnimating && animating) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08009713 if (DEBUG_VISIBILITY) Slog.v(TAG,
9714 "Animation done that could impact force hide: "
9715 + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009716 wallpaperForceHidingChanged = true;
Dianne Hackbornb601ce12010-03-01 23:36:02 -08009717 mFocusMayChange = true;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009718 } else if (w.isReadyForDisplay() && w.mAnimation == null) {
9719 forceHiding = true;
9720 }
9721 } else if (mPolicy.canBeForceHidden(w, attrs)) {
9722 boolean changed;
9723 if (forceHiding) {
9724 changed = w.hideLw(false, false);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08009725 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
9726 "Now policy hidden: " + w);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009727 } else {
9728 changed = w.showLw(false, false);
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08009729 if (DEBUG_VISIBILITY && changed) Slog.v(TAG,
9730 "Now policy shown: " + w);
9731 if (changed) {
9732 if (wallpaperForceHidingChanged
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009733 && w.isVisibleNow() /*w.isReadyForDisplay()*/) {
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08009734 // Assume we will need to animate. If
9735 // we don't (because the wallpaper will
9736 // stay with the lock screen), then we will
9737 // clean up later.
9738 Animation a = mPolicy.createForceHideEnterAnimation();
9739 if (a != null) {
9740 w.setAnimation(a);
9741 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009742 }
Dianne Hackborn20cb56e2010-03-04 00:58:29 -08009743 if (mCurrentFocus == null ||
9744 mCurrentFocus.mLayer < w.mLayer) {
9745 // We are showing on to of the current
9746 // focus, so re-evaluate focus to make
9747 // sure it is correct.
9748 mFocusMayChange = true;
9749 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009750 }
9751 }
9752 if (changed && (attrs.flags
9753 & WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER) != 0) {
9754 wallpaperMayChange = true;
9755 }
9756 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009757
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009758 mPolicy.animatingWindowLw(w, attrs);
9759 }
9760
9761 final AppWindowToken atoken = w.mAppToken;
9762 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
9763 if (atoken.lastTransactionSequence != transactionSequence) {
9764 atoken.lastTransactionSequence = transactionSequence;
9765 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
9766 atoken.startingDisplayed = false;
9767 }
9768 if ((w.isOnScreen() || w.mAttrs.type
9769 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
9770 && !w.mExiting && !w.mDestroying) {
9771 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009772 Slog.v(TAG, "Eval win " + w + ": isDrawn="
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009773 + w.isDrawnLw()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009774 + ", isAnimating=" + w.isAnimating());
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009775 if (!w.isDrawnLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009776 Slog.v(TAG, "Not displayed: s=" + w.mSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009777 + " pv=" + w.mPolicyVisibility
9778 + " dp=" + w.mDrawPending
9779 + " cdp=" + w.mCommitDrawPending
9780 + " ah=" + w.mAttachedHidden
9781 + " th=" + atoken.hiddenRequested
9782 + " a=" + w.mAnimating);
9783 }
9784 }
9785 if (w != atoken.startingWindow) {
9786 if (!atoken.freezingScreen || !w.mAppFreezing) {
9787 atoken.numInterestingWindows++;
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009788 if (w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009789 atoken.numDrawnWindows++;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009790 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009791 "tokenMayBeDrawn: " + atoken
9792 + " freezingScreen=" + atoken.freezingScreen
9793 + " mAppFreezing=" + w.mAppFreezing);
9794 tokenMayBeDrawn = true;
9795 }
9796 }
Dianne Hackborn7433e8a2009-09-27 13:21:20 -07009797 } else if (w.isDrawnLw()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009798 atoken.startingDisplayed = true;
9799 }
9800 }
9801 } else if (w.mReadyToShow) {
9802 w.performShowLocked();
9803 }
9804 }
9805
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009806 changes |= mPolicy.finishAnimationLw();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009807
9808 if (tokenMayBeDrawn) {
9809 // See if any windows have been drawn, so they (and others
9810 // associated with them) can now be shown.
9811 final int NT = mTokenList.size();
9812 for (i=0; i<NT; i++) {
9813 AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
9814 if (wtoken == null) {
9815 continue;
9816 }
9817 if (wtoken.freezingScreen) {
9818 int numInteresting = wtoken.numInterestingWindows;
9819 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009820 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009821 "allDrawn: " + wtoken
9822 + " interesting=" + numInteresting
9823 + " drawn=" + wtoken.numDrawnWindows);
9824 wtoken.showAllWindowsLocked();
9825 unsetAppFreezingScreenLocked(wtoken, false, true);
9826 orientationChangeComplete = true;
9827 }
9828 } else if (!wtoken.allDrawn) {
9829 int numInteresting = wtoken.numInterestingWindows;
9830 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009831 if (DEBUG_VISIBILITY) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009832 "allDrawn: " + wtoken
9833 + " interesting=" + numInteresting
9834 + " drawn=" + wtoken.numDrawnWindows);
9835 wtoken.allDrawn = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -08009836 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009837
9838 // We can now show all of the drawn windows!
9839 if (!mOpeningApps.contains(wtoken)) {
9840 wtoken.showAllWindowsLocked();
9841 }
9842 }
9843 }
9844 }
9845 }
9846
9847 // If we are ready to perform an app transition, check through
9848 // all of the app tokens to be shown and see if they are ready
9849 // to go.
9850 if (mAppTransitionReady) {
9851 int NN = mOpeningApps.size();
9852 boolean goodToGo = true;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009853 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009854 "Checking " + NN + " opening apps (frozen="
9855 + mDisplayFrozen + " timeout="
9856 + mAppTransitionTimeout + ")...");
9857 if (!mDisplayFrozen && !mAppTransitionTimeout) {
9858 // If the display isn't frozen, wait to do anything until
9859 // all of the apps are ready. Otherwise just go because
9860 // we'll unfreeze the display when everyone is ready.
9861 for (i=0; i<NN && goodToGo; i++) {
9862 AppWindowToken wtoken = mOpeningApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -08009863 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009864 "Check opening app" + wtoken + ": allDrawn="
9865 + wtoken.allDrawn + " startingDisplayed="
9866 + wtoken.startingDisplayed);
9867 if (!wtoken.allDrawn && !wtoken.startingDisplayed
9868 && !wtoken.startingMoved) {
9869 goodToGo = false;
9870 }
9871 }
9872 }
9873 if (goodToGo) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009874 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "**** GOOD TO GO");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009875 int transit = mNextAppTransition;
9876 if (mSkipAppTransitionAnimation) {
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009877 transit = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009878 }
Dianne Hackbornbfe319e2009-09-21 00:34:05 -07009879 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009880 mAppTransitionReady = false;
Dianne Hackborna8f60182009-09-01 19:01:50 -07009881 mAppTransitionRunning = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009882 mAppTransitionTimeout = false;
9883 mStartingIconInTransition = false;
9884 mSkipAppTransitionAnimation = false;
9885
9886 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
9887
Dianne Hackborna8f60182009-09-01 19:01:50 -07009888 // If there are applications waiting to come to the
9889 // top of the stack, now is the time to move their windows.
9890 // (Note that we don't do apps going to the bottom
9891 // here -- we want to keep their windows in the old
9892 // Z-order until the animation completes.)
9893 if (mToTopApps.size() > 0) {
9894 NN = mAppTokens.size();
9895 for (i=0; i<NN; i++) {
9896 AppWindowToken wtoken = mAppTokens.get(i);
9897 if (wtoken.sendingToTop) {
9898 wtoken.sendingToTop = false;
9899 moveAppWindowsLocked(wtoken, NN, false);
9900 }
9901 }
9902 mToTopApps.clear();
9903 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009904
Dianne Hackborn25994b42009-09-04 14:21:19 -07009905 WindowState oldWallpaper = mWallpaperTarget;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009906
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009907 adjustWallpaperWindowsLocked();
Dianne Hackborn6c3f5712009-08-25 18:42:59 -07009908 wallpaperMayChange = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009909
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009910 // The top-most window will supply the layout params,
9911 // and we will determine it below.
9912 LayoutParams animLp = null;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009913 AppWindowToken animToken = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009914 int bestAnimLayer = -1;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009915
Joe Onorato8a9b2202010-02-26 18:56:32 -08009916 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn3be63c02009-08-20 19:31:38 -07009917 "New wallpaper target=" + mWallpaperTarget
9918 + ", lower target=" + mLowerWallpaperTarget
9919 + ", upper target=" + mUpperWallpaperTarget);
Dianne Hackborn25994b42009-09-04 14:21:19 -07009920 int foundWallpapers = 0;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009921 // Do a first pass through the tokens for two
9922 // things:
9923 // (1) Determine if both the closing and opening
9924 // app token sets are wallpaper targets, in which
9925 // case special animations are needed
9926 // (since the wallpaper needs to stay static
9927 // behind them).
9928 // (2) Find the layout params of the top-most
9929 // application window in the tokens, which is
9930 // what will control the animation theme.
9931 final int NC = mClosingApps.size();
9932 NN = NC + mOpeningApps.size();
9933 for (i=0; i<NN; i++) {
9934 AppWindowToken wtoken;
9935 int mode;
9936 if (i < NC) {
9937 wtoken = mClosingApps.get(i);
9938 mode = 1;
9939 } else {
9940 wtoken = mOpeningApps.get(i-NC);
9941 mode = 2;
9942 }
9943 if (mLowerWallpaperTarget != null) {
9944 if (mLowerWallpaperTarget.mAppToken == wtoken
9945 || mUpperWallpaperTarget.mAppToken == wtoken) {
9946 foundWallpapers |= mode;
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07009947 }
9948 }
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009949 if (wtoken.appFullscreen) {
9950 WindowState ws = wtoken.findMainWindow();
9951 if (ws != null) {
9952 // If this is a compatibility mode
9953 // window, we will always use its anim.
9954 if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
9955 animLp = ws.mAttrs;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009956 animToken = ws.mAppToken;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009957 bestAnimLayer = Integer.MAX_VALUE;
9958 } else if (ws.mLayer > bestAnimLayer) {
9959 animLp = ws.mAttrs;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009960 animToken = ws.mAppToken;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07009961 bestAnimLayer = ws.mLayer;
9962 }
Dianne Hackborn25994b42009-09-04 14:21:19 -07009963 }
Dianne Hackbornf8fbdb62009-08-19 12:39:43 -07009964 }
9965 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009966
Dianne Hackborn25994b42009-09-04 14:21:19 -07009967 if (foundWallpapers == 3) {
Joe Onorato8a9b2202010-02-26 18:56:32 -08009968 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07009969 "Wallpaper animation!");
9970 switch (transit) {
9971 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
9972 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
9973 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
9974 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_OPEN;
9975 break;
9976 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
9977 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
9978 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
9979 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_INTRA_CLOSE;
9980 break;
9981 }
Joe Onorato8a9b2202010-02-26 18:56:32 -08009982 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07009983 "New transit: " + transit);
9984 } else if (oldWallpaper != null) {
9985 // We are transitioning from an activity with
9986 // a wallpaper to one without.
9987 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_CLOSE;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009988 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07009989 "New transit away from wallpaper: " + transit);
9990 } else if (mWallpaperTarget != null) {
9991 // We are transitioning from an activity without
9992 // a wallpaper to now showing the wallpaper
9993 transit = WindowManagerPolicy.TRANSIT_WALLPAPER_OPEN;
Joe Onorato8a9b2202010-02-26 18:56:32 -08009994 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
Dianne Hackborn25994b42009-09-04 14:21:19 -07009995 "New transit into wallpaper: " + transit);
9996 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08009997
Dianne Hackborn3b3e1452009-09-24 19:22:12 -07009998 if ((transit&WindowManagerPolicy.TRANSIT_ENTER_MASK) != 0) {
9999 mLastEnterAnimToken = animToken;
10000 mLastEnterAnimParams = animLp;
10001 } else if (mLastEnterAnimParams != null) {
10002 animLp = mLastEnterAnimParams;
10003 mLastEnterAnimToken = null;
10004 mLastEnterAnimParams = null;
10005 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010006
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010007 // If all closing windows are obscured, then there is
10008 // no need to do an animation. This is the case, for
10009 // example, when this transition is being done behind
10010 // the lock screen.
10011 if (!mPolicy.allowAppAnimationsLw()) {
10012 animLp = null;
10013 }
10014
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010015 NN = mOpeningApps.size();
10016 for (i=0; i<NN; i++) {
10017 AppWindowToken wtoken = mOpeningApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010018 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010019 "Now opening app" + wtoken);
10020 wtoken.reportedVisible = false;
10021 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -070010022 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010023 setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010024 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070010025 wtoken.waitingToShow = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010026 wtoken.showAllWindowsLocked();
10027 }
10028 NN = mClosingApps.size();
10029 for (i=0; i<NN; i++) {
10030 AppWindowToken wtoken = mClosingApps.get(i);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010031 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010032 "Now closing app" + wtoken);
10033 wtoken.inPendingTransaction = false;
Dianne Hackborn83360b32009-08-24 18:43:32 -070010034 wtoken.animation = null;
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -070010035 setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010036 wtoken.updateReportedVisibilityLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070010037 wtoken.waitingToHide = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010038 // Force the allDrawn flag, because we want to start
10039 // this guy's animations regardless of whether it's
10040 // gotten drawn.
10041 wtoken.allDrawn = true;
10042 }
10043
Dianne Hackborn8b571a82009-09-25 16:09:43 -070010044 mNextAppTransitionPackage = null;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010045
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010046 mOpeningApps.clear();
10047 mClosingApps.clear();
10048
10049 // This has changed the visibility of windows, so perform
10050 // a new layout to get them all up-to-date.
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010051 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010052 mLayoutNeeded = true;
Dianne Hackborn20583ff2009-07-27 21:51:05 -070010053 if (!moveInputMethodWindowsIfNeededLocked(true)) {
10054 assignLayersLocked();
10055 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010056 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010057 mFocusMayChange = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010058 }
10059 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010060
Dianne Hackborn16064f92010-03-25 00:47:24 -070010061 int adjResult = 0;
10062
Dianne Hackborna8f60182009-09-01 19:01:50 -070010063 if (!animating && mAppTransitionRunning) {
10064 // We have finished the animation of an app transition. To do
10065 // this, we have delayed a lot of operations like showing and
10066 // hiding apps, moving apps in Z-order, etc. The app token list
10067 // reflects the correct Z-order, but the window list may now
10068 // be out of sync with it. So here we will just rebuild the
10069 // entire app window list. Fun!
10070 mAppTransitionRunning = false;
10071 // Clear information about apps that were moving.
10072 mToBottomApps.clear();
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010073
Dianne Hackborna8f60182009-09-01 19:01:50 -070010074 rebuildAppWindowListLocked();
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010075 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn16064f92010-03-25 00:47:24 -070010076 adjResult |= ADJUST_WALLPAPER_LAYERS_CHANGED;
Dianne Hackborna8f60182009-09-01 19:01:50 -070010077 moveInputMethodWindowsIfNeededLocked(false);
10078 wallpaperMayChange = true;
Suchi Amalapurapuc9568e32009-11-05 18:51:16 -080010079 // Since the window list has been rebuilt, focus might
10080 // have to be recomputed since the actual order of windows
10081 // might have changed again.
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010082 mFocusMayChange = true;
Dianne Hackborna8f60182009-09-01 19:01:50 -070010083 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010084
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010085 if (wallpaperForceHidingChanged && changes == 0 && !mAppTransitionReady) {
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010086 // At this point, there was a window with a wallpaper that
10087 // was force hiding other windows behind it, but now it
10088 // is going away. This may be simple -- just animate
10089 // away the wallpaper and its window -- or it may be
10090 // hard -- the wallpaper now needs to be shown behind
10091 // something that was hidden.
10092 WindowState oldWallpaper = mWallpaperTarget;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010093 if (mLowerWallpaperTarget != null
10094 && mLowerWallpaperTarget.mAppToken != null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010095 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010096 "wallpaperForceHiding changed with lower="
10097 + mLowerWallpaperTarget);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010098 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010099 "hidden=" + mLowerWallpaperTarget.mAppToken.hidden +
10100 " hiddenRequested=" + mLowerWallpaperTarget.mAppToken.hiddenRequested);
10101 if (mLowerWallpaperTarget.mAppToken.hidden) {
10102 // The lower target has become hidden before we
10103 // actually started the animation... let's completely
10104 // re-evaluate everything.
10105 mLowerWallpaperTarget = mUpperWallpaperTarget = null;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010106 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010107 }
10108 }
Dianne Hackborn16064f92010-03-25 00:47:24 -070010109 adjResult |= adjustWallpaperWindowsLocked();
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010110 wallpaperMayChange = false;
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010111 wallpaperForceHidingChanged = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010112 if (DEBUG_WALLPAPER) Slog.v(TAG, "****** OLD: " + oldWallpaper
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010113 + " NEW: " + mWallpaperTarget
10114 + " LOWER: " + mLowerWallpaperTarget);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010115 if (mLowerWallpaperTarget == null) {
10116 // Whoops, we don't need a special wallpaper animation.
10117 // Clear them out.
10118 forceHiding = false;
10119 for (i=N-1; i>=0; i--) {
10120 WindowState w = (WindowState)mWindows.get(i);
10121 if (w.mSurface != null) {
10122 final WindowManager.LayoutParams attrs = w.mAttrs;
Suchi Amalapurapuc03d28b2009-10-28 14:32:05 -070010123 if (mPolicy.doesForceHide(w, attrs) && w.isVisibleLw()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010124 if (DEBUG_FOCUS) Slog.i(TAG, "win=" + w + " force hides other windows");
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010125 forceHiding = true;
10126 } else if (mPolicy.canBeForceHidden(w, attrs)) {
10127 if (!w.mAnimating) {
10128 // We set the animation above so it
10129 // is not yet running.
10130 w.clearAnimation();
10131 }
10132 }
10133 }
10134 }
10135 }
10136 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010137
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010138 if (wallpaperMayChange) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010139 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010140 "Wallpaper may change! Adjusting");
Dianne Hackborn16064f92010-03-25 00:47:24 -070010141 adjResult |= adjustWallpaperWindowsLocked();
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010142 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010143
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010144 if ((adjResult&ADJUST_WALLPAPER_LAYERS_CHANGED) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010145 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010146 "Wallpaper layer changed: assigning layers + relayout");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010147 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010148 assignLayersLocked();
10149 } else if ((adjResult&ADJUST_WALLPAPER_VISIBILITY_CHANGED) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010150 if (DEBUG_WALLPAPER) Slog.v(TAG,
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010151 "Wallpaper visibility changed: relayout");
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010152 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010153 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010154
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010155 if (mFocusMayChange) {
10156 mFocusMayChange = false;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010157 if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010158 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010159 adjResult = 0;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010160 }
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010161 }
10162
10163 if (mLayoutNeeded) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010164 changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
Dianne Hackborn6c3f5712009-08-25 18:42:59 -070010165 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010166
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010167 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
10168 + Integer.toHexString(changes));
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010169
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010170 } while (changes != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010171
10172 // THIRD LOOP: Update the surfaces of all windows.
10173
10174 final boolean someoneLosingFocus = mLosingFocus.size() != 0;
10175
10176 boolean obscured = false;
10177 boolean blurring = false;
10178 boolean dimming = false;
10179 boolean covered = false;
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070010180 boolean syswin = false;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010181 boolean backgroundFillerShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010182
Dianne Hackbornbdd52b22009-09-02 21:46:19 -070010183 final int N = mWindows.size();
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010184
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010185 for (i=N-1; i>=0; i--) {
10186 WindowState w = (WindowState)mWindows.get(i);
10187
10188 boolean displayed = false;
10189 final WindowManager.LayoutParams attrs = w.mAttrs;
10190 final int attrFlags = attrs.flags;
10191
10192 if (w.mSurface != null) {
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010193 // XXX NOTE: The logic here could be improved. We have
10194 // the decision about whether to resize a window separated
10195 // from whether to hide the surface. This can cause us to
10196 // resize a surface even if we are going to hide it. You
10197 // can see this by (1) holding device in landscape mode on
10198 // home screen; (2) tapping browser icon (device will rotate
10199 // to landscape; (3) tap home. The wallpaper will be resized
10200 // in step 2 but then immediately hidden, causing us to
10201 // have to resize and then redraw it again in step 3. It
10202 // would be nice to figure out how to avoid this, but it is
10203 // difficult because we do need to resize surfaces in some
10204 // cases while they are hidden such as when first showing a
10205 // window.
10206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010207 w.computeShownFrameLocked();
Joe Onorato8a9b2202010-02-26 18:56:32 -080010208 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010209 TAG, "Placing surface #" + i + " " + w.mSurface
10210 + ": new=" + w.mShownFrame + ", old="
10211 + w.mLastShownFrame);
10212
10213 boolean resize;
10214 int width, height;
10215 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
10216 resize = w.mLastRequestedWidth != w.mRequestedWidth ||
10217 w.mLastRequestedHeight != w.mRequestedHeight;
10218 // for a scaled surface, we just want to use
10219 // the requested size.
10220 width = w.mRequestedWidth;
10221 height = w.mRequestedHeight;
10222 w.mLastRequestedWidth = width;
10223 w.mLastRequestedHeight = height;
10224 w.mLastShownFrame.set(w.mShownFrame);
10225 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010226 if (SHOW_TRANSACTIONS) logSurface(w,
10227 "POS " + w.mShownFrame.left
10228 + ", " + w.mShownFrame.top, null);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010229 w.mSurfaceX = w.mShownFrame.left;
10230 w.mSurfaceY = w.mShownFrame.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010231 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
10232 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010233 Slog.w(TAG, "Error positioning surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010234 if (!recoveringMemory) {
10235 reclaimSomeSurfaceMemoryLocked(w, "position");
10236 }
10237 }
10238 } else {
10239 resize = !w.mLastShownFrame.equals(w.mShownFrame);
10240 width = w.mShownFrame.width();
10241 height = w.mShownFrame.height();
10242 w.mLastShownFrame.set(w.mShownFrame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010243 }
10244
10245 if (resize) {
10246 if (width < 1) width = 1;
10247 if (height < 1) height = 1;
10248 if (w.mSurface != null) {
10249 try {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010250 if (SHOW_TRANSACTIONS) logSurface(w,
10251 "POS " + w.mShownFrame.left + ","
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010252 + w.mShownFrame.top + " SIZE "
10253 + w.mShownFrame.width() + "x"
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010254 + w.mShownFrame.height(), null);
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010255 w.mSurfaceResized = true;
Dianne Hackborn16064f92010-03-25 00:47:24 -070010256 w.mSurfaceW = width;
10257 w.mSurfaceH = height;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010258 w.mSurface.setSize(width, height);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010259 w.mSurfaceX = w.mShownFrame.left;
10260 w.mSurfaceY = w.mShownFrame.top;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010261 w.mSurface.setPosition(w.mShownFrame.left,
10262 w.mShownFrame.top);
10263 } catch (RuntimeException e) {
10264 // If something goes wrong with the surface (such
10265 // as running out of memory), don't take down the
10266 // entire system.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010267 Slog.e(TAG, "Failure updating surface of " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010268 + "size=(" + width + "x" + height
10269 + "), pos=(" + w.mShownFrame.left
10270 + "," + w.mShownFrame.top + ")", e);
10271 if (!recoveringMemory) {
10272 reclaimSomeSurfaceMemoryLocked(w, "size");
10273 }
10274 }
10275 }
10276 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010277 if (!w.mAppFreezing && w.mLayoutSeq == mLayoutSeq) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010278 w.mContentInsetsChanged =
10279 !w.mLastContentInsets.equals(w.mContentInsets);
10280 w.mVisibleInsetsChanged =
10281 !w.mLastVisibleInsets.equals(w.mVisibleInsets);
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010282 boolean configChanged =
10283 w.mConfiguration != mCurConfiguration
10284 && (w.mConfiguration == null
10285 || mCurConfiguration.diff(w.mConfiguration) != 0);
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010286 if (DEBUG_CONFIGURATION && configChanged) {
10287 Slog.v(TAG, "Win " + w + " config changed: "
10288 + mCurConfiguration);
10289 }
Joe Onorato8a9b2202010-02-26 18:56:32 -080010290 if (localLOGV) Slog.v(TAG, "Resizing " + w
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010291 + ": configChanged=" + configChanged
10292 + " last=" + w.mLastFrame + " frame=" + w.mFrame);
Romain Guy06882f82009-06-10 13:36:04 -070010293 if (!w.mLastFrame.equals(w.mFrame)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010294 || w.mContentInsetsChanged
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010295 || w.mVisibleInsetsChanged
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010296 || w.mSurfaceResized
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010297 || configChanged) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010298 w.mLastFrame.set(w.mFrame);
10299 w.mLastContentInsets.set(w.mContentInsets);
10300 w.mLastVisibleInsets.set(w.mVisibleInsets);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010301 // If the screen is currently frozen, then keep
10302 // it frozen until this window draws at its new
10303 // orientation.
10304 if (mDisplayFrozen) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010305 if (DEBUG_ORIENTATION) Slog.v(TAG,
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010306 "Resizing while display frozen: " + w);
10307 w.mOrientationChanging = true;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010308 if (!mWindowsFreezingScreen) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010309 mWindowsFreezingScreen = true;
10310 // XXX should probably keep timeout from
10311 // when we first froze the display.
10312 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10313 mH.sendMessageDelayed(mH.obtainMessage(
10314 H.WINDOW_FREEZE_TIMEOUT), 2000);
10315 }
10316 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010317 // If the orientation is changing, then we need to
10318 // hold off on unfreezing the display until this
10319 // window has been redrawn; to do that, we need
10320 // to go through the process of getting informed
10321 // by the application when it has finished drawing.
10322 if (w.mOrientationChanging) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010323 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010324 "Orientation start waiting for draw in "
10325 + w + ", surface " + w.mSurface);
10326 w.mDrawPending = true;
10327 w.mCommitDrawPending = false;
10328 w.mReadyToShow = false;
10329 if (w.mAppToken != null) {
10330 w.mAppToken.allDrawn = false;
10331 }
10332 }
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010333 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010334 "Resizing window " + w + " to " + w.mFrame);
10335 mResizingWindows.add(w);
10336 } else if (w.mOrientationChanging) {
10337 if (!w.mDrawPending && !w.mCommitDrawPending) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010338 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010339 "Orientation not waiting for draw in "
10340 + w + ", surface " + w.mSurface);
10341 w.mOrientationChanging = false;
10342 }
10343 }
10344 }
10345
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010346 if (w.mAttachedHidden || !w.isReadyForDisplay()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010347 if (!w.mLastHidden) {
10348 //dump();
Dianne Hackborn5943c202010-04-12 21:36:49 -070010349 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Window hiding: waitingToShow="
10350 + w.mRootToken.waitingToShow + " polvis="
10351 + w.mPolicyVisibility + " atthid="
10352 + w.mAttachedHidden + " tokhid="
10353 + w.mRootToken.hidden + " vis="
10354 + w.mViewVisibility);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010355 w.mLastHidden = true;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010356 if (SHOW_TRANSACTIONS) logSurface(w,
10357 "HIDE (performLayout)", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010358 if (w.mSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010359 w.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010360 try {
10361 w.mSurface.hide();
10362 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010363 Slog.w(TAG, "Exception hiding surface in " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010364 }
10365 }
10366 mKeyWaiter.releasePendingPointerLocked(w.mSession);
10367 }
10368 // If we are waiting for this window to handle an
10369 // orientation change, well, it is hidden, so
10370 // doesn't really matter. Note that this does
10371 // introduce a potential glitch if the window
10372 // becomes unhidden before it has drawn for the
10373 // new orientation.
10374 if (w.mOrientationChanging) {
10375 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010376 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010377 "Orientation change skips hidden " + w);
10378 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010379 } else if (w.mLastLayer != w.mAnimLayer
10380 || w.mLastAlpha != w.mShownAlpha
10381 || w.mLastDsDx != w.mDsDx
10382 || w.mLastDtDx != w.mDtDx
10383 || w.mLastDsDy != w.mDsDy
10384 || w.mLastDtDy != w.mDtDy
10385 || w.mLastHScale != w.mHScale
10386 || w.mLastVScale != w.mVScale
10387 || w.mLastHidden) {
10388 displayed = true;
10389 w.mLastAlpha = w.mShownAlpha;
10390 w.mLastLayer = w.mAnimLayer;
10391 w.mLastDsDx = w.mDsDx;
10392 w.mLastDtDx = w.mDtDx;
10393 w.mLastDsDy = w.mDsDy;
10394 w.mLastDtDy = w.mDtDy;
10395 w.mLastHScale = w.mHScale;
10396 w.mLastVScale = w.mVScale;
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010397 if (SHOW_TRANSACTIONS) logSurface(w,
10398 "alpha=" + w.mShownAlpha + " layer=" + w.mAnimLayer
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010399 + " matrix=[" + (w.mDsDx*w.mHScale)
10400 + "," + (w.mDtDx*w.mVScale)
10401 + "][" + (w.mDsDy*w.mHScale)
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010402 + "," + (w.mDtDy*w.mVScale) + "]", null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010403 if (w.mSurface != null) {
10404 try {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010405 w.mSurfaceAlpha = w.mShownAlpha;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010406 w.mSurface.setAlpha(w.mShownAlpha);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010407 w.mSurfaceLayer = w.mAnimLayer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010408 w.mSurface.setLayer(w.mAnimLayer);
10409 w.mSurface.setMatrix(
10410 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
10411 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
10412 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010413 Slog.w(TAG, "Error updating surface in " + w, e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010414 if (!recoveringMemory) {
10415 reclaimSomeSurfaceMemoryLocked(w, "update");
10416 }
10417 }
10418 }
10419
10420 if (w.mLastHidden && !w.mDrawPending
10421 && !w.mCommitDrawPending
10422 && !w.mReadyToShow) {
Dianne Hackbornb8b11a02010-03-10 15:53:11 -080010423 if (SHOW_TRANSACTIONS) logSurface(w,
10424 "SHOW (performLayout)", null);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010425 if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010426 + " during relayout");
10427 if (showSurfaceRobustlyLocked(w)) {
10428 w.mHasDrawn = true;
10429 w.mLastHidden = false;
10430 } else {
10431 w.mOrientationChanging = false;
10432 }
10433 }
10434 if (w.mSurface != null) {
10435 w.mToken.hasVisible = true;
10436 }
10437 } else {
10438 displayed = true;
10439 }
10440
10441 if (displayed) {
10442 if (!covered) {
Romain Guy980a9382010-01-08 15:06:28 -080010443 if (attrs.width == LayoutParams.MATCH_PARENT
10444 && attrs.height == LayoutParams.MATCH_PARENT) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010445 covered = true;
10446 }
10447 }
10448 if (w.mOrientationChanging) {
10449 if (w.mDrawPending || w.mCommitDrawPending) {
10450 orientationChangeComplete = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010451 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010452 "Orientation continue waiting for draw in " + w);
10453 } else {
10454 w.mOrientationChanging = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010455 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 "Orientation change complete in " + w);
10457 }
10458 }
10459 w.mToken.hasVisible = true;
10460 }
10461 } else if (w.mOrientationChanging) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010462 if (DEBUG_ORIENTATION) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010463 "Orientation change skips hidden " + w);
10464 w.mOrientationChanging = false;
10465 }
10466
10467 final boolean canBeSeen = w.isDisplayedLw();
10468
10469 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
10470 focusDisplayed = true;
10471 }
10472
Dianne Hackborne9e9bca2009-08-18 15:08:22 -070010473 final boolean obscuredChanged = w.mObscured != obscured;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010474
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010475 // Update effect.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010476 if (!(w.mObscured=obscured)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010477 if (w.mSurface != null) {
10478 if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
10479 holdScreen = w.mSession;
10480 }
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070010481 if (!syswin && w.mAttrs.screenBrightness >= 0
10482 && screenBrightness < 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010483 screenBrightness = w.mAttrs.screenBrightness;
10484 }
Mike Lockwoodfb73f792009-11-20 11:31:18 -050010485 if (!syswin && w.mAttrs.buttonBrightness >= 0
10486 && buttonBrightness < 0) {
10487 buttonBrightness = w.mAttrs.buttonBrightness;
10488 }
Mike Lockwood46af6a82010-03-09 08:28:22 -050010489 if (canBeSeen
10490 && (attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG
10491 || attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD
10492 || attrs.type == WindowManager.LayoutParams.TYPE_SYSTEM_ERROR)) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -070010493 syswin = true;
10494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010495 }
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010496
Dianne Hackborn25994b42009-09-04 14:21:19 -070010497 boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
10498 if (opaqueDrawn && w.isFullscreen(dw, dh)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010499 // This window completely covers everything behind it,
10500 // so we want to leave all of them as unblurred (for
10501 // performance reasons).
10502 obscured = true;
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010503 } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010504 if (SHOW_TRANSACTIONS) Slog.d(TAG, "showing background filler");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010505 // This window is in compatibility mode, and needs background filler.
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010506 obscured = true;
10507 if (mBackgroundFillerSurface == null) {
10508 try {
10509 mBackgroundFillerSurface = new Surface(mFxSession, 0,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080010510 "BackGroundFiller",
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010511 0, dw, dh,
10512 PixelFormat.OPAQUE,
10513 Surface.FX_SURFACE_NORMAL);
10514 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010515 Slog.e(TAG, "Exception creating filler surface", e);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010516 }
10517 }
10518 try {
10519 mBackgroundFillerSurface.setPosition(0, 0);
10520 mBackgroundFillerSurface.setSize(dw, dh);
10521 // Using the same layer as Dim because they will never be shown at the
10522 // same time.
10523 mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1);
10524 mBackgroundFillerSurface.show();
10525 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010526 Slog.e(TAG, "Exception showing filler surface");
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010527 }
10528 backgroundFillerShown = true;
10529 mBackgroundFillerShown = true;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010530 } else if (canBeSeen && !obscured &&
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010531 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010532 if (localLOGV) Slog.v(TAG, "Win " + w
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010533 + ": blurring=" + blurring
10534 + " obscured=" + obscured
10535 + " displayed=" + displayed);
10536 if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
10537 if (!dimming) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010538 //Slog.i(TAG, "DIM BEHIND: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010539 dimming = true;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010540 if (mDimAnimator == null) {
10541 mDimAnimator = new DimAnimator(mFxSession);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010542 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010543 mDimAnimator.show(dw, dh);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010544 mDimAnimator.updateParameters(w, currentTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010545 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010546 }
10547 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
10548 if (!blurring) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010549 //Slog.i(TAG, "BLUR BEHIND: " + w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010550 blurring = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010551 if (mBlurSurface == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010552 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010553 + mBlurSurface + ": CREATE");
10554 try {
Romain Guy06882f82009-06-10 13:36:04 -070010555 mBlurSurface = new Surface(mFxSession, 0,
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080010556 "BlurSurface",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010557 -1, 16, 16,
10558 PixelFormat.OPAQUE,
10559 Surface.FX_SURFACE_BLUR);
10560 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010561 Slog.e(TAG, "Exception creating Blur surface", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010562 }
10563 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010564 if (mBlurSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010565 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
10566 + mBlurSurface + ": pos=(0,0) (" +
10567 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010568 mBlurSurface.setPosition(0, 0);
10569 mBlurSurface.setSize(dw, dh);
Dianne Hackborn16064f92010-03-25 00:47:24 -070010570 mBlurSurface.setLayer(w.mAnimLayer-2);
10571 if (!mBlurShown) {
10572 try {
10573 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR "
10574 + mBlurSurface + ": SHOW");
10575 mBlurSurface.show();
10576 } catch (RuntimeException e) {
10577 Slog.w(TAG, "Failure showing blur surface", e);
10578 }
10579 mBlurShown = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010580 }
10581 }
10582 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010583 }
10584 }
10585 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010586
Dianne Hackborne9e9bca2009-08-18 15:08:22 -070010587 if (obscuredChanged && mWallpaperTarget == w) {
10588 // This is the wallpaper target and its obscured state
10589 // changed... make sure the current wallaper's visibility
10590 // has been updated accordingly.
10591 updateWallpaperVisibilityLocked();
10592 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010593 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010594
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010595 if (backgroundFillerShown == false && mBackgroundFillerShown) {
10596 mBackgroundFillerShown = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010597 if (SHOW_TRANSACTIONS) Slog.d(TAG, "hiding background filler");
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010598 try {
10599 mBackgroundFillerSurface.hide();
10600 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010601 Slog.e(TAG, "Exception hiding filler surface", e);
Mitsuru Oshima1ecf5d22009-07-06 17:20:38 -070010602 }
10603 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010604
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070010605 if (mDimAnimator != null && mDimAnimator.mDimShown) {
Dianne Hackbornde2606d2009-12-18 16:53:55 -080010606 animating |= mDimAnimator.updateSurface(dimming, currentTime,
10607 mDisplayFrozen || !mPolicy.isScreenOn());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010608 }
Romain Guy06882f82009-06-10 13:36:04 -070010609
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010610 if (!blurring && mBlurShown) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010611 if (SHOW_TRANSACTIONS) Slog.i(TAG, " BLUR " + mBlurSurface
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010612 + ": HIDE");
10613 try {
10614 mBlurSurface.hide();
10615 } catch (IllegalArgumentException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010616 Slog.w(TAG, "Illegal argument exception hiding blur surface");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010617 }
10618 mBlurShown = false;
10619 }
10620
Joe Onorato8a9b2202010-02-26 18:56:32 -080010621 if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010622 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010623 Slog.e(TAG, "Unhandled exception in Window Manager", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010624 }
10625
10626 Surface.closeTransaction();
Romain Guy06882f82009-06-10 13:36:04 -070010627
Joe Onorato8a9b2202010-02-26 18:56:32 -080010628 if (DEBUG_ORIENTATION && mDisplayFrozen) Slog.v(TAG,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010629 "With display frozen, orientationChangeComplete="
10630 + orientationChangeComplete);
10631 if (orientationChangeComplete) {
10632 if (mWindowsFreezingScreen) {
10633 mWindowsFreezingScreen = false;
10634 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
10635 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010636 stopFreezingDisplayLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010637 }
Romain Guy06882f82009-06-10 13:36:04 -070010638
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010639 i = mResizingWindows.size();
10640 if (i > 0) {
10641 do {
10642 i--;
10643 WindowState win = mResizingWindows.get(i);
10644 try {
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010645 if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG,
10646 "Reporting new frame to " + win + ": " + win.mFrame);
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010647 int diff = 0;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010648 boolean configChanged =
10649 win.mConfiguration != mCurConfiguration
10650 && (win.mConfiguration == null
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010651 || (diff=mCurConfiguration.diff(win.mConfiguration)) != 0);
10652 if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION)
10653 && configChanged) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010654 Slog.i(TAG, "Sending new config to window " + win + ": "
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010655 + win.mFrame.width() + "x" + win.mFrame.height()
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010656 + " / " + mCurConfiguration + " / 0x"
10657 + Integer.toHexString(diff));
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010658 }
Dianne Hackborn694f79b2010-03-17 19:44:59 -070010659 win.mConfiguration = mCurConfiguration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010660 win.mClient.resized(win.mFrame.width(),
10661 win.mFrame.height(), win.mLastContentInsets,
Dianne Hackborne36d6e22010-02-17 19:46:25 -080010662 win.mLastVisibleInsets, win.mDrawPending,
10663 configChanged ? win.mConfiguration : null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010664 win.mContentInsetsChanged = false;
10665 win.mVisibleInsetsChanged = false;
Dianne Hackbornac3587d2010-03-11 11:12:11 -080010666 win.mSurfaceResized = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010667 } catch (RemoteException e) {
10668 win.mOrientationChanging = false;
10669 }
10670 } while (i > 0);
10671 mResizingWindows.clear();
10672 }
Romain Guy06882f82009-06-10 13:36:04 -070010673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010674 // Destroy the surface of any windows that are no longer visible.
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010675 boolean wallpaperDestroyed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010676 i = mDestroySurface.size();
10677 if (i > 0) {
10678 do {
10679 i--;
10680 WindowState win = mDestroySurface.get(i);
10681 win.mDestroying = false;
10682 if (mInputMethodWindow == win) {
10683 mInputMethodWindow = null;
10684 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010685 if (win == mWallpaperTarget) {
10686 wallpaperDestroyed = true;
10687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010688 win.destroySurfaceLocked();
10689 } while (i > 0);
10690 mDestroySurface.clear();
10691 }
10692
10693 // Time to remove any exiting tokens?
10694 for (i=mExitingTokens.size()-1; i>=0; i--) {
10695 WindowToken token = mExitingTokens.get(i);
10696 if (!token.hasVisible) {
10697 mExitingTokens.remove(i);
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070010698 if (token.windowType == TYPE_WALLPAPER) {
10699 mWallpaperTokens.remove(token);
10700 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010701 }
10702 }
10703
10704 // Time to remove any exiting applications?
10705 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
10706 AppWindowToken token = mExitingAppTokens.get(i);
10707 if (!token.hasVisible && !mClosingApps.contains(token)) {
Dianne Hackborn9bfb7072009-09-22 11:37:40 -070010708 // Make sure there is no animation running on this token,
10709 // so any windows associated with it will be removed as
10710 // soon as their animations are complete
10711 token.animation = null;
10712 token.animating = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010713 mAppTokens.remove(token);
10714 mExitingAppTokens.remove(i);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070010715 if (mLastEnterAnimToken == token) {
10716 mLastEnterAnimToken = null;
10717 mLastEnterAnimParams = null;
10718 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010719 }
10720 }
10721
Dianne Hackborna8f60182009-09-01 19:01:50 -070010722 boolean needRelayout = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010723
Dianne Hackborna8f60182009-09-01 19:01:50 -070010724 if (!animating && mAppTransitionRunning) {
10725 // We have finished the animation of an app transition. To do
10726 // this, we have delayed a lot of operations like showing and
10727 // hiding apps, moving apps in Z-order, etc. The app token list
10728 // reflects the correct Z-order, but the window list may now
10729 // be out of sync with it. So here we will just rebuild the
10730 // entire app window list. Fun!
10731 mAppTransitionRunning = false;
10732 needRelayout = true;
10733 rebuildAppWindowListLocked();
Dianne Hackborn16064f92010-03-25 00:47:24 -070010734 assignLayersLocked();
Dianne Hackborna8f60182009-09-01 19:01:50 -070010735 // Clear information about apps that were moving.
10736 mToBottomApps.clear();
10737 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010739 if (focusDisplayed) {
10740 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
10741 }
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010742 if (wallpaperDestroyed) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010743 needRelayout = adjustWallpaperWindowsLocked() != 0;
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010744 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070010745 if (needRelayout) {
Dianne Hackborn7341d7a2009-08-14 11:37:52 -070010746 requestAnimationLocked(0);
10747 } else if (animating) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010748 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
10749 }
Dianne Hackbornce73c1e2010-04-12 23:11:38 -070010750
10751 if (DEBUG_FREEZE) Slog.v(TAG, "Layout: mDisplayFrozen=" + mDisplayFrozen
10752 + " holdScreen=" + holdScreen);
10753 if (!mDisplayFrozen) {
10754 mQueue.setHoldScreenLocked(holdScreen != null);
10755 if (screenBrightness < 0 || screenBrightness > 1.0f) {
10756 mPowerManager.setScreenBrightnessOverride(-1);
10757 } else {
10758 mPowerManager.setScreenBrightnessOverride((int)
10759 (screenBrightness * Power.BRIGHTNESS_ON));
10760 }
10761 if (buttonBrightness < 0 || buttonBrightness > 1.0f) {
10762 mPowerManager.setButtonBrightnessOverride(-1);
10763 } else {
10764 mPowerManager.setButtonBrightnessOverride((int)
10765 (buttonBrightness * Power.BRIGHTNESS_ON));
10766 }
10767 if (holdScreen != mHoldingScreenOn) {
10768 mHoldingScreenOn = holdScreen;
10769 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
10770 mH.sendMessage(m);
10771 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010772 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010773
Dianne Hackborn93e462b2009-09-15 22:50:40 -070010774 if (mTurnOnScreen) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010775 if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
Dianne Hackborn93e462b2009-09-15 22:50:40 -070010776 mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
10777 LocalPowerManager.BUTTON_EVENT, true);
10778 mTurnOnScreen = false;
10779 }
Dianne Hackbornf3bea9c2009-12-09 18:26:21 -080010780
10781 // Check to see if we are now in a state where the screen should
10782 // be enabled, because the window obscured flags have changed.
10783 enableScreenIfNeededLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010784 }
10785
10786 void requestAnimationLocked(long delay) {
10787 if (!mAnimationPending) {
10788 mAnimationPending = true;
10789 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
10790 }
10791 }
Romain Guy06882f82009-06-10 13:36:04 -070010792
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010793 /**
10794 * Have the surface flinger show a surface, robustly dealing with
10795 * error conditions. In particular, if there is not enough memory
10796 * to show the surface, then we will try to get rid of other surfaces
10797 * in order to succeed.
Romain Guy06882f82009-06-10 13:36:04 -070010798 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010799 * @return Returns true if the surface was successfully shown.
10800 */
10801 boolean showSurfaceRobustlyLocked(WindowState win) {
10802 try {
10803 if (win.mSurface != null) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070010804 win.mSurfaceShown = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010805 win.mSurface.show();
Dianne Hackborn93e462b2009-09-15 22:50:40 -070010806 if (win.mTurnOnScreen) {
Dianne Hackbornb601ce12010-03-01 23:36:02 -080010807 if (DEBUG_VISIBILITY) Slog.v(TAG,
10808 "Show surface turning screen on: " + win);
Dianne Hackborn93e462b2009-09-15 22:50:40 -070010809 win.mTurnOnScreen = false;
10810 mTurnOnScreen = true;
10811 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010812 }
10813 return true;
10814 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010815 Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010816 }
Romain Guy06882f82009-06-10 13:36:04 -070010817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010818 reclaimSomeSurfaceMemoryLocked(win, "show");
Romain Guy06882f82009-06-10 13:36:04 -070010819
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010820 return false;
10821 }
Romain Guy06882f82009-06-10 13:36:04 -070010822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010823 void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
10824 final Surface surface = win.mSurface;
Romain Guy06882f82009-06-10 13:36:04 -070010825
Doug Zongkerab5c49c2009-12-04 10:31:43 -080010826 EventLog.writeEvent(EventLogTags.WM_NO_SURFACE_MEMORY, win.toString(),
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 win.mSession.mPid, operation);
Romain Guy06882f82009-06-10 13:36:04 -070010828
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010829 if (mForceRemoves == null) {
10830 mForceRemoves = new ArrayList<WindowState>();
10831 }
Romain Guy06882f82009-06-10 13:36:04 -070010832
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010833 long callingIdentity = Binder.clearCallingIdentity();
10834 try {
10835 // There was some problem... first, do a sanity check of the
10836 // window list to make sure we haven't left any dangling surfaces
10837 // around.
10838 int N = mWindows.size();
10839 boolean leakedSurface = false;
Joe Onorato8a9b2202010-02-26 18:56:32 -080010840 Slog.i(TAG, "Out of memory for surface! Looking for leaks...");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010841 for (int i=0; i<N; i++) {
10842 WindowState ws = (WindowState)mWindows.get(i);
10843 if (ws.mSurface != null) {
10844 if (!mSessions.contains(ws.mSession)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010845 Slog.w(TAG, "LEAKED SURFACE (session doesn't exist): "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010846 + ws + " surface=" + ws.mSurface
10847 + " token=" + win.mToken
10848 + " pid=" + ws.mSession.mPid
10849 + " uid=" + ws.mSession.mUid);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010850 ws.mSurface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070010851 ws.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010852 ws.mSurface = null;
10853 mForceRemoves.add(ws);
10854 i--;
10855 N--;
10856 leakedSurface = true;
10857 } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010858 Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010859 + ws + " surface=" + ws.mSurface
10860 + " token=" + win.mAppToken);
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010861 ws.mSurface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070010862 ws.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010863 ws.mSurface = null;
10864 leakedSurface = true;
10865 }
10866 }
10867 }
Romain Guy06882f82009-06-10 13:36:04 -070010868
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010869 boolean killedApps = false;
10870 if (!leakedSurface) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080010871 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010872 SparseIntArray pidCandidates = new SparseIntArray();
10873 for (int i=0; i<N; i++) {
10874 WindowState ws = (WindowState)mWindows.get(i);
10875 if (ws.mSurface != null) {
10876 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
10877 }
10878 }
10879 if (pidCandidates.size() > 0) {
10880 int[] pids = new int[pidCandidates.size()];
10881 for (int i=0; i<pids.length; i++) {
10882 pids[i] = pidCandidates.keyAt(i);
10883 }
10884 try {
Suchi Amalapurapue99bb5f2010-03-19 14:36:49 -070010885 if (mActivityManager.killPids(pids, "Free memory")) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010886 killedApps = true;
10887 }
10888 } catch (RemoteException e) {
10889 }
10890 }
10891 }
Romain Guy06882f82009-06-10 13:36:04 -070010892
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010893 if (leakedSurface || killedApps) {
10894 // We managed to reclaim some memory, so get rid of the trouble
10895 // surface and ask the app to request another one.
Joe Onorato8a9b2202010-02-26 18:56:32 -080010896 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010897 if (surface != null) {
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070010898 surface.destroy();
Dianne Hackborn16064f92010-03-25 00:47:24 -070010899 win.mSurfaceShown = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010900 win.mSurface = null;
10901 }
Romain Guy06882f82009-06-10 13:36:04 -070010902
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010903 try {
10904 win.mClient.dispatchGetNewSurface();
10905 } catch (RemoteException e) {
10906 }
10907 }
10908 } finally {
10909 Binder.restoreCallingIdentity(callingIdentity);
10910 }
10911 }
Romain Guy06882f82009-06-10 13:36:04 -070010912
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010913 private boolean updateFocusedWindowLocked(int mode) {
10914 WindowState newFocus = computeFocusedWindowLocked();
10915 if (mCurrentFocus != newFocus) {
10916 // This check makes sure that we don't already have the focus
10917 // change message pending.
10918 mH.removeMessages(H.REPORT_FOCUS_CHANGE);
10919 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
Joe Onorato8a9b2202010-02-26 18:56:32 -080010920 if (localLOGV) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010921 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
10922 final WindowState oldFocus = mCurrentFocus;
10923 mCurrentFocus = newFocus;
10924 mLosingFocus.remove(newFocus);
Romain Guy06882f82009-06-10 13:36:04 -070010925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010926 final WindowState imWindow = mInputMethodWindow;
10927 if (newFocus != imWindow && oldFocus != imWindow) {
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010928 if (moveInputMethodWindowsIfNeededLocked(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010929 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010930 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
10931 mLayoutNeeded = true;
10932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010933 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
10934 performLayoutLockedInner();
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010935 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
10936 // Client will do the layout, but we need to assign layers
10937 // for handleNewWindowLocked() below.
10938 assignLayersLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010939 }
10940 }
Romain Guy06882f82009-06-10 13:36:04 -070010941
The Android Open Source Projectc474dec2009-03-04 09:49:09 -080010942 if (newFocus != null && mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
10943 mKeyWaiter.handleNewWindowLocked(newFocus);
10944 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010945 return true;
10946 }
10947 return false;
10948 }
10949
10950 private WindowState computeFocusedWindowLocked() {
10951 WindowState result = null;
10952 WindowState win;
10953
10954 int i = mWindows.size() - 1;
10955 int nextAppIndex = mAppTokens.size()-1;
10956 WindowToken nextApp = nextAppIndex >= 0
10957 ? mAppTokens.get(nextAppIndex) : null;
10958
10959 while (i >= 0) {
10960 win = (WindowState)mWindows.get(i);
10961
Joe Onorato8a9b2202010-02-26 18:56:32 -080010962 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 TAG, "Looking for focus: " + i
10964 + " = " + win
10965 + ", flags=" + win.mAttrs.flags
10966 + ", canReceive=" + win.canReceiveKeys());
10967
10968 AppWindowToken thisApp = win.mAppToken;
Romain Guy06882f82009-06-10 13:36:04 -070010969
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010970 // If this window's application has been removed, just skip it.
10971 if (thisApp != null && thisApp.removed) {
10972 i--;
10973 continue;
10974 }
Romain Guy06882f82009-06-10 13:36:04 -070010975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010976 // If there is a focused app, don't allow focus to go to any
10977 // windows below it. If this is an application window, step
10978 // through the app tokens until we find its app.
10979 if (thisApp != null && nextApp != null && thisApp != nextApp
10980 && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
10981 int origAppIndex = nextAppIndex;
10982 while (nextAppIndex > 0) {
10983 if (nextApp == mFocusedApp) {
10984 // Whoops, we are below the focused app... no focus
10985 // for you!
Joe Onorato8a9b2202010-02-26 18:56:32 -080010986 if (localLOGV || DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010987 TAG, "Reached focused app: " + mFocusedApp);
10988 return null;
10989 }
10990 nextAppIndex--;
10991 nextApp = mAppTokens.get(nextAppIndex);
10992 if (nextApp == thisApp) {
10993 break;
10994 }
10995 }
10996 if (thisApp != nextApp) {
10997 // Uh oh, the app token doesn't exist! This shouldn't
10998 // happen, but if it does we can get totally hosed...
10999 // so restart at the original app.
11000 nextAppIndex = origAppIndex;
11001 nextApp = mAppTokens.get(nextAppIndex);
11002 }
11003 }
11004
11005 // Dispatch to this window if it is wants key events.
11006 if (win.canReceiveKeys()) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011007 if (DEBUG_FOCUS) Slog.v(
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011008 TAG, "Found focus @ " + i + " = " + win);
11009 result = win;
11010 break;
11011 }
11012
11013 i--;
11014 }
11015
11016 return result;
11017 }
11018
11019 private void startFreezingDisplayLocked() {
11020 if (mDisplayFrozen) {
Chris Tate2ad63a92009-03-25 17:36:48 -070011021 // Freezing the display also suspends key event delivery, to
11022 // keep events from going astray while the display is reconfigured.
11023 // If someone has changed orientation again while the screen is
11024 // still frozen, the events will continue to be blocked while the
11025 // successive orientation change is processed. To prevent spurious
11026 // ANRs, we reset the event dispatch timeout in this case.
11027 synchronized (mKeyWaiter) {
11028 mKeyWaiter.mWasFrozen = true;
11029 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011030 return;
11031 }
Romain Guy06882f82009-06-10 13:36:04 -070011032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011033 mScreenFrozenLock.acquire();
Romain Guy06882f82009-06-10 13:36:04 -070011034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011035 long now = SystemClock.uptimeMillis();
Joe Onorato8a9b2202010-02-26 18:56:32 -080011036 //Slog.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011037 if (mFreezeGcPending != 0) {
11038 if (now > (mFreezeGcPending+1000)) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011039 //Slog.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011040 mH.removeMessages(H.FORCE_GC);
11041 Runtime.getRuntime().gc();
11042 mFreezeGcPending = now;
11043 }
11044 } else {
11045 mFreezeGcPending = now;
11046 }
Romain Guy06882f82009-06-10 13:36:04 -070011047
Dianne Hackbornce73c1e2010-04-12 23:11:38 -070011048 if (DEBUG_FREEZE) Slog.v(TAG, "*** FREEZING DISPLAY", new RuntimeException());
11049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011050 mDisplayFrozen = true;
Dianne Hackbornbfe319e2009-09-21 00:34:05 -070011051 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
11052 mNextAppTransition = WindowManagerPolicy.TRANSIT_UNSET;
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011053 mNextAppTransitionPackage = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011054 mAppTransitionReady = true;
11055 }
Romain Guy06882f82009-06-10 13:36:04 -070011056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011057 if (PROFILE_ORIENTATION) {
11058 File file = new File("/data/system/frozen");
11059 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
11060 }
11061 Surface.freezeDisplay(0);
11062 }
Romain Guy06882f82009-06-10 13:36:04 -070011063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011064 private void stopFreezingDisplayLocked() {
11065 if (!mDisplayFrozen) {
11066 return;
11067 }
Romain Guy06882f82009-06-10 13:36:04 -070011068
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011069 if (mWaitingForConfig || mAppsFreezingScreen > 0 || mWindowsFreezingScreen) {
11070 return;
11071 }
11072
Dianne Hackbornce73c1e2010-04-12 23:11:38 -070011073 if (DEBUG_FREEZE) Slog.v(TAG, "*** UNFREEZING DISPLAY", new RuntimeException());
11074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011075 mDisplayFrozen = false;
11076 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
11077 if (PROFILE_ORIENTATION) {
11078 Debug.stopMethodTracing();
11079 }
11080 Surface.unfreezeDisplay(0);
Romain Guy06882f82009-06-10 13:36:04 -070011081
Chris Tate2ad63a92009-03-25 17:36:48 -070011082 // Reset the key delivery timeout on unfreeze, too. We force a wakeup here
11083 // too because regular key delivery processing should resume immediately.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011084 synchronized (mKeyWaiter) {
11085 mKeyWaiter.mWasFrozen = true;
11086 mKeyWaiter.notifyAll();
11087 }
11088
Christopher Tateb696aee2010-04-02 19:08:30 -070011089 // While the display is frozen we don't re-compute the orientation
11090 // to avoid inconsistent states. However, something interesting
11091 // could have actually changed during that time so re-evaluate it
11092 // now to catch that.
11093 if (updateOrientationFromAppTokensLocked()) {
11094 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
11095 }
11096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011097 // A little kludge: a lot could have happened while the
11098 // display was frozen, so now that we are coming back we
11099 // do a gc so that any remote references the system
11100 // processes holds on others can be released if they are
11101 // no longer needed.
11102 mH.removeMessages(H.FORCE_GC);
11103 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
11104 2000);
Romain Guy06882f82009-06-10 13:36:04 -070011105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011106 mScreenFrozenLock.release();
11107 }
Romain Guy06882f82009-06-10 13:36:04 -070011108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011109 @Override
11110 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
11111 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
11112 != PackageManager.PERMISSION_GRANTED) {
11113 pw.println("Permission Denial: can't dump WindowManager from from pid="
11114 + Binder.getCallingPid()
11115 + ", uid=" + Binder.getCallingUid());
11116 return;
11117 }
Romain Guy06882f82009-06-10 13:36:04 -070011118
Dianne Hackborna2e92262010-03-02 17:19:29 -080011119 pw.println("Input State:");
11120 mQueue.dump(pw, " ");
11121 pw.println(" ");
11122
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011123 synchronized(mWindowMap) {
11124 pw.println("Current Window Manager state:");
11125 for (int i=mWindows.size()-1; i>=0; i--) {
11126 WindowState w = (WindowState)mWindows.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011127 pw.print(" Window #"); pw.print(i); pw.print(' ');
11128 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011129 w.dump(pw, " ");
11130 }
11131 if (mInputMethodDialogs.size() > 0) {
11132 pw.println(" ");
11133 pw.println(" Input method dialogs:");
11134 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
11135 WindowState w = mInputMethodDialogs.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011136 pw.print(" IM Dialog #"); pw.print(i); pw.print(": "); pw.println(w);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011137 }
11138 }
11139 if (mPendingRemove.size() > 0) {
11140 pw.println(" ");
11141 pw.println(" Remove pending for:");
11142 for (int i=mPendingRemove.size()-1; i>=0; i--) {
11143 WindowState w = mPendingRemove.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011144 pw.print(" Remove #"); pw.print(i); pw.print(' ');
11145 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011146 w.dump(pw, " ");
11147 }
11148 }
11149 if (mForceRemoves != null && mForceRemoves.size() > 0) {
11150 pw.println(" ");
11151 pw.println(" Windows force removing:");
11152 for (int i=mForceRemoves.size()-1; i>=0; i--) {
11153 WindowState w = mForceRemoves.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011154 pw.print(" Removing #"); pw.print(i); pw.print(' ');
11155 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011156 w.dump(pw, " ");
11157 }
11158 }
11159 if (mDestroySurface.size() > 0) {
11160 pw.println(" ");
11161 pw.println(" Windows waiting to destroy their surface:");
11162 for (int i=mDestroySurface.size()-1; i>=0; i--) {
11163 WindowState w = mDestroySurface.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011164 pw.print(" Destroy #"); pw.print(i); pw.print(' ');
11165 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011166 w.dump(pw, " ");
11167 }
11168 }
11169 if (mLosingFocus.size() > 0) {
11170 pw.println(" ");
11171 pw.println(" Windows losing focus:");
11172 for (int i=mLosingFocus.size()-1; i>=0; i--) {
11173 WindowState w = mLosingFocus.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011174 pw.print(" Losing #"); pw.print(i); pw.print(' ');
11175 pw.print(w); pw.println(":");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011176 w.dump(pw, " ");
11177 }
11178 }
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011179 if (mResizingWindows.size() > 0) {
11180 pw.println(" ");
11181 pw.println(" Windows waiting to resize:");
11182 for (int i=mResizingWindows.size()-1; i>=0; i--) {
11183 WindowState w = mResizingWindows.get(i);
11184 pw.print(" Resizing #"); pw.print(i); pw.print(' ');
11185 pw.print(w); pw.println(":");
11186 w.dump(pw, " ");
11187 }
11188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011189 if (mSessions.size() > 0) {
11190 pw.println(" ");
11191 pw.println(" All active sessions:");
11192 Iterator<Session> it = mSessions.iterator();
11193 while (it.hasNext()) {
11194 Session s = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011195 pw.print(" Session "); pw.print(s); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011196 s.dump(pw, " ");
11197 }
11198 }
11199 if (mTokenMap.size() > 0) {
11200 pw.println(" ");
11201 pw.println(" All tokens:");
11202 Iterator<WindowToken> it = mTokenMap.values().iterator();
11203 while (it.hasNext()) {
11204 WindowToken token = it.next();
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011205 pw.print(" Token "); pw.print(token.token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011206 token.dump(pw, " ");
11207 }
11208 }
11209 if (mTokenList.size() > 0) {
11210 pw.println(" ");
11211 pw.println(" Window token list:");
11212 for (int i=0; i<mTokenList.size(); i++) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011213 pw.print(" #"); pw.print(i); pw.print(": ");
11214 pw.println(mTokenList.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011215 }
11216 }
Dianne Hackborn4c62fc02009-08-08 20:40:27 -070011217 if (mWallpaperTokens.size() > 0) {
11218 pw.println(" ");
11219 pw.println(" Wallpaper tokens:");
11220 for (int i=mWallpaperTokens.size()-1; i>=0; i--) {
11221 WindowToken token = mWallpaperTokens.get(i);
11222 pw.print(" Wallpaper #"); pw.print(i);
11223 pw.print(' '); pw.print(token); pw.println(':');
11224 token.dump(pw, " ");
11225 }
11226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011227 if (mAppTokens.size() > 0) {
11228 pw.println(" ");
11229 pw.println(" Application tokens in Z order:");
11230 for (int i=mAppTokens.size()-1; i>=0; i--) {
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011231 pw.print(" App #"); pw.print(i); pw.print(": ");
11232 pw.println(mAppTokens.get(i));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011233 }
11234 }
11235 if (mFinishedStarting.size() > 0) {
11236 pw.println(" ");
11237 pw.println(" Finishing start of application tokens:");
11238 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
11239 WindowToken token = mFinishedStarting.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011240 pw.print(" Finished Starting #"); pw.print(i);
11241 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011242 token.dump(pw, " ");
11243 }
11244 }
11245 if (mExitingTokens.size() > 0) {
11246 pw.println(" ");
11247 pw.println(" Exiting tokens:");
11248 for (int i=mExitingTokens.size()-1; i>=0; i--) {
11249 WindowToken token = mExitingTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011250 pw.print(" Exiting #"); pw.print(i);
11251 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011252 token.dump(pw, " ");
11253 }
11254 }
11255 if (mExitingAppTokens.size() > 0) {
11256 pw.println(" ");
11257 pw.println(" Exiting application tokens:");
11258 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
11259 WindowToken token = mExitingAppTokens.get(i);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011260 pw.print(" Exiting App #"); pw.print(i);
11261 pw.print(' '); pw.print(token); pw.println(':');
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011262 token.dump(pw, " ");
11263 }
11264 }
11265 pw.println(" ");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011266 pw.print(" mCurrentFocus="); pw.println(mCurrentFocus);
11267 pw.print(" mLastFocus="); pw.println(mLastFocus);
11268 pw.print(" mFocusedApp="); pw.println(mFocusedApp);
11269 pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
11270 pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
Dianne Hackbornf21adf62009-08-13 10:20:21 -070011271 pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
Dianne Hackborn284ac932009-08-28 10:34:25 -070011272 if (mLowerWallpaperTarget != null && mUpperWallpaperTarget != null) {
11273 pw.print(" mLowerWallpaperTarget="); pw.println(mLowerWallpaperTarget);
11274 pw.print(" mUpperWallpaperTarget="); pw.println(mUpperWallpaperTarget);
11275 }
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011276 pw.print(" mCurConfiguration="); pw.println(this.mCurConfiguration);
11277 pw.print(" mInTouchMode="); pw.print(mInTouchMode);
11278 pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011279 pw.print(" mSystemBooted="); pw.print(mSystemBooted);
11280 pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
11281 pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded);
11282 pw.print(" mBlurShown="); pw.println(mBlurShown);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011283 if (mDimAnimator != null) {
11284 mDimAnimator.printTo(pw);
11285 } else {
Dianne Hackborna2e92262010-03-02 17:19:29 -080011286 pw.println( " no DimAnimator ");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011287 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011288 pw.print(" mInputMethodAnimLayerAdjustment=");
Dianne Hackborn759a39e2009-08-09 17:20:27 -070011289 pw.print(mInputMethodAnimLayerAdjustment);
11290 pw.print(" mWallpaperAnimLayerAdjustment=");
11291 pw.println(mWallpaperAnimLayerAdjustment);
Dianne Hackborn284ac932009-08-28 10:34:25 -070011292 pw.print(" mLastWallpaperX="); pw.print(mLastWallpaperX);
11293 pw.print(" mLastWallpaperY="); pw.println(mLastWallpaperY);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011294 pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen);
11295 pw.print(" mWindowsFreezingScreen="); pw.print(mWindowsFreezingScreen);
Dianne Hackborne36d6e22010-02-17 19:46:25 -080011296 pw.print(" mAppsFreezingScreen="); pw.print(mAppsFreezingScreen);
11297 pw.print(" mWaitingForConfig="); pw.println(mWaitingForConfig);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011298 pw.print(" mRotation="); pw.print(mRotation);
11299 pw.print(", mForcedAppOrientation="); pw.print(mForcedAppOrientation);
11300 pw.print(", mRequestedRotation="); pw.println(mRequestedRotation);
11301 pw.print(" mAnimationPending="); pw.print(mAnimationPending);
11302 pw.print(" mWindowAnimationScale="); pw.print(mWindowAnimationScale);
11303 pw.print(" mTransitionWindowAnimationScale="); pw.println(mTransitionAnimationScale);
11304 pw.print(" mNextAppTransition=0x");
11305 pw.print(Integer.toHexString(mNextAppTransition));
11306 pw.print(", mAppTransitionReady="); pw.print(mAppTransitionReady);
Dianne Hackborna8f60182009-09-01 19:01:50 -070011307 pw.print(", mAppTransitionRunning="); pw.print(mAppTransitionRunning);
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011308 pw.print(", mAppTransitionTimeout="); pw.println( mAppTransitionTimeout);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011309 if (mNextAppTransitionPackage != null) {
11310 pw.print(" mNextAppTransitionPackage=");
11311 pw.print(mNextAppTransitionPackage);
11312 pw.print(", mNextAppTransitionEnter=0x");
11313 pw.print(Integer.toHexString(mNextAppTransitionEnter));
11314 pw.print(", mNextAppTransitionExit=0x");
11315 pw.print(Integer.toHexString(mNextAppTransitionExit));
11316 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011317 pw.print(" mStartingIconInTransition="); pw.print(mStartingIconInTransition);
11318 pw.print(", mSkipAppTransitionAnimation="); pw.println(mSkipAppTransitionAnimation);
Dianne Hackborn3b3e1452009-09-24 19:22:12 -070011319 if (mLastEnterAnimToken != null || mLastEnterAnimToken != null) {
11320 pw.print(" mLastEnterAnimToken="); pw.print(mLastEnterAnimToken);
11321 pw.print(", mLastEnterAnimParams="); pw.println(mLastEnterAnimParams);
11322 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011323 if (mOpeningApps.size() > 0) {
11324 pw.print(" mOpeningApps="); pw.println(mOpeningApps);
11325 }
11326 if (mClosingApps.size() > 0) {
11327 pw.print(" mClosingApps="); pw.println(mClosingApps);
11328 }
Dianne Hackborna8f60182009-09-01 19:01:50 -070011329 if (mToTopApps.size() > 0) {
11330 pw.print(" mToTopApps="); pw.println(mToTopApps);
11331 }
11332 if (mToBottomApps.size() > 0) {
11333 pw.print(" mToBottomApps="); pw.println(mToBottomApps);
11334 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011335 pw.print(" DisplayWidth="); pw.print(mDisplay.getWidth());
11336 pw.print(" DisplayHeight="); pw.println(mDisplay.getHeight());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011337 pw.println(" KeyWaiter state:");
Dianne Hackborn1d442e02009-04-20 18:14:05 -070011338 pw.print(" mLastWin="); pw.print(mKeyWaiter.mLastWin);
11339 pw.print(" mLastBinder="); pw.println(mKeyWaiter.mLastBinder);
11340 pw.print(" mFinished="); pw.print(mKeyWaiter.mFinished);
11341 pw.print(" mGotFirstWindow="); pw.print(mKeyWaiter.mGotFirstWindow);
11342 pw.print(" mEventDispatching="); pw.print(mKeyWaiter.mEventDispatching);
11343 pw.print(" mTimeToSwitch="); pw.println(mKeyWaiter.mTimeToSwitch);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011344 }
11345 }
11346
11347 public void monitor() {
11348 synchronized (mWindowMap) { }
Mike Lockwood983ee092009-11-22 01:42:24 -050011349 synchronized (mKeyguardTokenWatcher) { }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011350 synchronized (mKeyWaiter) { }
11351 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011352
Dianne Hackbornddca3ee2009-07-23 19:01:31 -070011353 public void virtualKeyFeedback(KeyEvent event) {
11354 mPolicy.keyFeedbackFromInput(event);
11355 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011356
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011357 /**
11358 * DimAnimator class that controls the dim animation. This holds the surface and
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011359 * all state used for dim animation.
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011360 */
11361 private static class DimAnimator {
11362 Surface mDimSurface;
11363 boolean mDimShown = false;
11364 float mDimCurrentAlpha;
11365 float mDimTargetAlpha;
11366 float mDimDeltaPerMs;
11367 long mLastDimAnimTime;
Dianne Hackbornf83c5552010-03-31 22:19:32 -070011368
11369 int mLastDimWidth, mLastDimHeight;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011370
11371 DimAnimator (SurfaceSession session) {
11372 if (mDimSurface == null) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011373 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011374 + mDimSurface + ": CREATE");
11375 try {
Mathias Agopian5d26c1e2010-03-01 16:09:43 -080011376 mDimSurface = new Surface(session, 0,
11377 "DimSurface",
11378 -1, 16, 16, PixelFormat.OPAQUE,
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011379 Surface.FX_SURFACE_DIM);
11380 } catch (Exception e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011381 Slog.e(TAG, "Exception creating Dim surface", e);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011382 }
11383 }
11384 }
11385
11386 /**
11387 * Show the dim surface.
11388 */
11389 void show(int dw, int dh) {
Dianne Hackborn16064f92010-03-25 00:47:24 -070011390 if (!mDimShown) {
11391 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" +
11392 dw + "x" + dh + ")");
11393 mDimShown = true;
11394 try {
Dianne Hackbornf83c5552010-03-31 22:19:32 -070011395 mLastDimWidth = dw;
11396 mLastDimHeight = dh;
Dianne Hackborn16064f92010-03-25 00:47:24 -070011397 mDimSurface.setPosition(0, 0);
11398 mDimSurface.setSize(dw, dh);
11399 mDimSurface.show();
11400 } catch (RuntimeException e) {
11401 Slog.w(TAG, "Failure showing dim surface", e);
11402 }
Dianne Hackbornf83c5552010-03-31 22:19:32 -070011403 } else if (mLastDimWidth != dw || mLastDimHeight != dh) {
11404 mLastDimWidth = dw;
11405 mLastDimHeight = dh;
11406 mDimSurface.setSize(dw, dh);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011407 }
11408 }
11409
11410 /**
11411 * Set's the dim surface's layer and update dim parameters that will be used in
11412 * {@link updateSurface} after all windows are examined.
11413 */
11414 void updateParameters(WindowState w, long currentTime) {
11415 mDimSurface.setLayer(w.mAnimLayer-1);
11416
11417 final float target = w.mExiting ? 0 : w.mAttrs.dimAmount;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011418 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
Dianne Hackborn0586a1b2009-09-06 21:08:27 -070011419 + ": layer=" + (w.mAnimLayer-1) + " target=" + target);
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011420 if (mDimTargetAlpha != target) {
11421 // If the desired dim level has changed, then
11422 // start an animation to it.
11423 mLastDimAnimTime = currentTime;
11424 long duration = (w.mAnimating && w.mAnimation != null)
11425 ? w.mAnimation.computeDurationHint()
11426 : DEFAULT_DIM_DURATION;
11427 if (target > mDimTargetAlpha) {
11428 // This is happening behind the activity UI,
11429 // so we can make it run a little longer to
11430 // give a stronger impression without disrupting
11431 // the user.
11432 duration *= DIM_DURATION_MULTIPLIER;
11433 }
11434 if (duration < 1) {
11435 // Don't divide by zero
11436 duration = 1;
11437 }
11438 mDimTargetAlpha = target;
11439 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration;
11440 }
11441 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011442
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011443 /**
11444 * Updating the surface's alpha. Returns true if the animation continues, or returns
11445 * false when the animation is finished and the dim surface is hidden.
11446 */
11447 boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) {
11448 if (!dimming) {
11449 if (mDimTargetAlpha != 0) {
11450 mLastDimAnimTime = currentTime;
11451 mDimTargetAlpha = 0;
11452 mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
11453 }
11454 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -080011455
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011456 boolean animating = false;
11457 if (mLastDimAnimTime != 0) {
11458 mDimCurrentAlpha += mDimDeltaPerMs
11459 * (currentTime-mLastDimAnimTime);
11460 boolean more = true;
11461 if (displayFrozen) {
11462 // If the display is frozen, there is no reason to animate.
11463 more = false;
11464 } else if (mDimDeltaPerMs > 0) {
11465 if (mDimCurrentAlpha > mDimTargetAlpha) {
11466 more = false;
11467 }
11468 } else if (mDimDeltaPerMs < 0) {
11469 if (mDimCurrentAlpha < mDimTargetAlpha) {
11470 more = false;
11471 }
11472 } else {
11473 more = false;
11474 }
11475
11476 // Do we need to continue animating?
11477 if (more) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011478 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011479 + mDimSurface + ": alpha=" + mDimCurrentAlpha);
11480 mLastDimAnimTime = currentTime;
11481 mDimSurface.setAlpha(mDimCurrentAlpha);
11482 animating = true;
11483 } else {
11484 mDimCurrentAlpha = mDimTargetAlpha;
11485 mLastDimAnimTime = 0;
Joe Onorato8a9b2202010-02-26 18:56:32 -080011486 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM "
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011487 + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
11488 mDimSurface.setAlpha(mDimCurrentAlpha);
11489 if (!dimming) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011490 if (SHOW_TRANSACTIONS) Slog.i(TAG, " DIM " + mDimSurface
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011491 + ": HIDE");
11492 try {
11493 mDimSurface.hide();
11494 } catch (RuntimeException e) {
Joe Onorato8a9b2202010-02-26 18:56:32 -080011495 Slog.w(TAG, "Illegal argument exception hiding dim surface");
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011496 }
11497 mDimShown = false;
11498 }
11499 }
11500 }
11501 return animating;
11502 }
11503
11504 public void printTo(PrintWriter pw) {
11505 pw.print(" mDimShown="); pw.print(mDimShown);
11506 pw.print(" current="); pw.print(mDimCurrentAlpha);
11507 pw.print(" target="); pw.print(mDimTargetAlpha);
11508 pw.print(" delta="); pw.print(mDimDeltaPerMs);
11509 pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime);
11510 }
11511 }
11512
11513 /**
11514 * Animation that fade in after 0.5 interpolate time, or fade out in reverse order.
11515 * This is used for opening/closing transition for apps in compatible mode.
11516 */
11517 private static class FadeInOutAnimation extends Animation {
11518 int mWidth;
11519 boolean mFadeIn;
11520
11521 public FadeInOutAnimation(boolean fadeIn) {
11522 setInterpolator(new AccelerateInterpolator());
11523 setDuration(DEFAULT_FADE_IN_OUT_DURATION);
11524 mFadeIn = fadeIn;
11525 }
11526
11527 @Override
11528 protected void applyTransformation(float interpolatedTime, Transformation t) {
11529 float x = interpolatedTime;
11530 if (!mFadeIn) {
11531 x = 1.0f - x; // reverse the interpolation for fade out
11532 }
11533 if (x < 0.5) {
11534 // move the window out of the screen.
11535 t.getMatrix().setTranslate(mWidth, 0);
11536 } else {
11537 t.getMatrix().setTranslate(0, 0);// show
11538 t.setAlpha((x - 0.5f) * 2);
11539 }
11540 }
11541
11542 @Override
11543 public void initialize(int width, int height, int parentWidth, int parentHeight) {
11544 // width is the screen width {@see AppWindowToken#stepAnimatinoLocked}
11545 mWidth = width;
11546 }
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011547
11548 @Override
Mitsuru Oshima5a2b91d2009-07-16 16:30:02 -070011549 public int getZAdjustment() {
11550 return Animation.ZORDER_TOP;
Mitsuru Oshima0a5d2c42009-07-14 14:10:30 -070011551 }
11552 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011553}