blob: 7ed0aecdbc0300f6845d00fd90c8d1b5dca1d5f8 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001/*
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;
22import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
23import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
24import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
25import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
26import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
27import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080028import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
29import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070030import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
31import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
32import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_GPU;
33import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_HARDWARE;
34import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_PUSH_BUFFERS;
35import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
36import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080037import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
38import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070039
40import com.android.internal.app.IBatteryStats;
41import com.android.internal.policy.PolicyManager;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080042import com.android.internal.view.IInputContext;
43import com.android.internal.view.IInputMethodClient;
44import com.android.internal.view.IInputMethodManager;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070045import com.android.server.KeyInputQueue.QueuedEvent;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080046import com.android.server.am.BatteryStatsService;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070047
48import android.Manifest;
49import android.app.ActivityManagerNative;
50import android.app.IActivityManager;
51import android.content.Context;
52import android.content.pm.ActivityInfo;
53import android.content.pm.PackageManager;
54import android.content.res.Configuration;
55import android.graphics.Matrix;
56import android.graphics.PixelFormat;
57import android.graphics.Rect;
58import android.graphics.Region;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080059import android.os.BatteryStats;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070060import android.os.Binder;
61import android.os.Debug;
62import android.os.Handler;
63import android.os.IBinder;
64import android.os.LocalPowerManager;
65import android.os.Looper;
66import android.os.Message;
67import android.os.Parcel;
68import android.os.ParcelFileDescriptor;
69import android.os.PowerManager;
70import android.os.Process;
71import android.os.RemoteException;
72import android.os.ServiceManager;
73import android.os.SystemClock;
74import android.os.SystemProperties;
75import android.os.TokenWatcher;
76import android.provider.Settings;
77import android.util.Config;
78import android.util.EventLog;
79import android.util.Log;
80import android.util.SparseIntArray;
81import android.view.Display;
82import android.view.Gravity;
83import android.view.IApplicationToken;
84import android.view.IOnKeyguardExitResult;
85import android.view.IRotationWatcher;
86import android.view.IWindow;
87import android.view.IWindowManager;
88import android.view.IWindowSession;
89import android.view.KeyEvent;
90import android.view.MotionEvent;
91import android.view.RawInputEvent;
92import android.view.Surface;
93import android.view.SurfaceSession;
94import android.view.View;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -080095import android.view.ViewTreeObserver;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -070096import android.view.WindowManager;
97import android.view.WindowManagerImpl;
98import android.view.WindowManagerPolicy;
99import android.view.WindowManager.LayoutParams;
100import android.view.animation.Animation;
101import android.view.animation.AnimationUtils;
102import android.view.animation.Transformation;
103
104import java.io.BufferedWriter;
105import java.io.File;
106import java.io.FileDescriptor;
107import java.io.IOException;
108import java.io.OutputStream;
109import java.io.OutputStreamWriter;
110import java.io.PrintWriter;
111import java.io.StringWriter;
112import java.net.Socket;
113import java.util.ArrayList;
114import java.util.HashMap;
115import java.util.HashSet;
116import java.util.Iterator;
117import java.util.List;
118
119/** {@hide} */
120public class WindowManagerService extends IWindowManager.Stub implements Watchdog.Monitor {
121 static final String TAG = "WindowManager";
122 static final boolean DEBUG = false;
123 static final boolean DEBUG_FOCUS = false;
124 static final boolean DEBUG_ANIM = false;
125 static final boolean DEBUG_INPUT = false;
126 static final boolean DEBUG_VISIBILITY = false;
127 static final boolean DEBUG_ORIENTATION = false;
128 static final boolean DEBUG_APP_TRANSITIONS = false;
129 static final boolean DEBUG_STARTING_WINDOW = false;
130 static final boolean DEBUG_REORDER = false;
131 static final boolean SHOW_TRANSACTIONS = false;
132
133 static final boolean PROFILE_ORIENTATION = false;
134 static final boolean BLUR = true;
135 static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
136
137 static final int LOG_WM_NO_SURFACE_MEMORY = 31000;
138
139 /** How long to wait for first key repeat, in milliseconds */
140 static final int KEY_REPEAT_FIRST_DELAY = 750;
141
142 /** How long to wait for subsequent key repeats, in milliseconds */
143 static final int KEY_REPEAT_DELAY = 50;
144
145 /** How much to multiply the policy's type layer, to reserve room
146 * for multiple windows of the same type and Z-ordering adjustment
147 * with TYPE_LAYER_OFFSET. */
148 static final int TYPE_LAYER_MULTIPLIER = 10000;
149
150 /** Offset from TYPE_LAYER_MULTIPLIER for moving a group of windows above
151 * or below others in the same layer. */
152 static final int TYPE_LAYER_OFFSET = 1000;
153
154 /** How much to increment the layer for each window, to reserve room
155 * for effect surfaces between them.
156 */
157 static final int WINDOW_LAYER_MULTIPLIER = 5;
158
159 /** The maximum length we will accept for a loaded animation duration:
160 * this is 10 seconds.
161 */
162 static final int MAX_ANIMATION_DURATION = 10*1000;
163
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800164 /** Amount of time (in milliseconds) to animate the dim surface from one
165 * value to another, when no window animation is driving it.
166 */
167 static final int DEFAULT_DIM_DURATION = 200;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -0800168
169 /** Adjustment to time to perform a dim, to make it more dramatic.
170 */
171 static final int DIM_DURATION_MULTIPLIER = 6;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800172
173 static final int UPDATE_FOCUS_NORMAL = 0;
174 static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
175 static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
176 static final int UPDATE_FOCUS_WILL_PLACE_SURFACES = 3;
177
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700178 private static final String SYSTEM_SECURE = "ro.secure";
179
180 /**
181 * Condition waited on by {@link #reenableKeyguard} to know the call to
182 * the window policy has finished.
183 */
184 private boolean mWaitingUntilKeyguardReenabled = false;
185
186
187 final TokenWatcher mKeyguardDisabled = new TokenWatcher(
188 new Handler(), "WindowManagerService.mKeyguardDisabled") {
189 public void acquired() {
190 mPolicy.enableKeyguard(false);
191 }
192 public void released() {
193 synchronized (mKeyguardDisabled) {
194 mPolicy.enableKeyguard(true);
195 mWaitingUntilKeyguardReenabled = false;
196 mKeyguardDisabled.notifyAll();
197 }
198 }
199 };
200
201 final Context mContext;
202
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800203 final boolean mHaveInputMethods;
204
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700205 final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
206
207 final IActivityManager mActivityManager;
208
209 final IBatteryStats mBatteryStats;
210
211 /**
212 * All currently active sessions with clients.
213 */
214 final HashSet<Session> mSessions = new HashSet<Session>();
215
216 /**
217 * Mapping from an IWindow IBinder to the server's Window object.
218 * This is also used as the lock for all of our state.
219 */
220 final HashMap<IBinder, WindowState> mWindowMap = new HashMap<IBinder, WindowState>();
221
222 /**
223 * Mapping from a token IBinder to a WindowToken object.
224 */
225 final HashMap<IBinder, WindowToken> mTokenMap =
226 new HashMap<IBinder, WindowToken>();
227
228 /**
229 * The same tokens as mTokenMap, stored in a list for efficient iteration
230 * over them.
231 */
232 final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
233
234 /**
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800235 * Window tokens that are in the process of exiting, but still
236 * on screen for animations.
237 */
238 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
239
240 /**
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700241 * Z-ordered (bottom-most first) list of all application tokens, for
242 * controlling the ordering of windows in different applications. This
243 * contains WindowToken objects.
244 */
245 final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
246
247 /**
248 * Application tokens that are in the process of exiting, but still
249 * on screen for animations.
250 */
251 final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
252
253 /**
254 * List of window tokens that have finished starting their application,
255 * and now need to have the policy remove their windows.
256 */
257 final ArrayList<AppWindowToken> mFinishedStarting = new ArrayList<AppWindowToken>();
258
259 /**
260 * Z-ordered (bottom-most first) list of all Window objects.
261 */
262 final ArrayList mWindows = new ArrayList();
263
264 /**
265 * Windows that are being resized. Used so we can tell the client about
266 * the resize after closing the transaction in which we resized the
267 * underlying surface.
268 */
269 final ArrayList<WindowState> mResizingWindows = new ArrayList<WindowState>();
270
271 /**
272 * Windows whose animations have ended and now must be removed.
273 */
274 final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
275
276 /**
277 * Windows whose surface should be destroyed.
278 */
279 final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
280
281 /**
282 * Windows that have lost input focus and are waiting for the new
283 * focus window to be displayed before they are told about this.
284 */
285 ArrayList<WindowState> mLosingFocus = new ArrayList<WindowState>();
286
287 /**
288 * This is set when we have run out of memory, and will either be an empty
289 * list or contain windows that need to be force removed.
290 */
291 ArrayList<WindowState> mForceRemoves;
292
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800293 IInputMethodManager mInputMethodManager;
294
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700295 SurfaceSession mFxSession;
296 Surface mDimSurface;
297 boolean mDimShown;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800298 float mDimCurrentAlpha;
299 float mDimTargetAlpha;
300 float mDimDeltaPerMs;
301 long mLastDimAnimTime;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700302 Surface mBlurSurface;
303 boolean mBlurShown;
304
305 int mTransactionSequence = 0;
306
307 final float[] mTmpFloats = new float[9];
308
309 boolean mDisplayEnabled = false;
310 boolean mSystemBooted = false;
311 int mRotation = 0;
312 int mRequestedRotation = 0;
313 int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
314 ArrayList<IRotationWatcher> mRotationWatchers
315 = new ArrayList<IRotationWatcher>();
316
317 boolean mLayoutNeeded = true;
318 boolean mAnimationPending = false;
319 boolean mSurfacesChanged = false;
320 boolean mDisplayFrozen = false;
321 boolean mWindowsFreezingScreen = false;
322 long mFreezeGcPending = 0;
323 int mAppsFreezingScreen = 0;
324
325 // State management of app transitions. When we are preparing for a
326 // transition, mNextAppTransition will be the kind of transition to
327 // perform or TRANSIT_NONE if we are not waiting. If we are waiting,
328 // mOpeningApps and mClosingApps are the lists of tokens that will be
329 // made visible or hidden at the next transition.
330 int mNextAppTransition = WindowManagerPolicy.TRANSIT_NONE;
331 boolean mAppTransitionReady = false;
332 boolean mAppTransitionTimeout = false;
333 boolean mStartingIconInTransition = false;
334 boolean mSkipAppTransitionAnimation = false;
335 final ArrayList<AppWindowToken> mOpeningApps = new ArrayList<AppWindowToken>();
336 final ArrayList<AppWindowToken> mClosingApps = new ArrayList<AppWindowToken>();
337
338 //flag to detect fat touch events
339 boolean mFatTouch = false;
340 Display mDisplay;
341
342 H mH = new H();
343
344 WindowState mCurrentFocus = null;
345 WindowState mLastFocus = null;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800346
347 // This just indicates the window the input method is on top of, not
348 // necessarily the window its input is going to.
349 WindowState mInputMethodTarget = null;
350
351 WindowState mInputMethodWindow = null;
352 final ArrayList<WindowState> mInputMethodDialogs = new ArrayList<WindowState>();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700353
354 AppWindowToken mFocusedApp = null;
355
356 PowerManagerService mPowerManager;
357
358 float mWindowAnimationScale = 1.0f;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800359 float mTransitionAnimationScale = 1.0f;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700360
361 final KeyWaiter mKeyWaiter = new KeyWaiter();
362 final KeyQ mQueue;
363 final InputDispatcherThread mInputThread;
364
365 // Who is holding the screen on.
366 Session mHoldingScreenOn;
367
368 /**
369 * Whether the UI is currently running in touch mode (not showing
370 * navigational focus because the user is directly pressing the screen).
371 */
372 boolean mInTouchMode = false;
373
374 private ViewServer mViewServer;
375
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800376 final Rect mTempRect = new Rect();
377
378 public static WindowManagerService main(Context context,
379 PowerManagerService pm, boolean haveInputMethods) {
380 WMThread thr = new WMThread(context, pm, haveInputMethods);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700381 thr.start();
382
383 synchronized (thr) {
384 while (thr.mService == null) {
385 try {
386 thr.wait();
387 } catch (InterruptedException e) {
388 }
389 }
390 }
391
392 return thr.mService;
393 }
394
395 static class WMThread extends Thread {
396 WindowManagerService mService;
397
398 private final Context mContext;
399 private final PowerManagerService mPM;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800400 private final boolean mHaveInputMethods;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700401
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800402 public WMThread(Context context, PowerManagerService pm,
403 boolean haveInputMethods) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700404 super("WindowManager");
405 mContext = context;
406 mPM = pm;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800407 mHaveInputMethods = haveInputMethods;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700408 }
409
410 public void run() {
411 Looper.prepare();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800412 WindowManagerService s = new WindowManagerService(mContext, mPM,
413 mHaveInputMethods);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700414 android.os.Process.setThreadPriority(
415 android.os.Process.THREAD_PRIORITY_DISPLAY);
416
417 synchronized (this) {
418 mService = s;
419 notifyAll();
420 }
421
422 Looper.loop();
423 }
424 }
425
426 static class PolicyThread extends Thread {
427 private final WindowManagerPolicy mPolicy;
428 private final WindowManagerService mService;
429 private final Context mContext;
430 private final PowerManagerService mPM;
431 boolean mRunning = false;
432
433 public PolicyThread(WindowManagerPolicy policy,
434 WindowManagerService service, Context context,
435 PowerManagerService pm) {
436 super("WindowManagerPolicy");
437 mPolicy = policy;
438 mService = service;
439 mContext = context;
440 mPM = pm;
441 }
442
443 public void run() {
444 Looper.prepare();
445 //Looper.myLooper().setMessageLogging(new LogPrinter(
446 // Log.VERBOSE, "WindowManagerPolicy"));
447 android.os.Process.setThreadPriority(
448 android.os.Process.THREAD_PRIORITY_FOREGROUND);
449 mPolicy.init(mContext, mService, mPM);
450
451 synchronized (this) {
452 mRunning = true;
453 notifyAll();
454 }
455
456 Looper.loop();
457 }
458 }
459
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800460 private WindowManagerService(Context context, PowerManagerService pm,
461 boolean haveInputMethods) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700462 mContext = context;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800463 mHaveInputMethods = haveInputMethods;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700464
465 mPowerManager = pm;
466 mPowerManager.setPolicy(mPolicy);
467
468 mActivityManager = ActivityManagerNative.getDefault();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800469 mBatteryStats = BatteryStatsService.getService();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700470
471 // Get persisted window scale setting
472 mWindowAnimationScale = Settings.System.getFloat(context.getContentResolver(),
473 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
474 mTransitionAnimationScale = Settings.System.getFloat(context.getContentResolver(),
475 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
476
477 mQueue = new KeyQ();
478
479 mInputThread = new InputDispatcherThread();
480
481 PolicyThread thr = new PolicyThread(mPolicy, this, context, pm);
482 thr.start();
483
484 synchronized (thr) {
485 while (!thr.mRunning) {
486 try {
487 thr.wait();
488 } catch (InterruptedException e) {
489 }
490 }
491 }
492
493 mInputThread.start();
494
495 // Add ourself to the Watchdog monitors.
496 Watchdog.getInstance().addMonitor(this);
497 }
498
499 @Override
500 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
501 throws RemoteException {
502 try {
503 return super.onTransact(code, data, reply, flags);
504 } catch (RuntimeException e) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800505 // The window manager only throws security exceptions, so let's
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700506 // log all others.
507 if (!(e instanceof SecurityException)) {
508 Log.e(TAG, "Window Manager Crash", e);
509 }
510 throw e;
511 }
512 }
513
514 private void placeWindowAfter(Object pos, WindowState window) {
515 final int i = mWindows.indexOf(pos);
516 if (localLOGV || DEBUG_FOCUS) Log.v(
517 TAG, "Adding window " + window + " at "
518 + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
519 mWindows.add(i+1, window);
520 }
521
522 private void placeWindowBefore(Object pos, WindowState window) {
523 final int i = mWindows.indexOf(pos);
524 if (localLOGV || DEBUG_FOCUS) Log.v(
525 TAG, "Adding window " + window + " at "
526 + i + " of " + mWindows.size() + " (before " + pos + ")");
527 mWindows.add(i, window);
528 }
529
530 //This method finds out the index of a window that has the same app token as
531 //win. used for z ordering the windows in mWindows
532 private int findIdxBasedOnAppTokens(WindowState win) {
533 //use a local variable to cache mWindows
534 ArrayList localmWindows = mWindows;
535 int jmax = localmWindows.size();
536 if(jmax == 0) {
537 return -1;
538 }
539 for(int j = (jmax-1); j >= 0; j--) {
540 WindowState wentry = (WindowState)localmWindows.get(j);
541 if(wentry.mAppToken == win.mAppToken) {
542 return j;
543 }
544 }
545 return -1;
546 }
547
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800548 private void addWindowToListInOrderLocked(WindowState win, boolean addToToken) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700549 final IWindow client = win.mClient;
550 final WindowToken token = win.mToken;
551 final ArrayList localmWindows = mWindows;
552
553 final int N = localmWindows.size();
554 final WindowState attached = win.mAttachedWindow;
555 int i;
556 if (attached == null) {
557 int tokenWindowsPos = token.windows.size();
558 if (token.appWindowToken != null) {
559 int index = tokenWindowsPos-1;
560 if (index >= 0) {
561 // If this application has existing windows, we
562 // simply place the new window on top of them... but
563 // keep the starting window on top.
564 if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
565 // Base windows go behind everything else.
566 placeWindowBefore(token.windows.get(0), win);
567 tokenWindowsPos = 0;
568 } else {
569 AppWindowToken atoken = win.mAppToken;
570 if (atoken != null &&
571 token.windows.get(index) == atoken.startingWindow) {
572 placeWindowBefore(token.windows.get(index), win);
573 tokenWindowsPos--;
574 } else {
575 int newIdx = findIdxBasedOnAppTokens(win);
576 if(newIdx != -1) {
577 //there is a window above this one associated with the same
578 //apptoken note that the window could be a floating window
579 //that was created later or a window at the top of the list of
580 //windows associated with this token.
581 localmWindows.add(newIdx+1, win);
582 }
583 }
584 }
585 } else {
586 if (localLOGV) Log.v(
587 TAG, "Figuring out where to add app window "
588 + client.asBinder() + " (token=" + token + ")");
589 // Figure out where the window should go, based on the
590 // order of applications.
591 final int NA = mAppTokens.size();
592 Object pos = null;
593 for (i=NA-1; i>=0; i--) {
594 AppWindowToken t = mAppTokens.get(i);
595 if (t == token) {
596 i--;
597 break;
598 }
599 if (t.windows.size() > 0) {
600 pos = t.windows.get(0);
601 }
602 }
603 // We now know the index into the apps. If we found
604 // an app window above, that gives us the position; else
605 // we need to look some more.
606 if (pos != null) {
607 // Move behind any windows attached to this one.
608 WindowToken atoken =
609 mTokenMap.get(((WindowState)pos).mClient.asBinder());
610 if (atoken != null) {
611 final int NC = atoken.windows.size();
612 if (NC > 0) {
613 WindowState bottom = atoken.windows.get(0);
614 if (bottom.mSubLayer < 0) {
615 pos = bottom;
616 }
617 }
618 }
619 placeWindowBefore(pos, win);
620 } else {
621 while (i >= 0) {
622 AppWindowToken t = mAppTokens.get(i);
623 final int NW = t.windows.size();
624 if (NW > 0) {
625 pos = t.windows.get(NW-1);
626 break;
627 }
628 i--;
629 }
630 if (pos != null) {
631 // Move in front of any windows attached to this
632 // one.
633 WindowToken atoken =
634 mTokenMap.get(((WindowState)pos).mClient.asBinder());
635 if (atoken != null) {
636 final int NC = atoken.windows.size();
637 if (NC > 0) {
638 WindowState top = atoken.windows.get(NC-1);
639 if (top.mSubLayer >= 0) {
640 pos = top;
641 }
642 }
643 }
644 placeWindowAfter(pos, win);
645 } else {
646 // Just search for the start of this layer.
647 final int myLayer = win.mBaseLayer;
648 for (i=0; i<N; i++) {
649 WindowState w = (WindowState)localmWindows.get(i);
650 if (w.mBaseLayer > myLayer) {
651 break;
652 }
653 }
654 if (localLOGV || DEBUG_FOCUS) Log.v(
655 TAG, "Adding window " + win + " at "
656 + i + " of " + N);
657 localmWindows.add(i, win);
658 }
659 }
660 }
661 } else {
662 // Figure out where window should go, based on layer.
663 final int myLayer = win.mBaseLayer;
664 for (i=N-1; i>=0; i--) {
665 if (((WindowState)localmWindows.get(i)).mBaseLayer <= myLayer) {
666 i++;
667 break;
668 }
669 }
670 if (i < 0) i = 0;
671 if (localLOGV || DEBUG_FOCUS) Log.v(
672 TAG, "Adding window " + win + " at "
673 + i + " of " + N);
674 localmWindows.add(i, win);
675 }
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800676 if (addToToken) {
677 token.windows.add(tokenWindowsPos, win);
678 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700679
680 } else {
681 // Figure out this window's ordering relative to the window
682 // it is attached to.
683 final int NA = token.windows.size();
684 final int sublayer = win.mSubLayer;
685 int largestSublayer = Integer.MIN_VALUE;
686 WindowState windowWithLargestSublayer = null;
687 for (i=0; i<NA; i++) {
688 WindowState w = token.windows.get(i);
689 final int wSublayer = w.mSubLayer;
690 if (wSublayer >= largestSublayer) {
691 largestSublayer = wSublayer;
692 windowWithLargestSublayer = w;
693 }
694 if (sublayer < 0) {
695 // For negative sublayers, we go below all windows
696 // in the same sublayer.
697 if (wSublayer >= sublayer) {
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800698 if (addToToken) {
699 token.windows.add(i, win);
700 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700701 placeWindowBefore(
702 wSublayer >= 0 ? attached : w, win);
703 break;
704 }
705 } else {
706 // For positive sublayers, we go above all windows
707 // in the same sublayer.
708 if (wSublayer > sublayer) {
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800709 if (addToToken) {
710 token.windows.add(i, win);
711 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700712 placeWindowBefore(w, win);
713 break;
714 }
715 }
716 }
717 if (i >= NA) {
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800718 if (addToToken) {
719 token.windows.add(win);
720 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700721 if (sublayer < 0) {
722 placeWindowBefore(attached, win);
723 } else {
724 placeWindowAfter(largestSublayer >= 0
725 ? windowWithLargestSublayer
726 : attached,
727 win);
728 }
729 }
730 }
731
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800732 if (win.mAppToken != null && addToToken) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700733 win.mAppToken.allAppWindows.add(win);
734 }
735 }
736
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800737 int findDesiredInputMethodWindowIndexLocked() {
738 final ArrayList localmWindows = mWindows;
739 final int N = localmWindows.size();
740 WindowState w = null;
741 int i = N;
742 while (i > 0) {
743 i--;
744 w = (WindowState)localmWindows.get(i);
745 final int fl = w.mAttrs.flags
746 & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
747 //Log.i(TAG, "Checking window @" + i + " " + w + " fl=0x"
748 // + Integer.toHexString(fl));
749 if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) {
750 //Log.i(TAG, "Putting input method here!");
751 if (w.isVisibleOrAdding()) {
752 break;
753 }
754 }
755 }
756 //Log.i(TAG, "Placing input method @" + (i+1));
757 if (w != null) {
758 mInputMethodTarget = w;
759 return i+1;
760 }
761 mInputMethodTarget = null;
762 return -1;
763 }
764
765 void addInputMethodWindowToListLocked(WindowState win) {
766 int pos = findDesiredInputMethodWindowIndexLocked();
767 if (pos >= 0) {
768 win.mTargetAppToken = mInputMethodTarget.mAppToken;
769 mWindows.add(pos, win);
770 moveInputMethodDialogsLocked(pos+1);
771 return;
772 }
773 win.mTargetAppToken = null;
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800774 addWindowToListInOrderLocked(win, true);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800775 moveInputMethodDialogsLocked(pos);
776 }
777
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800778 private int tmpRemoveWindowLocked(int interestingPos, WindowState win) {
779 int wpos = mWindows.indexOf(win);
780 if (wpos >= 0) {
781 if (wpos < interestingPos) interestingPos--;
782 mWindows.remove(wpos);
783 int NC = win.mChildWindows.size();
784 while (NC > 0) {
785 NC--;
786 WindowState cw = (WindowState)win.mChildWindows.get(NC);
787 int cpos = mWindows.indexOf(cw);
788 if (cpos >= 0) {
789 if (cpos < interestingPos) interestingPos--;
790 mWindows.remove(cpos);
791 }
792 }
793 }
794 return interestingPos;
795 }
796
797 private void reAddWindowToListInOrderLocked(WindowState win) {
798 addWindowToListInOrderLocked(win, false);
799 // This is a hack to get all of the child windows added as well
800 // at the right position. Child windows should be rare and
801 // this case should be rare, so it shouldn't be that big a deal.
802 int wpos = mWindows.indexOf(win);
803 if (wpos >= 0) {
804 mWindows.remove(wpos);
805 reAddWindowLocked(wpos, win);
806 }
807 }
808
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800809 void moveInputMethodDialogsLocked(int pos) {
810 ArrayList<WindowState> dialogs = mInputMethodDialogs;
811 final int N = dialogs.size();
812 for (int i=0; i<N; i++) {
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800813 pos = tmpRemoveWindowLocked(pos, dialogs.get(i));
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800814 }
815 if (pos >= 0) {
816 final AppWindowToken targetAppToken = mInputMethodTarget.mAppToken;
817 WindowState wp = (WindowState)mWindows.get(pos);
818 if (wp == mInputMethodWindow) {
819 pos++;
820 }
821 for (int i=0; i<N; i++) {
822 WindowState win = dialogs.get(i);
823 win.mTargetAppToken = targetAppToken;
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800824 pos = reAddWindowLocked(pos, win);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800825 }
826 return;
827 }
828 for (int i=0; i<N; i++) {
829 WindowState win = dialogs.get(i);
830 win.mTargetAppToken = null;
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800831 reAddWindowToListInOrderLocked(win);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800832 }
833 }
834
835 boolean moveInputMethodWindowsIfNeededLocked(boolean needAssignLayers) {
836 final WindowState imWin = mInputMethodWindow;
837 final int DN = mInputMethodDialogs.size();
838 if (imWin == null && DN == 0) {
839 return false;
840 }
841
842 int imPos = findDesiredInputMethodWindowIndexLocked();
843 if (imPos >= 0) {
844 // In this case, the input method windows are to be placed
845 // immediately above the window they are targeting.
846
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800847 // First check to see if the input method windows are already
848 // located here, and contiguous.
849 final int N = mWindows.size();
850 WindowState firstImWin = imPos < N
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800851 ? (WindowState)mWindows.get(imPos) : null;
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800852
853 // Figure out the actual input method window that should be
854 // at the bottom of their stack.
855 WindowState baseImWin = imWin != null
856 ? imWin : mInputMethodDialogs.get(0);
857 if (baseImWin.mChildWindows.size() > 0) {
858 WindowState cw = (WindowState)baseImWin.mChildWindows.get(0);
859 if (cw.mSubLayer < 0) baseImWin = cw;
860 }
861
862 if (firstImWin == baseImWin) {
863 // The windows haven't moved... but are they still contiguous?
864 // First find the top IM window.
865 int pos = imPos+1;
866 while (pos < N) {
867 if (!((WindowState)mWindows.get(pos)).mIsImWindow) {
868 break;
869 }
870 pos++;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800871 }
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800872 pos++;
873 // Now there should be no more input method windows above.
874 while (pos < N) {
875 if (((WindowState)mWindows.get(pos)).mIsImWindow) {
876 break;
877 }
878 pos++;
879 }
880 if (pos >= N) {
881 // All is good!
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800882 return false;
883 }
884 }
885
886 if (imWin != null) {
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800887 imPos = tmpRemoveWindowLocked(imPos, imWin);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800888 imWin.mTargetAppToken = mInputMethodTarget.mAppToken;
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800889 reAddWindowLocked(imPos, imWin);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800890 if (DN > 0) moveInputMethodDialogsLocked(imPos+1);
891 } else {
892 moveInputMethodDialogsLocked(imPos);
893 }
894
895 } else {
896 // In this case, the input method windows go in a fixed layer,
897 // because they aren't currently associated with a focus window.
898
899 if (imWin != null) {
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800900 tmpRemoveWindowLocked(0, imWin);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800901 imWin.mTargetAppToken = null;
The Android Open Source Project9266c5582009-01-15 16:12:10 -0800902 reAddWindowToListInOrderLocked(imWin);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800903 if (DN > 0) moveInputMethodDialogsLocked(-1);;
904 } else {
905 moveInputMethodDialogsLocked(-1);;
906 }
907
908 }
909
910 if (needAssignLayers) {
911 assignLayersLocked();
912 }
913
914 return true;
915 }
916
917 void adjustInputMethodDialogsLocked() {
918 moveInputMethodDialogsLocked(findDesiredInputMethodWindowIndexLocked());
919 }
920
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700921 public int addWindow(Session session, IWindow client,
922 WindowManager.LayoutParams attrs, int viewVisibility,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800923 Rect outContentInsets) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700924 int res = mPolicy.checkAddPermission(attrs);
925 if (res != WindowManagerImpl.ADD_OKAY) {
926 return res;
927 }
928
929 boolean reportNewConfig = false;
930 WindowState attachedWindow = null;
931 WindowState win = null;
932
933 synchronized(mWindowMap) {
934 // Instantiating a Display requires talking with the simulator,
935 // so don't do it until we know the system is mostly up and
936 // running.
937 if (mDisplay == null) {
938 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
939 mDisplay = wm.getDefaultDisplay();
940 mQueue.setDisplay(mDisplay);
941 reportNewConfig = true;
942 }
943
944 if (mWindowMap.containsKey(client.asBinder())) {
945 Log.w(TAG, "Window " + client + " is already added");
946 return WindowManagerImpl.ADD_DUPLICATE_ADD;
947 }
948
949 if (attrs.type >= FIRST_SUB_WINDOW && attrs.type <= LAST_SUB_WINDOW) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800950 attachedWindow = windowForClientLocked(null, attrs.token);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700951 if (attachedWindow == null) {
952 Log.w(TAG, "Attempted to add window with token that is not a window: "
953 + attrs.token + ". Aborting.");
954 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
955 }
956 if (attachedWindow.mAttrs.type >= FIRST_SUB_WINDOW
957 && attachedWindow.mAttrs.type <= LAST_SUB_WINDOW) {
958 Log.w(TAG, "Attempted to add window with token that is a sub-window: "
959 + attrs.token + ". Aborting.");
960 return WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN;
961 }
962 }
963
964 boolean addToken = false;
965 WindowToken token = mTokenMap.get(attrs.token);
966 if (token == null) {
967 if (attrs.type >= FIRST_APPLICATION_WINDOW
968 && attrs.type <= LAST_APPLICATION_WINDOW) {
969 Log.w(TAG, "Attempted to add application window with unknown token "
970 + attrs.token + ". Aborting.");
971 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
972 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800973 if (attrs.type == TYPE_INPUT_METHOD) {
974 Log.w(TAG, "Attempted to add input method window with unknown token "
975 + attrs.token + ". Aborting.");
976 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
977 }
978 token = new WindowToken(attrs.token, -1);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -0700979 addToken = true;
980 } else if (attrs.type >= FIRST_APPLICATION_WINDOW
981 && attrs.type <= LAST_APPLICATION_WINDOW) {
982 AppWindowToken atoken = token.appWindowToken;
983 if (atoken == null) {
984 Log.w(TAG, "Attempted to add window with non-application token "
985 + token + ". Aborting.");
986 return WindowManagerImpl.ADD_NOT_APP_TOKEN;
987 } else if (atoken.removed) {
988 Log.w(TAG, "Attempted to add window with exiting application token "
989 + token + ". Aborting.");
990 return WindowManagerImpl.ADD_APP_EXITING;
991 }
992 if (attrs.type == TYPE_APPLICATION_STARTING && atoken.firstWindowDrawn) {
993 // No need for this guy!
994 if (localLOGV) Log.v(
995 TAG, "**** NO NEED TO START: " + attrs.getTitle());
996 return WindowManagerImpl.ADD_STARTING_NOT_NEEDED;
997 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -0800998 } else if (attrs.type == TYPE_INPUT_METHOD) {
999 if (token.windowType != TYPE_INPUT_METHOD) {
1000 Log.w(TAG, "Attempted to add input method window with bad token "
1001 + attrs.token + ". Aborting.");
1002 return WindowManagerImpl.ADD_BAD_APP_TOKEN;
1003 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001004 }
1005
1006 win = new WindowState(session, client, token,
1007 attachedWindow, attrs, viewVisibility);
1008 if (win.mDeathRecipient == null) {
1009 // Client has apparently died, so there is no reason to
1010 // continue.
1011 Log.w(TAG, "Adding window client " + client.asBinder()
1012 + " that is dead, aborting.");
1013 return WindowManagerImpl.ADD_APP_EXITING;
1014 }
1015
1016 mPolicy.adjustWindowParamsLw(win.mAttrs);
1017
1018 res = mPolicy.prepareAddWindowLw(win, attrs);
1019 if (res != WindowManagerImpl.ADD_OKAY) {
1020 return res;
1021 }
1022
1023 // From now on, no exceptions or errors allowed!
1024
1025 res = WindowManagerImpl.ADD_OKAY;
1026
1027 final long origId = Binder.clearCallingIdentity();
1028
1029 if (addToken) {
1030 mTokenMap.put(attrs.token, token);
1031 mTokenList.add(token);
1032 }
1033 win.attach();
1034 mWindowMap.put(client.asBinder(), win);
1035
1036 if (attrs.type == TYPE_APPLICATION_STARTING &&
1037 token.appWindowToken != null) {
1038 token.appWindowToken.startingWindow = win;
1039 }
1040
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001041 boolean imMayMove = true;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001042
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001043 if (attrs.type == TYPE_INPUT_METHOD) {
1044 mInputMethodWindow = win;
1045 addInputMethodWindowToListLocked(win);
1046 imMayMove = false;
1047 } else if (attrs.type == TYPE_INPUT_METHOD_DIALOG) {
1048 mInputMethodDialogs.add(win);
The Android Open Source Project9266c5582009-01-15 16:12:10 -08001049 addWindowToListInOrderLocked(win, true);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001050 adjustInputMethodDialogsLocked();
1051 imMayMove = false;
1052 } else {
The Android Open Source Project9266c5582009-01-15 16:12:10 -08001053 addWindowToListInOrderLocked(win, true);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001054 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001055
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001056 Binder.restoreCallingIdentity(origId);
1057
1058 win.mEnterAnimationPending = true;
1059
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001060 mPolicy.getContentInsetHintLw(attrs, outContentInsets);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001061
1062 if (mInTouchMode) {
1063 res |= WindowManagerImpl.ADD_FLAG_IN_TOUCH_MODE;
1064 }
1065 if (win == null || win.mAppToken == null || !win.mAppToken.clientHidden) {
1066 res |= WindowManagerImpl.ADD_FLAG_APP_VISIBLE;
1067 }
1068
1069 if (win.canReceiveKeys()) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001070 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS)) {
1071 imMayMove = false;
1072 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001073 }
1074
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001075 if (imMayMove) {
1076 moveInputMethodWindowsIfNeededLocked(false);
1077 }
1078
1079 assignLayersLocked();
1080 // Don't do layout here, the window must call
1081 // relayout to be displayed, so we'll do it there.
1082
1083 //dump();
1084
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001085 if (localLOGV) Log.v(
1086 TAG, "New client " + client.asBinder()
1087 + ": window=" + win);
1088 }
1089
1090 if (reportNewConfig) {
1091 final long origId = Binder.clearCallingIdentity();
1092 sendNewConfiguration();
1093 Binder.restoreCallingIdentity(origId);
1094 }
1095
1096 return res;
1097 }
1098
1099 public void removeWindow(Session session, IWindow client) {
1100 synchronized(mWindowMap) {
1101 WindowState win = windowForClientLocked(session, client);
1102 if (win == null) {
1103 return;
1104 }
1105 removeWindowLocked(session, win);
1106 }
1107 }
1108
1109 public void removeWindowLocked(Session session, WindowState win) {
1110
1111 if (localLOGV || DEBUG_FOCUS) Log.v(
1112 TAG, "Remove " + win + " client="
1113 + Integer.toHexString(System.identityHashCode(
1114 win.mClient.asBinder()))
1115 + ", surface=" + win.mSurface);
1116
1117 final long origId = Binder.clearCallingIdentity();
1118
1119 if (DEBUG_APP_TRANSITIONS) Log.v(
1120 TAG, "Remove " + win + ": mSurface=" + win.mSurface
1121 + " mExiting=" + win.mExiting
1122 + " isAnimating=" + win.isAnimating()
1123 + " app-animation="
1124 + (win.mAppToken != null ? win.mAppToken.animation : null)
1125 + " inPendingTransaction="
1126 + (win.mAppToken != null ? win.mAppToken.inPendingTransaction : false)
1127 + " mDisplayFrozen=" + mDisplayFrozen);
1128
1129 // First, see if we need to run an animation. If we do, we have
1130 // to hold off on removing the window until the animation is done.
1131 // If the display is frozen, just remove immediately, since the
1132 // animation wouldn't be seen.
1133 if (win.mSurface != null && !mDisplayFrozen) {
1134 // If we are not currently running the exit animation, we
1135 // need to see about starting one.
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001136 if (win.isVisibleLw()) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001137 int transit = WindowManagerPolicy.TRANSIT_EXIT;
1138 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
1139 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
1140 }
1141 // Try starting an animation.
1142 if (applyAnimationLocked(win, transit, false)) {
1143 win.mExiting = true;
1144 }
1145 }
1146 if (win.mExiting || win.isAnimating()) {
1147 // The exit animation is running... wait for it!
1148 //Log.i(TAG, "*** Running exit animation...");
1149 win.mExiting = true;
1150 win.mRemoveOnExit = true;
1151 mLayoutNeeded = true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001152 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001153 performLayoutAndPlaceSurfacesLocked();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001154 if (win.mAppToken != null) {
1155 win.mAppToken.updateReportedVisibilityLocked();
1156 }
1157 //dump();
1158 Binder.restoreCallingIdentity(origId);
1159 return;
1160 }
1161 }
1162
1163 removeWindowInnerLocked(session, win);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001164 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001165 Binder.restoreCallingIdentity(origId);
1166 }
1167
1168 private void removeWindowInnerLocked(Session session, WindowState win) {
1169 mKeyWaiter.releasePendingPointerLocked(win.mSession);
1170 mKeyWaiter.releasePendingTrackballLocked(win.mSession);
1171
1172 mPolicy.removeWindowLw(win);
1173 win.removeLocked();
1174
1175 mWindowMap.remove(win.mClient.asBinder());
1176 mWindows.remove(win);
1177
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001178 if (mInputMethodWindow == win) {
1179 mInputMethodWindow = null;
1180 } else if (win.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
1181 mInputMethodDialogs.remove(win);
1182 }
1183
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001184 final WindowToken token = win.mToken;
1185 final AppWindowToken atoken = win.mAppToken;
1186 token.windows.remove(win);
1187 if (atoken != null) {
1188 atoken.allAppWindows.remove(win);
1189 }
1190 if (localLOGV) Log.v(
1191 TAG, "**** Removing window " + win + ": count="
1192 + token.windows.size());
1193 if (token.windows.size() == 0) {
1194 if (atoken != token) {
1195 mTokenMap.remove(token.token);
1196 mTokenList.remove(token);
1197 } else {
1198 atoken.firstWindowDrawn = false;
1199 }
1200 }
1201
1202 if (atoken != null) {
1203 if (atoken.startingWindow == win) {
1204 atoken.startingWindow = null;
1205 } else if (atoken.allAppWindows.size() == 0 && atoken.startingData != null) {
1206 // If this is the last window and we had requested a starting
1207 // transition window, well there is no point now.
1208 atoken.startingData = null;
1209 } else if (atoken.allAppWindows.size() == 1 && atoken.startingView != null) {
1210 // If this is the last window except for a starting transition
1211 // window, we need to get rid of the starting transition.
1212 if (DEBUG_STARTING_WINDOW) {
1213 Log.v(TAG, "Schedule remove starting " + token
1214 + ": no more real windows");
1215 }
1216 Message m = mH.obtainMessage(H.REMOVE_STARTING, atoken);
1217 mH.sendMessage(m);
1218 }
1219 }
1220
1221 if (!mInLayout) {
1222 assignLayersLocked();
1223 mLayoutNeeded = true;
1224 performLayoutAndPlaceSurfacesLocked();
1225 if (win.mAppToken != null) {
1226 win.mAppToken.updateReportedVisibilityLocked();
1227 }
1228 }
1229 }
1230
1231 private void setTransparentRegionWindow(Session session, IWindow client, Region region) {
1232 long origId = Binder.clearCallingIdentity();
1233 try {
1234 synchronized (mWindowMap) {
1235 WindowState w = windowForClientLocked(session, client);
1236 if ((w != null) && (w.mSurface != null)) {
1237 Surface.openTransaction();
1238 try {
1239 w.mSurface.setTransparentRegionHint(region);
1240 } finally {
1241 Surface.closeTransaction();
1242 }
1243 }
1244 }
1245 } finally {
1246 Binder.restoreCallingIdentity(origId);
1247 }
1248 }
1249
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001250 void setInsetsWindow(Session session, IWindow client,
1251 int touchableInsets, Rect contentInsets,
1252 Rect visibleInsets) {
1253 long origId = Binder.clearCallingIdentity();
1254 try {
1255 synchronized (mWindowMap) {
1256 WindowState w = windowForClientLocked(session, client);
1257 if (w != null) {
1258 w.mGivenInsetsPending = false;
1259 w.mGivenContentInsets.set(contentInsets);
1260 w.mGivenVisibleInsets.set(visibleInsets);
1261 w.mTouchableInsets = touchableInsets;
1262 mLayoutNeeded = true;
1263 performLayoutAndPlaceSurfacesLocked();
1264 }
1265 }
1266 } finally {
1267 Binder.restoreCallingIdentity(origId);
1268 }
1269 }
1270
1271 public void getWindowDisplayFrame(Session session, IWindow client,
1272 Rect outDisplayFrame) {
1273 synchronized(mWindowMap) {
1274 WindowState win = windowForClientLocked(session, client);
1275 if (win == null) {
1276 outDisplayFrame.setEmpty();
1277 return;
1278 }
1279 outDisplayFrame.set(win.mDisplayFrame);
1280 }
1281 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001282
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001283 public int relayoutWindow(Session session, IWindow client,
1284 WindowManager.LayoutParams attrs, int requestedWidth,
1285 int requestedHeight, int viewVisibility, boolean insetsPending,
1286 Rect outFrame, Rect outContentInsets, Rect outVisibleInsets,
1287 Surface outSurface) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001288 boolean displayed = false;
1289 boolean inTouchMode;
1290
1291 long origId = Binder.clearCallingIdentity();
1292
1293 synchronized(mWindowMap) {
1294 WindowState win = windowForClientLocked(session, client);
1295 if (win == null) {
1296 return 0;
1297 }
1298 win.mRequestedWidth = requestedWidth;
1299 win.mRequestedHeight = requestedHeight;
1300
1301 if (attrs != null) {
1302 mPolicy.adjustWindowParamsLw(attrs);
1303 }
1304
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001305 int attrChanges = 0;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001306 int flagChanges = 0;
1307 if (attrs != null) {
1308 flagChanges = win.mAttrs.flags ^= attrs.flags;
1309 attrChanges = win.mAttrs.copyFrom(attrs);
1310 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001311
1312 if (localLOGV) Log.v(
1313 TAG, "Relayout given client " + client.asBinder()
1314 + " (" + win.mAttrs.getTitle() + ")");
1315
1316
1317 if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
1318 win.mAlpha = attrs.alpha;
1319 }
1320
1321 final boolean scaledWindow =
1322 ((win.mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0);
1323
1324 if (scaledWindow) {
1325 // requested{Width|Height} Surface's physical size
1326 // attrs.{width|height} Size on screen
1327 win.mHScale = (attrs.width != requestedWidth) ?
1328 (attrs.width / (float)requestedWidth) : 1.0f;
1329 win.mVScale = (attrs.height != requestedHeight) ?
1330 (attrs.height / (float)requestedHeight) : 1.0f;
1331 }
1332
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001333 boolean imMayMove = (flagChanges&(
1334 WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM |
1335 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)) != 0;
1336
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001337 boolean focusMayChange = win.mViewVisibility != viewVisibility
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001338 || ((flagChanges&WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) != 0)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001339 || (!win.mRelayoutCalled);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001340
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001341 win.mRelayoutCalled = true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001342 final int oldVisibility = win.mViewVisibility;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001343 win.mViewVisibility = viewVisibility;
1344 if (viewVisibility == View.VISIBLE &&
1345 (win.mAppToken == null || !win.mAppToken.clientHidden)) {
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001346 displayed = !win.isVisibleLw();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001347 if (win.mExiting) {
1348 win.mExiting = false;
1349 win.mAnimation = null;
1350 }
1351 if (win.mDestroying) {
1352 win.mDestroying = false;
1353 mDestroySurface.remove(win);
1354 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001355 if (oldVisibility == View.GONE) {
1356 win.mEnterAnimationPending = true;
1357 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001358 if (displayed && win.mSurface != null && !win.mDrawPending
1359 && !win.mCommitDrawPending && !mDisplayFrozen) {
1360 applyEnterAnimationLocked(win);
1361 }
1362 try {
1363 Surface surface = win.createSurfaceLocked();
1364 if (surface != null) {
1365 outSurface.copyFrom(surface);
1366 } else {
1367 outSurface.clear();
1368 }
1369 } catch (Exception e) {
1370 Log.w(TAG, "Exception thrown when creating surface for client "
1371 + client + " (" + win.mAttrs.getTitle() + ")",
1372 e);
1373 Binder.restoreCallingIdentity(origId);
1374 return 0;
1375 }
1376 if (displayed) {
1377 focusMayChange = true;
1378 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001379 if (win.mAttrs.type == TYPE_INPUT_METHOD
1380 && mInputMethodWindow == null) {
1381 mInputMethodWindow = win;
1382 imMayMove = true;
1383 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001384 } else {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001385 win.mEnterAnimationPending = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001386 if (win.mSurface != null) {
1387 // If we are not currently running the exit animation, we
1388 // need to see about starting one.
1389 if (!win.mExiting) {
1390 // Try starting an animation; if there isn't one, we
1391 // can destroy the surface right away.
1392 int transit = WindowManagerPolicy.TRANSIT_EXIT;
1393 if (win.getAttrs().type == TYPE_APPLICATION_STARTING) {
1394 transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
1395 }
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08001396 if (win.isVisibleLw() &&
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001397 applyAnimationLocked(win, transit, false)) {
1398 win.mExiting = true;
1399 mKeyWaiter.finishedKey(session, client, true,
1400 KeyWaiter.RETURN_NOTHING);
1401 } else if (win.isAnimating()) {
1402 // Currently in a hide animation... turn this into
1403 // an exit.
1404 win.mExiting = true;
1405 } else {
1406 win.destroySurfaceLocked();
1407 }
1408 }
1409 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001410 if (mInputMethodWindow == win) {
1411 mInputMethodWindow = null;
1412 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001413 outSurface.clear();
1414 }
1415
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001416 boolean assignLayers = false;
1417
1418 if (focusMayChange) {
1419 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
1420 if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
1421 assignLayers = true;
1422 imMayMove = false;
1423 }
1424 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
1425 }
1426
1427 if (imMayMove) {
1428 if (moveInputMethodWindowsIfNeededLocked(false)) {
1429 assignLayers = true;
1430 }
1431 }
1432
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001433 mLayoutNeeded = true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001434 win.mGivenInsetsPending = insetsPending;
1435 if (assignLayers) {
1436 assignLayersLocked();
1437 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001438 performLayoutAndPlaceSurfacesLocked();
1439 if (win.mAppToken != null) {
1440 win.mAppToken.updateReportedVisibilityLocked();
1441 }
1442 outFrame.set(win.mFrame);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001443 outContentInsets.set(win.mContentInsets);
1444 outVisibleInsets.set(win.mVisibleInsets);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001445 if (localLOGV) Log.v(
1446 TAG, "Relayout given client " + client.asBinder()
1447 + ", requestedWidth=" + requestedWidth
1448 + ", requestedHeight=" + requestedHeight
1449 + ", viewVisibility=" + viewVisibility
1450 + "\nRelayout returning frame=" + outFrame
1451 + ", surface=" + outSurface);
1452
1453 if (localLOGV || DEBUG_FOCUS) Log.v(
1454 TAG, "Relayout of " + win + ": focusMayChange=" + focusMayChange);
1455
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001456 inTouchMode = mInTouchMode;
1457 }
1458
1459 Binder.restoreCallingIdentity(origId);
1460
1461 return (inTouchMode ? WindowManagerImpl.RELAYOUT_IN_TOUCH_MODE : 0)
1462 | (displayed ? WindowManagerImpl.RELAYOUT_FIRST_TIME : 0);
1463 }
1464
1465 public void finishDrawingWindow(Session session, IWindow client) {
1466 final long origId = Binder.clearCallingIdentity();
1467 synchronized(mWindowMap) {
1468 WindowState win = windowForClientLocked(session, client);
1469 if (win != null && win.finishDrawingLocked()) {
1470 mLayoutNeeded = true;
1471 performLayoutAndPlaceSurfacesLocked();
1472 }
1473 }
1474 Binder.restoreCallingIdentity(origId);
1475 }
1476
1477 private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
1478 if (DEBUG_ANIM) Log.v(TAG, "Loading animations: params package="
1479 + (lp != null ? lp.packageName : null)
1480 + " resId=0x" + (lp != null ? Integer.toHexString(lp.windowAnimations) : null));
1481 if (lp != null && lp.windowAnimations != 0) {
1482 // If this is a system resource, don't try to load it from the
1483 // application resources. It is nice to avoid loading application
1484 // resources if we can.
1485 String packageName = lp.packageName != null ? lp.packageName : "android";
1486 int resId = lp.windowAnimations;
1487 if ((resId&0xFF000000) == 0x01000000) {
1488 packageName = "android";
1489 }
1490 if (DEBUG_ANIM) Log.v(TAG, "Loading animations: picked package="
1491 + packageName);
1492 return AttributeCache.instance().get(packageName, resId,
1493 com.android.internal.R.styleable.WindowAnimation);
1494 }
1495 return null;
1496 }
1497
1498 private void applyEnterAnimationLocked(WindowState win) {
1499 int transit = WindowManagerPolicy.TRANSIT_SHOW;
1500 if (win.mEnterAnimationPending) {
1501 win.mEnterAnimationPending = false;
1502 transit = WindowManagerPolicy.TRANSIT_ENTER;
1503 }
1504
1505 applyAnimationLocked(win, transit, true);
1506 }
1507
1508 private boolean applyAnimationLocked(WindowState win,
1509 int transit, boolean isEntrance) {
1510 if (win.mAnimating && win.mAnimationIsEntrance == isEntrance) {
1511 // If we are trying to apply an animation, but already running
1512 // an animation of the same type, then just leave that one alone.
1513 return true;
1514 }
1515
1516 // Only apply an animation if the display isn't frozen. If it is
1517 // frozen, there is no reason to animate and it can cause strange
1518 // artifacts when we unfreeze the display if some different animation
1519 // is running.
1520 if (!mDisplayFrozen) {
1521 int anim = mPolicy.selectAnimationLw(win, transit);
1522 int attr = -1;
1523 Animation a = null;
1524 if (anim != 0) {
1525 a = AnimationUtils.loadAnimation(mContext, anim);
1526 } else {
1527 switch (transit) {
1528 case WindowManagerPolicy.TRANSIT_ENTER:
1529 attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
1530 break;
1531 case WindowManagerPolicy.TRANSIT_EXIT:
1532 attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
1533 break;
1534 case WindowManagerPolicy.TRANSIT_SHOW:
1535 attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
1536 break;
1537 case WindowManagerPolicy.TRANSIT_HIDE:
1538 attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
1539 break;
1540 }
1541 if (attr >= 0) {
1542 a = loadAnimation(win.mAttrs, attr);
1543 }
1544 }
1545 if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: win=" + win
1546 + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
1547 + " mAnimation=" + win.mAnimation
1548 + " isEntrance=" + isEntrance);
1549 if (a != null) {
1550 if (DEBUG_ANIM) {
1551 RuntimeException e = new RuntimeException();
1552 e.fillInStackTrace();
1553 Log.v(TAG, "Loaded animation " + a + " for " + win, e);
1554 }
1555 win.setAnimation(a);
1556 }
1557 } else {
1558 win.clearAnimation();
1559 }
1560
1561 return win.mAnimation != null;
1562 }
1563
1564 private Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
1565 int anim = 0;
1566 Context context = mContext;
1567 if (animAttr >= 0) {
1568 AttributeCache.Entry ent = getCachedAnimations(lp);
1569 if (ent != null) {
1570 context = ent.context;
1571 anim = ent.array.getResourceId(animAttr, 0);
1572 }
1573 }
1574 if (anim != 0) {
1575 return AnimationUtils.loadAnimation(context, anim);
1576 }
1577 return null;
1578 }
1579
1580 private boolean applyAnimationLocked(AppWindowToken wtoken,
1581 WindowManager.LayoutParams lp, int transit, boolean enter) {
1582 // Only apply an animation if the display isn't frozen. If it is
1583 // frozen, there is no reason to animate and it can cause strange
1584 // artifacts when we unfreeze the display if some different animation
1585 // is running.
1586 if (!mDisplayFrozen) {
1587 int animAttr = 0;
1588 switch (transit) {
1589 case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN:
1590 animAttr = enter
1591 ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation
1592 : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation;
1593 break;
1594 case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE:
1595 animAttr = enter
1596 ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation
1597 : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
1598 break;
1599 case WindowManagerPolicy.TRANSIT_TASK_OPEN:
1600 animAttr = enter
1601 ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation
1602 : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation;
1603 break;
1604 case WindowManagerPolicy.TRANSIT_TASK_CLOSE:
1605 animAttr = enter
1606 ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation
1607 : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation;
1608 break;
1609 case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT:
1610 animAttr = enter
1611 ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation
1612 : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation;
1613 break;
1614 case WindowManagerPolicy.TRANSIT_TASK_TO_BACK:
1615 animAttr = enter
1616 ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation
1617 : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation;
1618 break;
1619 }
1620 Animation a = loadAnimation(lp, animAttr);
1621 if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: wtoken=" + wtoken
1622 + " anim=" + a
1623 + " animAttr=0x" + Integer.toHexString(animAttr)
1624 + " transit=" + transit);
1625 if (a != null) {
1626 if (DEBUG_ANIM) {
1627 RuntimeException e = new RuntimeException();
1628 e.fillInStackTrace();
1629 Log.v(TAG, "Loaded animation " + a + " for " + wtoken, e);
1630 }
1631 wtoken.setAnimation(a);
1632 }
1633 } else {
1634 wtoken.clearAnimation();
1635 }
1636
1637 return wtoken.animation != null;
1638 }
1639
1640 // -------------------------------------------------------------
1641 // Application Window Tokens
1642 // -------------------------------------------------------------
1643
1644 public void validateAppTokens(List tokens) {
1645 int v = tokens.size()-1;
1646 int m = mAppTokens.size()-1;
1647 while (v >= 0 && m >= 0) {
1648 AppWindowToken wtoken = mAppTokens.get(m);
1649 if (wtoken.removed) {
1650 m--;
1651 continue;
1652 }
1653 if (tokens.get(v) != wtoken.token) {
1654 Log.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
1655 + " @ " + v + ", internal is " + wtoken.token + " @ " + m);
1656 }
1657 v--;
1658 m--;
1659 }
1660 while (v >= 0) {
1661 Log.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
1662 v--;
1663 }
1664 while (m >= 0) {
1665 AppWindowToken wtoken = mAppTokens.get(m);
1666 if (!wtoken.removed) {
1667 Log.w(TAG, "Invalid internal token: " + wtoken.token + " @ " + m);
1668 }
1669 m--;
1670 }
1671 }
1672
1673 boolean checkCallingPermission(String permission, String func) {
1674 // Quick check: if the calling permission is me, it's all okay.
1675 if (Binder.getCallingPid() == Process.myPid()) {
1676 return true;
1677 }
1678
1679 if (mContext.checkCallingPermission(permission)
1680 == PackageManager.PERMISSION_GRANTED) {
1681 return true;
1682 }
1683 String msg = "Permission Denial: " + func + " from pid="
1684 + Binder.getCallingPid()
1685 + ", uid=" + Binder.getCallingUid()
1686 + " requires " + permission;
1687 Log.w(TAG, msg);
1688 return false;
1689 }
1690
1691 AppWindowToken findAppWindowToken(IBinder token) {
1692 WindowToken wtoken = mTokenMap.get(token);
1693 if (wtoken == null) {
1694 return null;
1695 }
1696 return wtoken.appWindowToken;
1697 }
1698
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001699 public void addWindowToken(IBinder token, int type) {
1700 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
1701 "addWindowToken()")) {
1702 return;
1703 }
1704
1705 synchronized(mWindowMap) {
1706 WindowToken wtoken = mTokenMap.get(token);
1707 if (wtoken != null) {
1708 Log.w(TAG, "Attempted to add existing input method token: " + token);
1709 return;
1710 }
1711 wtoken = new WindowToken(token, type);
1712 mTokenMap.put(token, wtoken);
1713 mTokenList.add(wtoken);
1714 }
1715 }
1716
1717 public void removeWindowToken(IBinder token) {
1718 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
1719 "removeWindowToken()")) {
1720 return;
1721 }
1722
1723 final long origId = Binder.clearCallingIdentity();
1724 synchronized(mWindowMap) {
1725 WindowToken wtoken = mTokenMap.remove(token);
1726 mTokenList.remove(wtoken);
1727 if (wtoken != null) {
1728 boolean delayed = false;
1729 if (!wtoken.hidden) {
1730 wtoken.hidden = true;
1731
1732 final int N = wtoken.windows.size();
1733 boolean changed = false;
1734
1735 for (int i=0; i<N; i++) {
1736 WindowState win = wtoken.windows.get(i);
1737
1738 if (win.isAnimating()) {
1739 delayed = true;
1740 }
1741
1742 if (win.isVisibleNow()) {
1743 applyAnimationLocked(win,
1744 WindowManagerPolicy.TRANSIT_EXIT, false);
1745 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
1746 KeyWaiter.RETURN_NOTHING);
1747 changed = true;
1748 }
1749 }
1750
1751 if (changed) {
1752 mLayoutNeeded = true;
1753 performLayoutAndPlaceSurfacesLocked();
1754 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
1755 }
1756
1757 if (delayed) {
1758 mExitingTokens.add(wtoken);
1759 }
1760 }
1761
1762 } else {
1763 Log.w(TAG, "Attempted to remove non-existing token: " + token);
1764 }
1765 }
1766 Binder.restoreCallingIdentity(origId);
1767 }
1768
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001769 public void addAppToken(int addPos, IApplicationToken token,
1770 int groupId, int requestedOrientation, boolean fullscreen) {
1771 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
1772 "addAppToken()")) {
1773 return;
1774 }
1775
1776 synchronized(mWindowMap) {
1777 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
1778 if (wtoken != null) {
1779 Log.w(TAG, "Attempted to add existing app token: " + token);
1780 return;
1781 }
1782 wtoken = new AppWindowToken(token);
1783 wtoken.groupId = groupId;
1784 wtoken.appFullscreen = fullscreen;
1785 wtoken.requestedOrientation = requestedOrientation;
1786 mAppTokens.add(addPos, wtoken);
1787 if (Config.LOGV) Log.v(TAG, "Adding new app token: " + wtoken);
1788 mTokenMap.put(token.asBinder(), wtoken);
1789 mTokenList.add(wtoken);
1790
1791 // Application tokens start out hidden.
1792 wtoken.hidden = true;
1793 wtoken.hiddenRequested = true;
1794
1795 //dump();
1796 }
1797 }
1798
1799 public void setAppGroupId(IBinder token, int groupId) {
1800 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
1801 "setAppStartingIcon()")) {
1802 return;
1803 }
1804
1805 synchronized(mWindowMap) {
1806 AppWindowToken wtoken = findAppWindowToken(token);
1807 if (wtoken == null) {
1808 Log.w(TAG, "Attempted to set group id of non-existing app token: " + token);
1809 return;
1810 }
1811 wtoken.groupId = groupId;
1812 }
1813 }
1814
1815 public Configuration updateOrientationFromAppTokens(
1816 IBinder freezeThisOneIfNeeded) {
1817 boolean changed = false;
1818 synchronized(mWindowMap) {
1819 int pos = mAppTokens.size() - 1;
1820 int req = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
1821 int curGroup = 0;
1822 int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
1823 boolean haveGroup = false;
1824 while (pos >= 0) {
1825 AppWindowToken wtoken = mAppTokens.get(pos);
1826 pos--;
1827 if (!haveGroup) {
1828 // We ignore any hidden applications on the top.
1829 if (wtoken.hiddenRequested || wtoken.willBeHidden) {
1830 continue;
1831 }
1832 haveGroup = true;
1833 curGroup = wtoken.groupId;
1834 lastOrientation = wtoken.requestedOrientation;
1835 } else if (curGroup != wtoken.groupId) {
1836 // If we have hit a new application group, and the bottom
1837 // of the previous group didn't explicitly say to use
1838 // the orientation behind it, then we'll stick with the
1839 // user's orientation.
1840 if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
1841 break;
1842 }
1843 }
1844 int or = wtoken.requestedOrientation;
1845 // If this application has requested an explicit orientation,
1846 // then use it.
1847 if (or == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE ||
1848 or == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ||
1849 or == ActivityInfo.SCREEN_ORIENTATION_SENSOR ||
1850 or == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR ||
1851 or == ActivityInfo.SCREEN_ORIENTATION_USER) {
1852 req = or;
1853 break;
1854 }
1855 }
1856 if (req != mForcedAppOrientation) {
1857 changed = true;
1858 mForcedAppOrientation = req;
1859 //send a message to Policy indicating orientation change to take
1860 //action like disabling/enabling sensors etc.,
1861 mPolicy.setCurrentOrientation(req);
1862 }
1863
1864 if (changed) {
1865 changed = setRotationUncheckedLocked(
1866 WindowManagerPolicy.USE_LAST_ROTATION);
1867 if (changed) {
1868 if (freezeThisOneIfNeeded != null) {
1869 AppWindowToken wtoken = findAppWindowToken(
1870 freezeThisOneIfNeeded);
1871 if (wtoken != null) {
1872 startAppFreezingScreenLocked(wtoken,
1873 ActivityInfo.CONFIG_ORIENTATION);
1874 }
1875 }
1876 Configuration config = computeNewConfigurationLocked();
1877 if (config != null) {
1878 mLayoutNeeded = true;
1879 performLayoutAndPlaceSurfacesLocked();
1880 }
1881 return config;
1882 }
1883 }
1884 }
1885
1886 return null;
1887 }
1888
1889 public void setAppOrientation(IApplicationToken token, int requestedOrientation) {
1890 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
1891 "setAppOrientation()")) {
1892 return;
1893 }
1894
1895 synchronized(mWindowMap) {
1896 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
1897 if (wtoken == null) {
1898 Log.w(TAG, "Attempted to set orientation of non-existing app token: " + token);
1899 return;
1900 }
1901
1902 wtoken.requestedOrientation = requestedOrientation;
1903 }
1904 }
1905
1906 public int getAppOrientation(IApplicationToken token) {
1907 synchronized(mWindowMap) {
1908 AppWindowToken wtoken = findAppWindowToken(token.asBinder());
1909 if (wtoken == null) {
1910 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
1911 }
1912
1913 return wtoken.requestedOrientation;
1914 }
1915 }
1916
1917 public void setFocusedApp(IBinder token, boolean moveFocusNow) {
1918 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
1919 "setFocusedApp()")) {
1920 return;
1921 }
1922
1923 synchronized(mWindowMap) {
1924 boolean changed = false;
1925 if (token == null) {
1926 if (DEBUG_FOCUS) Log.v(TAG, "Clearing focused app, was " + mFocusedApp);
1927 changed = mFocusedApp != null;
1928 mFocusedApp = null;
1929 mKeyWaiter.tickle();
1930 } else {
1931 AppWindowToken newFocus = findAppWindowToken(token);
1932 if (newFocus == null) {
1933 Log.w(TAG, "Attempted to set focus to non-existing app token: " + token);
1934 return;
1935 }
1936 changed = mFocusedApp != newFocus;
1937 mFocusedApp = newFocus;
1938 if (DEBUG_FOCUS) Log.v(TAG, "Set focused app to: " + mFocusedApp);
1939 mKeyWaiter.tickle();
1940 }
1941
1942 if (moveFocusNow && changed) {
1943 final long origId = Binder.clearCallingIdentity();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08001944 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001945 Binder.restoreCallingIdentity(origId);
1946 }
1947 }
1948 }
1949
1950 public void prepareAppTransition(int transit) {
1951 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
1952 "prepareAppTransition()")) {
1953 return;
1954 }
1955
1956 synchronized(mWindowMap) {
1957 if (DEBUG_APP_TRANSITIONS) Log.v(
1958 TAG, "Prepare app transition: transit=" + transit
1959 + " mNextAppTransition=" + mNextAppTransition);
1960 if (!mDisplayFrozen) {
1961 if (mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
1962 mNextAppTransition = transit;
1963 }
1964 mAppTransitionReady = false;
1965 mAppTransitionTimeout = false;
1966 mStartingIconInTransition = false;
1967 mSkipAppTransitionAnimation = false;
1968 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
1969 mH.sendMessageDelayed(mH.obtainMessage(H.APP_TRANSITION_TIMEOUT),
1970 5000);
1971 }
1972 }
1973 }
1974
The Android Open Source Project9266c5582009-01-15 16:12:10 -08001975 public int getPendingAppTransition() {
1976 return mNextAppTransition;
1977 }
1978
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001979 public void executeAppTransition() {
1980 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
1981 "executeAppTransition()")) {
1982 return;
1983 }
1984
1985 synchronized(mWindowMap) {
1986 if (DEBUG_APP_TRANSITIONS) Log.v(
1987 TAG, "Execute app transition: mNextAppTransition=" + mNextAppTransition);
1988 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
1989 mAppTransitionReady = true;
1990 final long origId = Binder.clearCallingIdentity();
1991 performLayoutAndPlaceSurfacesLocked();
1992 Binder.restoreCallingIdentity(origId);
1993 }
1994 }
1995 }
1996
1997 public void setAppStartingWindow(IBinder token, String pkg,
1998 int theme, CharSequence nonLocalizedLabel, int labelRes, int icon,
1999 IBinder transferFrom, boolean createIfNeeded) {
2000 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2001 "setAppStartingIcon()")) {
2002 return;
2003 }
2004
2005 synchronized(mWindowMap) {
2006 if (DEBUG_STARTING_WINDOW) Log.v(
2007 TAG, "setAppStartingIcon: token=" + token + " pkg=" + pkg
2008 + " transferFrom=" + transferFrom);
2009
2010 AppWindowToken wtoken = findAppWindowToken(token);
2011 if (wtoken == null) {
2012 Log.w(TAG, "Attempted to set icon of non-existing app token: " + token);
2013 return;
2014 }
2015
2016 // If the display is frozen, we won't do anything until the
2017 // actual window is displayed so there is no reason to put in
2018 // the starting window.
2019 if (mDisplayFrozen) {
2020 return;
2021 }
2022
2023 if (wtoken.startingData != null) {
2024 return;
2025 }
2026
2027 if (transferFrom != null) {
2028 AppWindowToken ttoken = findAppWindowToken(transferFrom);
2029 if (ttoken != null) {
2030 WindowState startingWindow = ttoken.startingWindow;
2031 if (startingWindow != null) {
2032 if (mStartingIconInTransition) {
2033 // In this case, the starting icon has already
2034 // been displayed, so start letting windows get
2035 // shown immediately without any more transitions.
2036 mSkipAppTransitionAnimation = true;
2037 }
2038 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
2039 "Moving existing starting from " + ttoken
2040 + " to " + wtoken);
2041 final long origId = Binder.clearCallingIdentity();
2042
2043 // Transfer the starting window over to the new
2044 // token.
2045 wtoken.startingData = ttoken.startingData;
2046 wtoken.startingView = ttoken.startingView;
2047 wtoken.startingWindow = startingWindow;
2048 ttoken.startingData = null;
2049 ttoken.startingView = null;
2050 ttoken.startingWindow = null;
2051 ttoken.startingMoved = true;
2052 startingWindow.mToken = wtoken;
2053 startingWindow.mAppToken = wtoken;
2054 mWindows.remove(startingWindow);
2055 ttoken.windows.remove(startingWindow);
2056 ttoken.allAppWindows.remove(startingWindow);
The Android Open Source Project9266c5582009-01-15 16:12:10 -08002057 addWindowToListInOrderLocked(startingWindow, true);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002058 wtoken.allAppWindows.add(startingWindow);
2059
2060 // Propagate other interesting state between the
2061 // tokens. If the old token is displayed, we should
2062 // immediately force the new one to be displayed. If
2063 // it is animating, we need to move that animation to
2064 // the new one.
2065 if (ttoken.allDrawn) {
2066 wtoken.allDrawn = true;
2067 }
2068 if (ttoken.firstWindowDrawn) {
2069 wtoken.firstWindowDrawn = true;
2070 }
2071 if (!ttoken.hidden) {
2072 wtoken.hidden = false;
2073 wtoken.hiddenRequested = false;
2074 wtoken.willBeHidden = false;
2075 }
2076 if (wtoken.clientHidden != ttoken.clientHidden) {
2077 wtoken.clientHidden = ttoken.clientHidden;
2078 wtoken.sendAppVisibilityToClients();
2079 }
2080 if (ttoken.animation != null) {
2081 wtoken.animation = ttoken.animation;
2082 wtoken.animating = ttoken.animating;
2083 wtoken.animLayerAdjustment = ttoken.animLayerAdjustment;
2084 ttoken.animation = null;
2085 ttoken.animLayerAdjustment = 0;
2086 wtoken.updateLayers();
2087 ttoken.updateLayers();
2088 }
2089
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002090 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002091 assignLayersLocked();
2092 mLayoutNeeded = true;
2093 performLayoutAndPlaceSurfacesLocked();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002094 Binder.restoreCallingIdentity(origId);
2095 return;
2096 } else if (ttoken.startingData != null) {
2097 // The previous app was getting ready to show a
2098 // starting window, but hasn't yet done so. Steal it!
2099 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
2100 "Moving pending starting from " + ttoken
2101 + " to " + wtoken);
2102 wtoken.startingData = ttoken.startingData;
2103 ttoken.startingData = null;
2104 ttoken.startingMoved = true;
2105 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
2106 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2107 // want to process the message ASAP, before any other queued
2108 // messages.
2109 mH.sendMessageAtFrontOfQueue(m);
2110 return;
2111 }
2112 }
2113 }
2114
2115 // There is no existing starting window, and the caller doesn't
2116 // want us to create one, so that's it!
2117 if (!createIfNeeded) {
2118 return;
2119 }
2120
2121 mStartingIconInTransition = true;
2122 wtoken.startingData = new StartingData(
2123 pkg, theme, nonLocalizedLabel,
2124 labelRes, icon);
2125 Message m = mH.obtainMessage(H.ADD_STARTING, wtoken);
2126 // Note: we really want to do sendMessageAtFrontOfQueue() because we
2127 // want to process the message ASAP, before any other queued
2128 // messages.
2129 mH.sendMessageAtFrontOfQueue(m);
2130 }
2131 }
2132
2133 public void setAppWillBeHidden(IBinder token) {
2134 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2135 "setAppWillBeHidden()")) {
2136 return;
2137 }
2138
2139 AppWindowToken wtoken;
2140
2141 synchronized(mWindowMap) {
2142 wtoken = findAppWindowToken(token);
2143 if (wtoken == null) {
2144 Log.w(TAG, "Attempted to set will be hidden of non-existing app token: " + token);
2145 return;
2146 }
2147 wtoken.willBeHidden = true;
2148 }
2149 }
2150
2151 boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
2152 boolean visible, int transit, boolean performLayout) {
2153 boolean delayed = false;
2154
2155 if (wtoken.clientHidden == visible) {
2156 wtoken.clientHidden = !visible;
2157 wtoken.sendAppVisibilityToClients();
2158 }
2159
2160 wtoken.willBeHidden = false;
2161 if (wtoken.hidden == visible) {
2162 final int N = wtoken.allAppWindows.size();
2163 boolean changed = false;
2164 if (DEBUG_APP_TRANSITIONS) Log.v(
2165 TAG, "Changing app " + wtoken + " hidden=" + wtoken.hidden
2166 + " performLayout=" + performLayout);
2167
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002168 boolean runningAppAnimation = false;
2169
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002170 if (transit != WindowManagerPolicy.TRANSIT_NONE) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002171 if (wtoken.animation == sDummyAnimation) {
2172 wtoken.animation = null;
2173 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002174 applyAnimationLocked(wtoken, lp, transit, visible);
2175 changed = true;
2176 if (wtoken.animation != null) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002177 delayed = runningAppAnimation = true;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002178 }
2179 }
2180
2181 for (int i=0; i<N; i++) {
2182 WindowState win = wtoken.allAppWindows.get(i);
2183 if (win == wtoken.startingWindow) {
2184 continue;
2185 }
2186
2187 if (win.isAnimating()) {
2188 delayed = true;
2189 }
2190
2191 //Log.i(TAG, "Window " + win + ": vis=" + win.isVisible());
2192 //win.dump(" ");
2193 if (visible) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002194 if (!win.isVisibleNow()) {
2195 if (!runningAppAnimation) {
2196 applyAnimationLocked(win,
2197 WindowManagerPolicy.TRANSIT_ENTER, true);
2198 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002199 changed = true;
2200 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002201 } else if (win.isVisibleNow()) {
2202 if (!runningAppAnimation) {
2203 applyAnimationLocked(win,
2204 WindowManagerPolicy.TRANSIT_EXIT, false);
2205 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002206 mKeyWaiter.finishedKey(win.mSession, win.mClient, true,
2207 KeyWaiter.RETURN_NOTHING);
2208 changed = true;
2209 }
2210 }
2211
2212 wtoken.hidden = wtoken.hiddenRequested = !visible;
2213 if (!visible) {
2214 unsetAppFreezingScreenLocked(wtoken, true, true);
2215 } else {
2216 // If we are being set visible, and the starting window is
2217 // not yet displayed, then make sure it doesn't get displayed.
2218 WindowState swin = wtoken.startingWindow;
2219 if (swin != null && (swin.mDrawPending
2220 || swin.mCommitDrawPending)) {
2221 swin.mPolicyVisibility = false;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08002222 swin.mPolicyVisibilityAfterAnim = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002223 }
2224 }
2225
2226 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "setTokenVisibilityLocked: " + wtoken
2227 + ": hidden=" + wtoken.hidden + " hiddenRequested="
2228 + wtoken.hiddenRequested);
2229
2230 if (changed && performLayout) {
2231 mLayoutNeeded = true;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002232 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
2233 assignLayersLocked();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002234 performLayoutAndPlaceSurfacesLocked();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002235 }
2236 }
2237
2238 if (wtoken.animation != null) {
2239 delayed = true;
2240 }
2241
2242 return delayed;
2243 }
2244
2245 public void setAppVisibility(IBinder token, boolean visible) {
2246 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2247 "setAppVisibility()")) {
2248 return;
2249 }
2250
2251 AppWindowToken wtoken;
2252
2253 synchronized(mWindowMap) {
2254 wtoken = findAppWindowToken(token);
2255 if (wtoken == null) {
2256 Log.w(TAG, "Attempted to set visibility of non-existing app token: " + token);
2257 return;
2258 }
2259
2260 if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) {
2261 RuntimeException e = new RuntimeException();
2262 e.fillInStackTrace();
2263 Log.v(TAG, "setAppVisibility(" + token + ", " + visible
2264 + "): mNextAppTransition=" + mNextAppTransition
2265 + " hidden=" + wtoken.hidden
2266 + " hiddenRequested=" + wtoken.hiddenRequested, e);
2267 }
2268
2269 // If we are preparing an app transition, then delay changing
2270 // the visibility of this token until we execute that transition.
2271 if (!mDisplayFrozen && mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
2272 // Already in requested state, don't do anything more.
2273 if (wtoken.hiddenRequested != visible) {
2274 return;
2275 }
2276 wtoken.hiddenRequested = !visible;
2277
2278 if (DEBUG_APP_TRANSITIONS) Log.v(
2279 TAG, "Setting dummy animation on: " + wtoken);
2280 wtoken.setDummyAnimation();
2281 mOpeningApps.remove(wtoken);
2282 mClosingApps.remove(wtoken);
2283 wtoken.inPendingTransaction = true;
2284 if (visible) {
2285 mOpeningApps.add(wtoken);
2286 wtoken.allDrawn = false;
2287 wtoken.startingDisplayed = false;
2288 wtoken.startingMoved = false;
2289
2290 if (wtoken.clientHidden) {
2291 // In the case where we are making an app visible
2292 // but holding off for a transition, we still need
2293 // to tell the client to make its windows visible so
2294 // they get drawn. Otherwise, we will wait on
2295 // performing the transition until all windows have
2296 // been drawn, they never will be, and we are sad.
2297 wtoken.clientHidden = false;
2298 wtoken.sendAppVisibilityToClients();
2299 }
2300 } else {
2301 mClosingApps.add(wtoken);
2302 }
2303 return;
2304 }
2305
2306 final long origId = Binder.clearCallingIdentity();
2307 setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_NONE, true);
2308 wtoken.updateReportedVisibilityLocked();
2309 Binder.restoreCallingIdentity(origId);
2310 }
2311 }
2312
2313 void unsetAppFreezingScreenLocked(AppWindowToken wtoken,
2314 boolean unfreezeSurfaceNow, boolean force) {
2315 if (wtoken.freezingScreen) {
2316 if (DEBUG_ORIENTATION) Log.v(TAG, "Clear freezing of " + wtoken
2317 + " force=" + force);
2318 final int N = wtoken.allAppWindows.size();
2319 boolean unfrozeWindows = false;
2320 for (int i=0; i<N; i++) {
2321 WindowState w = wtoken.allAppWindows.get(i);
2322 if (w.mAppFreezing) {
2323 w.mAppFreezing = false;
2324 if (w.mSurface != null && !w.mOrientationChanging) {
2325 w.mOrientationChanging = true;
2326 }
2327 unfrozeWindows = true;
2328 }
2329 }
2330 if (force || unfrozeWindows) {
2331 if (DEBUG_ORIENTATION) Log.v(TAG, "No longer freezing: " + wtoken);
2332 wtoken.freezingScreen = false;
2333 mAppsFreezingScreen--;
2334 }
2335 if (unfreezeSurfaceNow) {
2336 if (unfrozeWindows) {
2337 mLayoutNeeded = true;
2338 performLayoutAndPlaceSurfacesLocked();
2339 }
2340 if (mAppsFreezingScreen == 0 && !mWindowsFreezingScreen) {
2341 stopFreezingDisplayLocked();
2342 }
2343 }
2344 }
2345 }
2346
2347 public void startAppFreezingScreenLocked(AppWindowToken wtoken,
2348 int configChanges) {
2349 if (DEBUG_ORIENTATION) {
2350 RuntimeException e = new RuntimeException();
2351 e.fillInStackTrace();
2352 Log.i(TAG, "Set freezing of " + wtoken.appToken
2353 + ": hidden=" + wtoken.hidden + " freezing="
2354 + wtoken.freezingScreen, e);
2355 }
2356 if (!wtoken.hiddenRequested) {
2357 if (!wtoken.freezingScreen) {
2358 wtoken.freezingScreen = true;
2359 mAppsFreezingScreen++;
2360 if (mAppsFreezingScreen == 1) {
2361 startFreezingDisplayLocked();
2362 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
2363 mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
2364 5000);
2365 }
2366 }
2367 final int N = wtoken.allAppWindows.size();
2368 for (int i=0; i<N; i++) {
2369 WindowState w = wtoken.allAppWindows.get(i);
2370 w.mAppFreezing = true;
2371 }
2372 }
2373 }
2374
2375 public void startAppFreezingScreen(IBinder token, int configChanges) {
2376 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2377 "setAppFreezingScreen()")) {
2378 return;
2379 }
2380
2381 synchronized(mWindowMap) {
2382 if (configChanges == 0 && !mDisplayFrozen) {
2383 if (DEBUG_ORIENTATION) Log.v(TAG, "Skipping set freeze of " + token);
2384 return;
2385 }
2386
2387 AppWindowToken wtoken = findAppWindowToken(token);
2388 if (wtoken == null || wtoken.appToken == null) {
2389 Log.w(TAG, "Attempted to freeze screen with non-existing app token: " + wtoken);
2390 return;
2391 }
2392 final long origId = Binder.clearCallingIdentity();
2393 startAppFreezingScreenLocked(wtoken, configChanges);
2394 Binder.restoreCallingIdentity(origId);
2395 }
2396 }
2397
2398 public void stopAppFreezingScreen(IBinder token, boolean force) {
2399 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2400 "setAppFreezingScreen()")) {
2401 return;
2402 }
2403
2404 synchronized(mWindowMap) {
2405 AppWindowToken wtoken = findAppWindowToken(token);
2406 if (wtoken == null || wtoken.appToken == null) {
2407 return;
2408 }
2409 final long origId = Binder.clearCallingIdentity();
2410 if (DEBUG_ORIENTATION) Log.v(TAG, "Clear freezing of " + token
2411 + ": hidden=" + wtoken.hidden + " freezing=" + wtoken.freezingScreen);
2412 unsetAppFreezingScreenLocked(wtoken, true, force);
2413 Binder.restoreCallingIdentity(origId);
2414 }
2415 }
2416
2417 public void removeAppToken(IBinder token) {
2418 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2419 "removeAppToken()")) {
2420 return;
2421 }
2422
2423 AppWindowToken wtoken = null;
2424 AppWindowToken startingToken = null;
2425 boolean delayed = false;
2426
2427 final long origId = Binder.clearCallingIdentity();
2428 synchronized(mWindowMap) {
2429 WindowToken basewtoken = mTokenMap.remove(token);
2430 mTokenList.remove(basewtoken);
2431 if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
2432 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "Removing app token: " + wtoken);
2433 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_NONE, true);
2434 wtoken.inPendingTransaction = false;
2435 mOpeningApps.remove(wtoken);
2436 if (mClosingApps.contains(wtoken)) {
2437 delayed = true;
2438 } else if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
2439 mClosingApps.add(wtoken);
2440 delayed = true;
2441 }
2442 if (DEBUG_APP_TRANSITIONS) Log.v(
2443 TAG, "Removing app " + wtoken + " delayed=" + delayed
2444 + " animation=" + wtoken.animation
2445 + " animating=" + wtoken.animating);
2446 if (delayed) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002447 // set the token aside because it has an active animation to be finished
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002448 mExitingAppTokens.add(wtoken);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002449 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002450 mAppTokens.remove(wtoken);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002451 wtoken.removed = true;
2452 if (wtoken.startingData != null) {
2453 startingToken = wtoken;
2454 }
2455 unsetAppFreezingScreenLocked(wtoken, true, true);
2456 if (mFocusedApp == wtoken) {
2457 if (DEBUG_FOCUS) Log.v(TAG, "Removing focused app token:" + wtoken);
2458 mFocusedApp = null;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002459 updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002460 mKeyWaiter.tickle();
2461 }
2462 } else {
2463 Log.w(TAG, "Attempted to remove non-existing app token: " + token);
2464 }
2465
2466 if (!delayed && wtoken != null) {
2467 wtoken.updateReportedVisibilityLocked();
2468 }
2469 }
2470 Binder.restoreCallingIdentity(origId);
2471
2472 if (startingToken != null) {
2473 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Schedule remove starting "
2474 + startingToken + ": app token removed");
2475 Message m = mH.obtainMessage(H.REMOVE_STARTING, startingToken);
2476 mH.sendMessage(m);
2477 }
2478 }
2479
2480 private boolean tmpRemoveAppWindowsLocked(WindowToken token) {
2481 final int NW = token.windows.size();
2482 for (int i=0; i<NW; i++) {
2483 WindowState win = token.windows.get(i);
2484 mWindows.remove(win);
2485 int j = win.mChildWindows.size();
2486 while (j > 0) {
2487 j--;
2488 mWindows.remove(win.mChildWindows.get(j));
2489 }
2490 }
2491 return NW > 0;
2492 }
2493
2494 void dumpAppTokensLocked() {
2495 for (int i=mAppTokens.size()-1; i>=0; i--) {
2496 Log.v(TAG, " #" + i + ": " + mAppTokens.get(i).token);
2497 }
2498 }
2499
2500 void dumpWindowsLocked() {
2501 for (int i=mWindows.size()-1; i>=0; i--) {
2502 Log.v(TAG, " #" + i + ": " + mWindows.get(i));
2503 }
2504 }
2505
2506 private int findWindowOffsetLocked(int tokenPos) {
2507 final int NW = mWindows.size();
2508
2509 if (tokenPos >= mAppTokens.size()) {
2510 int i = NW;
2511 while (i > 0) {
2512 i--;
2513 WindowState win = (WindowState)mWindows.get(i);
2514 if (win.getAppToken() != null) {
2515 return i+1;
2516 }
2517 }
2518 }
2519
2520 while (tokenPos > 0) {
2521 // Find the first app token below the new position that has
2522 // a window displayed.
2523 final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
2524 if (DEBUG_REORDER) Log.v(TAG, "Looking for lower windows @ "
2525 + tokenPos + " -- " + wtoken.token);
2526 int i = wtoken.windows.size();
2527 while (i > 0) {
2528 i--;
2529 WindowState win = wtoken.windows.get(i);
2530 int j = win.mChildWindows.size();
2531 while (j > 0) {
2532 j--;
2533 WindowState cwin = (WindowState)win.mChildWindows.get(j);
2534 if (cwin.mSubLayer >= 0 ) {
2535 for (int pos=NW-1; pos>=0; pos--) {
2536 if (mWindows.get(pos) == cwin) {
2537 if (DEBUG_REORDER) Log.v(TAG,
2538 "Found child win @" + (pos+1));
2539 return pos+1;
2540 }
2541 }
2542 }
2543 }
2544 for (int pos=NW-1; pos>=0; pos--) {
2545 if (mWindows.get(pos) == win) {
2546 if (DEBUG_REORDER) Log.v(TAG, "Found win @" + (pos+1));
2547 return pos+1;
2548 }
2549 }
2550 }
2551 tokenPos--;
2552 }
2553
2554 return 0;
2555 }
2556
The Android Open Source Project9266c5582009-01-15 16:12:10 -08002557 private final int reAddWindowLocked(int index, WindowState win) {
2558 final int NCW = win.mChildWindows.size();
2559 boolean added = false;
2560 for (int j=0; j<NCW; j++) {
2561 WindowState cwin = (WindowState)win.mChildWindows.get(j);
2562 if (cwin.mSubLayer >= 0) {
2563 mWindows.add(index, win);
2564 index++;
2565 added = true;
2566 }
2567 mWindows.add(index, cwin);
2568 index++;
2569 }
2570 if (!added) {
2571 mWindows.add(index, win);
2572 index++;
2573 }
2574 return index;
2575 }
2576
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002577 private final int reAddAppWindowsLocked(int index, WindowToken token) {
2578 final int NW = token.windows.size();
2579 for (int i=0; i<NW; i++) {
The Android Open Source Project9266c5582009-01-15 16:12:10 -08002580 index = reAddWindowLocked(index, token.windows.get(i));
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002581 }
2582 return index;
2583 }
2584
2585 public void moveAppToken(int index, IBinder token) {
2586 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2587 "moveAppToken()")) {
2588 return;
2589 }
2590
2591 synchronized(mWindowMap) {
2592 if (DEBUG_REORDER) Log.v(TAG, "Initial app tokens:");
2593 if (DEBUG_REORDER) dumpAppTokensLocked();
2594 final AppWindowToken wtoken = findAppWindowToken(token);
2595 if (wtoken == null || !mAppTokens.remove(wtoken)) {
2596 Log.w(TAG, "Attempting to reorder token that doesn't exist: "
2597 + token + " (" + wtoken + ")");
2598 return;
2599 }
2600 mAppTokens.add(index, wtoken);
2601 if (DEBUG_REORDER) Log.v(TAG, "Moved " + token + " to " + index + ":");
2602 if (DEBUG_REORDER) dumpAppTokensLocked();
2603
2604 final long origId = Binder.clearCallingIdentity();
2605 if (DEBUG_REORDER) Log.v(TAG, "Removing windows in " + token + ":");
2606 if (DEBUG_REORDER) dumpWindowsLocked();
2607 if (tmpRemoveAppWindowsLocked(wtoken)) {
2608 if (DEBUG_REORDER) Log.v(TAG, "Adding windows back in:");
2609 if (DEBUG_REORDER) dumpWindowsLocked();
2610 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
2611 if (DEBUG_REORDER) Log.v(TAG, "Final window list:");
2612 if (DEBUG_REORDER) dumpWindowsLocked();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002613 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002614 assignLayersLocked();
2615 mLayoutNeeded = true;
2616 performLayoutAndPlaceSurfacesLocked();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002617 }
2618 Binder.restoreCallingIdentity(origId);
2619 }
2620 }
2621
2622 private void removeAppTokensLocked(List<IBinder> tokens) {
2623 // XXX This should be done more efficiently!
2624 // (take advantage of the fact that both lists should be
2625 // ordered in the same way.)
2626 int N = tokens.size();
2627 for (int i=0; i<N; i++) {
2628 IBinder token = tokens.get(i);
2629 final AppWindowToken wtoken = findAppWindowToken(token);
2630 if (!mAppTokens.remove(wtoken)) {
2631 Log.w(TAG, "Attempting to reorder token that doesn't exist: "
2632 + token + " (" + wtoken + ")");
2633 i--;
2634 N--;
2635 }
2636 }
2637 }
2638
2639 private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
2640 // First remove all of the windows from the list.
2641 final int N = tokens.size();
2642 int i;
2643 for (i=0; i<N; i++) {
2644 WindowToken token = mTokenMap.get(tokens.get(i));
2645 if (token != null) {
2646 tmpRemoveAppWindowsLocked(token);
2647 }
2648 }
2649
2650 // Where to start adding?
2651 int pos = findWindowOffsetLocked(tokenPos);
2652
2653 // And now add them back at the correct place.
2654 for (i=0; i<N; i++) {
2655 WindowToken token = mTokenMap.get(tokens.get(i));
2656 if (token != null) {
2657 pos = reAddAppWindowsLocked(pos, token);
2658 }
2659 }
2660
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08002661 updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002662 assignLayersLocked();
2663 mLayoutNeeded = true;
2664 performLayoutAndPlaceSurfacesLocked();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002665
2666 //dump();
2667 }
2668
2669 public void moveAppTokensToTop(List<IBinder> tokens) {
2670 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2671 "moveAppTokensToTop()")) {
2672 return;
2673 }
2674
2675 final long origId = Binder.clearCallingIdentity();
2676 synchronized(mWindowMap) {
2677 removeAppTokensLocked(tokens);
2678 final int N = tokens.size();
2679 for (int i=0; i<N; i++) {
2680 AppWindowToken wt = findAppWindowToken(tokens.get(i));
2681 if (wt != null) {
2682 mAppTokens.add(wt);
2683 }
2684 }
2685 moveAppWindowsLocked(tokens, mAppTokens.size());
2686 }
2687 Binder.restoreCallingIdentity(origId);
2688 }
2689
2690 public void moveAppTokensToBottom(List<IBinder> tokens) {
2691 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
2692 "moveAppTokensToBottom()")) {
2693 return;
2694 }
2695
2696 final long origId = Binder.clearCallingIdentity();
2697 synchronized(mWindowMap) {
2698 removeAppTokensLocked(tokens);
2699 final int N = tokens.size();
2700 int pos = 0;
2701 for (int i=0; i<N; i++) {
2702 AppWindowToken wt = findAppWindowToken(tokens.get(i));
2703 if (wt != null) {
2704 mAppTokens.add(pos, wt);
2705 pos++;
2706 }
2707 }
2708 moveAppWindowsLocked(tokens, 0);
2709 }
2710 Binder.restoreCallingIdentity(origId);
2711 }
2712
2713 // -------------------------------------------------------------
2714 // Misc IWindowSession methods
2715 // -------------------------------------------------------------
2716
2717 public void disableKeyguard(IBinder token, String tag) {
2718 if (mContext.checkCallingPermission(android.Manifest.permission.DISABLE_KEYGUARD)
2719 != PackageManager.PERMISSION_GRANTED) {
2720 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
2721 }
2722 mKeyguardDisabled.acquire(token, tag);
2723 }
2724
2725 public void reenableKeyguard(IBinder token) {
2726 if (mContext.checkCallingPermission(android.Manifest.permission.DISABLE_KEYGUARD)
2727 != PackageManager.PERMISSION_GRANTED) {
2728 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
2729 }
2730 synchronized (mKeyguardDisabled) {
2731 mKeyguardDisabled.release(token);
2732
2733 if (!mKeyguardDisabled.isAcquired()) {
2734 // if we are the last one to reenable the keyguard wait until
2735 // we have actaully finished reenabling until returning
2736 mWaitingUntilKeyguardReenabled = true;
2737 while (mWaitingUntilKeyguardReenabled) {
2738 try {
2739 mKeyguardDisabled.wait();
2740 } catch (InterruptedException e) {
2741 Thread.currentThread().interrupt();
2742 }
2743 }
2744 }
2745 }
2746 }
2747
2748 /**
2749 * @see android.app.KeyguardManager#exitKeyguardSecurely
2750 */
2751 public void exitKeyguardSecurely(final IOnKeyguardExitResult callback) {
2752 if (mContext.checkCallingPermission(android.Manifest.permission.DISABLE_KEYGUARD)
2753 != PackageManager.PERMISSION_GRANTED) {
2754 throw new SecurityException("Requires DISABLE_KEYGUARD permission");
2755 }
2756 mPolicy.exitKeyguardSecurely(new WindowManagerPolicy.OnKeyguardExitResult() {
2757 public void onKeyguardExitResult(boolean success) {
2758 try {
2759 callback.onKeyguardExitResult(success);
2760 } catch (RemoteException e) {
2761 // Client has died, we don't care.
2762 }
2763 }
2764 });
2765 }
2766
2767 public boolean inKeyguardRestrictedInputMode() {
2768 return mPolicy.inKeyguardRestrictedKeyInputMode();
2769 }
2770
2771 static float fixScale(float scale) {
2772 if (scale < 0) scale = 0;
2773 else if (scale > 20) scale = 20;
2774 return Math.abs(scale);
2775 }
2776
2777 public void setAnimationScale(int which, float scale) {
2778 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
2779 "setAnimationScale()")) {
2780 return;
2781 }
2782
2783 if (scale < 0) scale = 0;
2784 else if (scale > 20) scale = 20;
2785 scale = Math.abs(scale);
2786 switch (which) {
2787 case 0: mWindowAnimationScale = fixScale(scale); break;
2788 case 1: mTransitionAnimationScale = fixScale(scale); break;
2789 }
2790
2791 // Persist setting
2792 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
2793 }
2794
2795 public void setAnimationScales(float[] scales) {
2796 if (!checkCallingPermission(android.Manifest.permission.SET_ANIMATION_SCALE,
2797 "setAnimationScale()")) {
2798 return;
2799 }
2800
2801 if (scales != null) {
2802 if (scales.length >= 1) {
2803 mWindowAnimationScale = fixScale(scales[0]);
2804 }
2805 if (scales.length >= 2) {
2806 mTransitionAnimationScale = fixScale(scales[1]);
2807 }
2808 }
2809
2810 // Persist setting
2811 mH.obtainMessage(H.PERSIST_ANIMATION_SCALE).sendToTarget();
2812 }
2813
2814 public float getAnimationScale(int which) {
2815 switch (which) {
2816 case 0: return mWindowAnimationScale;
2817 case 1: return mTransitionAnimationScale;
2818 }
2819 return 0;
2820 }
2821
2822 public float[] getAnimationScales() {
2823 return new float[] { mWindowAnimationScale, mTransitionAnimationScale };
2824 }
2825
2826 public int getSwitchState(int sw) {
2827 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
2828 "getSwitchState()")) {
2829 return -1;
2830 }
2831 return KeyInputQueue.getSwitchState(sw);
2832 }
2833
2834 public int getSwitchStateForDevice(int devid, int sw) {
2835 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
2836 "getSwitchStateForDevice()")) {
2837 return -1;
2838 }
2839 return KeyInputQueue.getSwitchState(devid, sw);
2840 }
2841
2842 public int getScancodeState(int sw) {
2843 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
2844 "getScancodeState()")) {
2845 return -1;
2846 }
2847 return KeyInputQueue.getScancodeState(sw);
2848 }
2849
2850 public int getScancodeStateForDevice(int devid, int sw) {
2851 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
2852 "getScancodeStateForDevice()")) {
2853 return -1;
2854 }
2855 return KeyInputQueue.getScancodeState(devid, sw);
2856 }
2857
2858 public int getKeycodeState(int sw) {
2859 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
2860 "getKeycodeState()")) {
2861 return -1;
2862 }
2863 return KeyInputQueue.getKeycodeState(sw);
2864 }
2865
2866 public int getKeycodeStateForDevice(int devid, int sw) {
2867 if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
2868 "getKeycodeStateForDevice()")) {
2869 return -1;
2870 }
2871 return KeyInputQueue.getKeycodeState(devid, sw);
2872 }
2873
2874 public void enableScreenAfterBoot() {
2875 synchronized(mWindowMap) {
2876 if (mSystemBooted) {
2877 return;
2878 }
2879 mSystemBooted = true;
2880 }
2881
2882 performEnableScreen();
2883 }
2884
2885 public void enableScreenIfNeededLocked() {
2886 if (mDisplayEnabled) {
2887 return;
2888 }
2889 if (!mSystemBooted) {
2890 return;
2891 }
2892 mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN));
2893 }
2894
2895 public void performEnableScreen() {
2896 synchronized(mWindowMap) {
2897 if (mDisplayEnabled) {
2898 return;
2899 }
2900 if (!mSystemBooted) {
2901 return;
2902 }
2903
2904 // Don't enable the screen until all existing windows
2905 // have been drawn.
2906 final int N = mWindows.size();
2907 for (int i=0; i<N; i++) {
2908 WindowState w = (WindowState)mWindows.get(i);
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08002909 if (w.isVisibleLw() && !w.isDisplayedLw()) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07002910 return;
2911 }
2912 }
2913
2914 mDisplayEnabled = true;
2915 if (false) {
2916 Log.i(TAG, "ENABLING SCREEN!");
2917 StringWriter sw = new StringWriter();
2918 PrintWriter pw = new PrintWriter(sw);
2919 this.dump(null, pw, null);
2920 Log.i(TAG, sw.toString());
2921 }
2922 try {
2923 IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
2924 if (surfaceFlinger != null) {
2925 //Log.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
2926 Parcel data = Parcel.obtain();
2927 data.writeInterfaceToken("android.ui.ISurfaceComposer");
2928 surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION,
2929 data, null, 0);
2930 data.recycle();
2931 }
2932 } catch (RemoteException ex) {
2933 Log.e(TAG, "Boot completed: SurfaceFlinger is dead!");
2934 }
2935 }
2936
2937 mPolicy.enableScreenAfterBoot();
2938
2939 // Make sure the last requested orientation has been applied.
2940 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false);
2941 }
2942
2943 public void setInTouchMode(boolean mode) {
2944 synchronized(mWindowMap) {
2945 mInTouchMode = mode;
2946 }
2947 }
2948
2949 public void setRotation(int rotation,
2950 boolean alwaysSendConfiguration) {
2951 if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
2952 "setOrientation()")) {
2953 return;
2954 }
2955
2956 setRotationUnchecked(rotation, alwaysSendConfiguration);
2957 }
2958
2959 public void setRotationUnchecked(int rotation, boolean alwaysSendConfiguration) {
2960 if(DEBUG_ORIENTATION) Log.v(TAG,
2961 "alwaysSendConfiguration set to "+alwaysSendConfiguration);
2962
2963 long origId = Binder.clearCallingIdentity();
2964 boolean changed;
2965 synchronized(mWindowMap) {
2966 changed = setRotationUncheckedLocked(rotation);
2967 }
2968
2969 if (changed) {
2970 sendNewConfiguration();
2971 synchronized(mWindowMap) {
2972 mLayoutNeeded = true;
2973 performLayoutAndPlaceSurfacesLocked();
2974 }
2975 } else if (alwaysSendConfiguration) {
2976 //update configuration ignoring orientation change
2977 sendNewConfiguration();
2978 }
2979
2980 Binder.restoreCallingIdentity(origId);
2981 }
2982
2983 public boolean setRotationUncheckedLocked(int rotation) {
2984 boolean changed;
2985 if (rotation == WindowManagerPolicy.USE_LAST_ROTATION) {
2986 rotation = mRequestedRotation;
2987 } else {
2988 mRequestedRotation = rotation;
2989 }
2990 if (DEBUG_ORIENTATION) Log.v(TAG, "Overwriting rotation value from "+rotation);
2991 rotation = mPolicy.rotationForOrientation(mForcedAppOrientation);
2992 if (DEBUG_ORIENTATION) Log.v(TAG, "new rotation is set to "+rotation);
2993 changed = mDisplayEnabled && mRotation != rotation;
2994
2995 if (changed) {
2996 mRotation = rotation;
2997 if (DEBUG_ORIENTATION) Log.v(TAG,
2998 "Rotation changed to " + rotation
2999 + " from " + mRotation
3000 + " (forceApp=" + mForcedAppOrientation
3001 + ", req=" + mRequestedRotation + ")");
3002 mWindowsFreezingScreen = true;
3003 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
3004 mH.sendMessageDelayed(mH.obtainMessage(H.WINDOW_FREEZE_TIMEOUT),
3005 2000);
3006 startFreezingDisplayLocked();
3007 mQueue.setOrientation(rotation);
3008 if (mDisplayEnabled) {
3009 Surface.setOrientation(0, rotation);
3010 }
3011 for (int i=mWindows.size()-1; i>=0; i--) {
3012 WindowState w = (WindowState)mWindows.get(i);
3013 if (w.mSurface != null) {
3014 w.mOrientationChanging = true;
3015 }
3016 }
3017 for (int i=mRotationWatchers.size()-1; i>=0; i--) {
3018 try {
3019 mRotationWatchers.get(i).onRotationChanged(rotation);
3020 } catch (RemoteException e) {
3021 }
3022 }
3023 } //end if changed
3024
3025 return changed;
3026 }
3027
3028 public int getRotation() {
3029 return mRotation;
3030 }
3031
3032 public int watchRotation(IRotationWatcher watcher) {
3033 final IBinder watcherBinder = watcher.asBinder();
3034 IBinder.DeathRecipient dr = new IBinder.DeathRecipient() {
3035 public void binderDied() {
3036 synchronized (mWindowMap) {
3037 for (int i=0; i<mRotationWatchers.size(); i++) {
3038 if (watcherBinder == mRotationWatchers.get(i).asBinder()) {
3039 mRotationWatchers.remove(i);
3040 i--;
3041 }
3042 }
3043 }
3044 }
3045 };
3046
3047 synchronized (mWindowMap) {
3048 try {
3049 watcher.asBinder().linkToDeath(dr, 0);
3050 mRotationWatchers.add(watcher);
3051 } catch (RemoteException e) {
3052 // Client died, no cleanup needed.
3053 }
3054
3055 return mRotation;
3056 }
3057 }
3058
3059 /**
3060 * Starts the view server on the specified port.
3061 *
3062 * @param port The port to listener to.
3063 *
3064 * @return True if the server was successfully started, false otherwise.
3065 *
3066 * @see com.android.server.ViewServer
3067 * @see com.android.server.ViewServer#VIEW_SERVER_DEFAULT_PORT
3068 */
3069 public boolean startViewServer(int port) {
3070 if ("1".equals(SystemProperties.get(SYSTEM_SECURE, "0"))) {
3071 return false;
3072 }
3073
3074 if (!checkCallingPermission(Manifest.permission.DUMP, "startViewServer")) {
3075 return false;
3076 }
3077
3078 if (port < 1024) {
3079 return false;
3080 }
3081
3082 if (mViewServer != null) {
3083 if (!mViewServer.isRunning()) {
3084 try {
3085 return mViewServer.start();
3086 } catch (IOException e) {
3087 Log.w(TAG, "View server did not start");
3088 }
3089 }
3090 return false;
3091 }
3092
3093 try {
3094 mViewServer = new ViewServer(this, port);
3095 return mViewServer.start();
3096 } catch (IOException e) {
3097 Log.w(TAG, "View server did not start");
3098 }
3099 return false;
3100 }
3101
3102 /**
3103 * Stops the view server if it exists.
3104 *
3105 * @return True if the server stopped, false if it wasn't started or
3106 * couldn't be stopped.
3107 *
3108 * @see com.android.server.ViewServer
3109 */
3110 public boolean stopViewServer() {
3111 if ("1".equals(SystemProperties.get(SYSTEM_SECURE, "0"))) {
3112 return false;
3113 }
3114
3115 if (!checkCallingPermission(Manifest.permission.DUMP, "stopViewServer")) {
3116 return false;
3117 }
3118
3119 if (mViewServer != null) {
3120 return mViewServer.stop();
3121 }
3122 return false;
3123 }
3124
3125 /**
3126 * Indicates whether the view server is running.
3127 *
3128 * @return True if the server is running, false otherwise.
3129 *
3130 * @see com.android.server.ViewServer
3131 */
3132 public boolean isViewServerRunning() {
3133 if ("1".equals(SystemProperties.get(SYSTEM_SECURE, "0"))) {
3134 return false;
3135 }
3136
3137 if (!checkCallingPermission(Manifest.permission.DUMP, "isViewServerRunning")) {
3138 return false;
3139 }
3140
3141 return mViewServer != null && mViewServer.isRunning();
3142 }
3143
3144 /**
3145 * Lists all availble windows in the system. The listing is written in the
3146 * specified Socket's output stream with the following syntax:
3147 * windowHashCodeInHexadecimal windowName
3148 * Each line of the ouput represents a different window.
3149 *
3150 * @param client The remote client to send the listing to.
3151 * @return False if an error occured, true otherwise.
3152 */
3153 boolean viewServerListWindows(Socket client) {
3154 if ("1".equals(SystemProperties.get(SYSTEM_SECURE, "0"))) {
3155 return false;
3156 }
3157
3158 boolean result = true;
3159
3160 Object[] windows;
3161 synchronized (mWindowMap) {
3162 windows = new Object[mWindows.size()];
3163 //noinspection unchecked
3164 windows = mWindows.toArray(windows);
3165 }
3166
3167 BufferedWriter out = null;
3168
3169 // Any uncaught exception will crash the system process
3170 try {
3171 OutputStream clientStream = client.getOutputStream();
3172 out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
3173
3174 final int count = windows.length;
3175 for (int i = 0; i < count; i++) {
3176 final WindowState w = (WindowState) windows[i];
3177 out.write(Integer.toHexString(System.identityHashCode(w)));
3178 out.write(' ');
3179 out.append(w.mAttrs.getTitle());
3180 out.write('\n');
3181 }
3182
3183 out.write("DONE.\n");
3184 out.flush();
3185 } catch (Exception e) {
3186 result = false;
3187 } finally {
3188 if (out != null) {
3189 try {
3190 out.close();
3191 } catch (IOException e) {
3192 result = false;
3193 }
3194 }
3195 }
3196
3197 return result;
3198 }
3199
3200 /**
3201 * Sends a command to a target window. The result of the command, if any, will be
3202 * written in the output stream of the specified socket.
3203 *
3204 * The parameters must follow this syntax:
3205 * windowHashcode extra
3206 *
3207 * Where XX is the length in characeters of the windowTitle.
3208 *
3209 * The first parameter is the target window. The window with the specified hashcode
3210 * will be the target. If no target can be found, nothing happens. The extra parameters
3211 * will be delivered to the target window and as parameters to the command itself.
3212 *
3213 * @param client The remote client to sent the result, if any, to.
3214 * @param command The command to execute.
3215 * @param parameters The command parameters.
3216 *
3217 * @return True if the command was successfully delivered, false otherwise. This does
3218 * not indicate whether the command itself was successful.
3219 */
3220 boolean viewServerWindowCommand(Socket client, String command, String parameters) {
3221 if ("1".equals(SystemProperties.get(SYSTEM_SECURE, "0"))) {
3222 return false;
3223 }
3224
3225 boolean success = true;
3226 Parcel data = null;
3227 Parcel reply = null;
3228
3229 // Any uncaught exception will crash the system process
3230 try {
3231 // Find the hashcode of the window
3232 int index = parameters.indexOf(' ');
3233 if (index == -1) {
3234 index = parameters.length();
3235 }
3236 final String code = parameters.substring(0, index);
3237 int hashCode = "ffffffff".equals(code) ? -1 : Integer.parseInt(code, 16);
3238
3239 // Extract the command's parameter after the window description
3240 if (index < parameters.length()) {
3241 parameters = parameters.substring(index + 1);
3242 } else {
3243 parameters = "";
3244 }
3245
3246 final WindowManagerService.WindowState window = findWindow(hashCode);
3247 if (window == null) {
3248 return false;
3249 }
3250
3251 data = Parcel.obtain();
3252 data.writeInterfaceToken("android.view.IWindow");
3253 data.writeString(command);
3254 data.writeString(parameters);
3255 data.writeInt(1);
3256 ParcelFileDescriptor.fromSocket(client).writeToParcel(data, 0);
3257
3258 reply = Parcel.obtain();
3259
3260 final IBinder binder = window.mClient.asBinder();
3261 // TODO: GET THE TRANSACTION CODE IN A SAFER MANNER
3262 binder.transact(IBinder.FIRST_CALL_TRANSACTION, data, reply, 0);
3263
3264 reply.readException();
3265
3266 } catch (Exception e) {
3267 Log.w(TAG, "Could not send command " + command + " with parameters " + parameters, e);
3268 success = false;
3269 } finally {
3270 if (data != null) {
3271 data.recycle();
3272 }
3273 if (reply != null) {
3274 reply.recycle();
3275 }
3276 }
3277
3278 return success;
3279 }
3280
3281 private WindowState findWindow(int hashCode) {
3282 if (hashCode == -1) {
3283 return getFocusedWindow();
3284 }
3285
3286 synchronized (mWindowMap) {
3287 final ArrayList windows = mWindows;
3288 final int count = windows.size();
3289
3290 for (int i = 0; i < count; i++) {
3291 WindowState w = (WindowState) windows.get(i);
3292 if (System.identityHashCode(w) == hashCode) {
3293 return w;
3294 }
3295 }
3296 }
3297
3298 return null;
3299 }
3300
3301 void sendNewConfiguration() {
3302 Configuration config;
3303 synchronized (mWindowMap) {
3304 config = computeNewConfigurationLocked();
3305 }
3306
3307 if (config != null) {
3308 try {
3309 mActivityManager.updateConfiguration(config);
3310 } catch (RemoteException e) {
3311 }
3312 }
3313 }
3314
3315 Configuration computeNewConfigurationLocked() {
3316 synchronized (mWindowMap) {
3317 if (mDisplay == null) {
3318 return null;
3319 }
3320 Configuration config = new Configuration();
3321 mQueue.getInputConfiguration(config);
3322 final int dw = mDisplay.getWidth();
3323 final int dh = mDisplay.getHeight();
3324 int orientation = Configuration.ORIENTATION_SQUARE;
3325 if (dw < dh) {
3326 orientation = Configuration.ORIENTATION_PORTRAIT;
3327 } else if (dw > dh) {
3328 orientation = Configuration.ORIENTATION_LANDSCAPE;
3329 }
3330 config.orientation = orientation;
3331 config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003332 config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003333 mPolicy.adjustConfigurationLw(config);
3334 Log.i(TAG, "Input configuration changed: " + config);
3335 long now = SystemClock.uptimeMillis();
3336 //Log.i(TAG, "Config changing, gc pending: " + mFreezeGcPending + ", now " + now);
3337 if (mFreezeGcPending != 0) {
3338 if (now > (mFreezeGcPending+1000)) {
3339 //Log.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
3340 mH.removeMessages(H.FORCE_GC);
3341 Runtime.getRuntime().gc();
3342 mFreezeGcPending = now;
3343 }
3344 } else {
3345 mFreezeGcPending = now;
3346 }
3347 return config;
3348 }
3349 }
3350
3351 // -------------------------------------------------------------
3352 // Input Events and Focus Management
3353 // -------------------------------------------------------------
3354
3355 private final void wakeupIfNeeded(WindowState targetWin, int eventType) {
3356 if (targetWin == null ||
3357 targetWin.mAttrs.type != WindowManager.LayoutParams.TYPE_KEYGUARD) {
3358 mPowerManager.userActivity(SystemClock.uptimeMillis(), false, eventType);
3359 }
3360 }
3361
3362 // tells if it's a cheek event or not -- this function is stateful
3363 private static final int EVENT_NONE = 0;
3364 private static final int EVENT_UNKNOWN = 0;
3365 private static final int EVENT_CHEEK = 0;
3366 private static final int EVENT_IGNORE_DURATION = 300; // ms
3367 private static final float CHEEK_THRESHOLD = 0.6f;
3368 private int mEventState = EVENT_NONE;
3369 private float mEventSize;
3370 private int eventType(MotionEvent ev) {
3371 float size = ev.getSize();
3372 switch (ev.getAction()) {
3373 case MotionEvent.ACTION_DOWN:
3374 mEventSize = size;
3375 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : TOUCH_EVENT;
3376 case MotionEvent.ACTION_UP:
3377 if (size > mEventSize) mEventSize = size;
3378 return (mEventSize > CHEEK_THRESHOLD) ? CHEEK_EVENT : OTHER_EVENT;
3379 case MotionEvent.ACTION_MOVE:
3380 final int N = ev.getHistorySize();
3381 if (size > mEventSize) mEventSize = size;
3382 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
3383 for (int i=0; i<N; i++) {
3384 size = ev.getHistoricalSize(i);
3385 if (size > mEventSize) mEventSize = size;
3386 if (mEventSize > CHEEK_THRESHOLD) return CHEEK_EVENT;
3387 }
3388 if (ev.getEventTime() < ev.getDownTime() + EVENT_IGNORE_DURATION) {
3389 return TOUCH_EVENT;
3390 } else {
3391 return OTHER_EVENT;
3392 }
3393 default:
3394 // not good
3395 return OTHER_EVENT;
3396 }
3397 }
3398
3399 /**
3400 * @return Returns true if event was dispatched, false if it was dropped for any reason
3401 */
3402 private boolean dispatchPointer(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
3403 if (DEBUG_INPUT || WindowManagerPolicy.WATCH_POINTER) Log.v(TAG,
3404 "dispatchPointer " + ev);
3405
3406 Object targetObj = mKeyWaiter.waitForNextEventTarget(null, qev,
3407 ev, true, false);
3408
3409 int action = ev.getAction();
3410
3411 if (action == MotionEvent.ACTION_UP) {
3412 // let go of our target
3413 mKeyWaiter.mMotionTarget = null;
3414 mPowerManager.logPointerUpEvent();
3415 } else if (action == MotionEvent.ACTION_DOWN) {
3416 mPowerManager.logPointerDownEvent();
3417 }
3418
3419 if (targetObj == null) {
3420 // In this case we are either dropping the event, or have received
3421 // a move or up without a down. It is common to receive move
3422 // events in such a way, since this means the user is moving the
3423 // pointer without actually pressing down. All other cases should
3424 // be atypical, so let's log them.
3425 if (ev.getAction() != MotionEvent.ACTION_MOVE) {
3426 Log.w(TAG, "No window to dispatch pointer action " + ev.getAction());
3427 }
3428 if (qev != null) {
3429 mQueue.recycleEvent(qev);
3430 }
3431 ev.recycle();
3432 return false;
3433 }
3434 if (targetObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
3435 if (qev != null) {
3436 mQueue.recycleEvent(qev);
3437 }
3438 ev.recycle();
3439 return true;
3440 }
3441
3442 WindowState target = (WindowState)targetObj;
3443
3444 final long eventTime = ev.getEventTime();
3445
3446 //Log.i(TAG, "Sending " + ev + " to " + target);
3447
3448 if (uid != 0 && uid != target.mSession.mUid) {
3449 if (mContext.checkPermission(
3450 android.Manifest.permission.INJECT_EVENTS, pid, uid)
3451 != PackageManager.PERMISSION_GRANTED) {
3452 Log.w(TAG, "Permission denied: injecting pointer event from pid "
3453 + pid + " uid " + uid + " to window " + target
3454 + " owned by uid " + target.mSession.mUid);
3455 if (qev != null) {
3456 mQueue.recycleEvent(qev);
3457 }
3458 ev.recycle();
3459 return false;
3460 }
3461 }
3462
3463 if ((target.mAttrs.flags &
3464 WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES) != 0) {
3465 //target wants to ignore fat touch events
3466 boolean cheekPress = mPolicy.isCheekPressedAgainstScreen(ev);
3467 //explicit flag to return without processing event further
3468 boolean returnFlag = false;
3469 if((action == MotionEvent.ACTION_DOWN)) {
3470 mFatTouch = false;
3471 if(cheekPress) {
3472 mFatTouch = true;
3473 returnFlag = true;
3474 }
3475 } else {
3476 if(action == MotionEvent.ACTION_UP) {
3477 if(mFatTouch) {
3478 //earlier even was invalid doesnt matter if current up is cheekpress or not
3479 mFatTouch = false;
3480 returnFlag = true;
3481 } else if(cheekPress) {
3482 //cancel the earlier event
3483 ev.setAction(MotionEvent.ACTION_CANCEL);
3484 action = MotionEvent.ACTION_CANCEL;
3485 }
3486 } else if(action == MotionEvent.ACTION_MOVE) {
3487 if(mFatTouch) {
3488 //two cases here
3489 //an invalid down followed by 0 or moves(valid or invalid)
3490 //a valid down, invalid move, more moves. want to ignore till up
3491 returnFlag = true;
3492 } else if(cheekPress) {
3493 //valid down followed by invalid moves
3494 //an invalid move have to cancel earlier action
3495 ev.setAction(MotionEvent.ACTION_CANCEL);
3496 action = MotionEvent.ACTION_CANCEL;
3497 if (DEBUG_INPUT) Log.v(TAG, "Sending cancel for invalid ACTION_MOVE");
3498 //note that the subsequent invalid moves will not get here
3499 mFatTouch = true;
3500 }
3501 }
3502 } //else if action
3503 if(returnFlag) {
3504 //recycle que, ev
3505 if (qev != null) {
3506 mQueue.recycleEvent(qev);
3507 }
3508 ev.recycle();
3509 return false;
3510 }
3511 } //end if target
3512
3513 synchronized(mWindowMap) {
3514 if (qev != null && action == MotionEvent.ACTION_MOVE) {
3515 mKeyWaiter.bindTargetWindowLocked(target,
3516 KeyWaiter.RETURN_PENDING_POINTER, qev);
3517 ev = null;
3518 } else {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003519 if (action == MotionEvent.ACTION_DOWN) {
3520 WindowState out = mKeyWaiter.mOutsideTouchTargets;
3521 if (out != null) {
3522 MotionEvent oev = MotionEvent.obtain(ev);
3523 oev.setAction(MotionEvent.ACTION_OUTSIDE);
3524 do {
3525 final Rect frame = out.mFrame;
3526 oev.offsetLocation(-(float)frame.left, -(float)frame.top);
3527 try {
3528 out.mClient.dispatchPointer(oev, eventTime);
3529 } catch (android.os.RemoteException e) {
3530 Log.i(TAG, "WINDOW DIED during outside motion dispatch: " + out);
3531 }
3532 oev.offsetLocation((float)frame.left, (float)frame.top);
3533 out = out.mNextOutsideTouch;
3534 } while (out != null);
3535 mKeyWaiter.mOutsideTouchTargets = null;
3536 }
3537 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003538 final Rect frame = target.mFrame;
3539 ev.offsetLocation(-(float)frame.left, -(float)frame.top);
3540 mKeyWaiter.bindTargetWindowLocked(target);
3541 }
3542 }
3543
3544 // finally offset the event to the target's coordinate system and
3545 // dispatch the event.
3546 try {
3547 if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
3548 Log.v(TAG, "Delivering pointer " + qev + " to " + target);
3549 }
3550 target.mClient.dispatchPointer(ev, eventTime);
3551 return true;
3552 } catch (android.os.RemoteException e) {
3553 Log.i(TAG, "WINDOW DIED during motion dispatch: " + target);
3554 mKeyWaiter.mMotionTarget = null;
3555 try {
3556 removeWindow(target.mSession, target.mClient);
3557 } catch (java.util.NoSuchElementException ex) {
3558 // This will happen if the window has already been
3559 // removed.
3560 }
3561 }
3562 return false;
3563 }
3564
3565 /**
3566 * @return Returns true if event was dispatched, false if it was dropped for any reason
3567 */
3568 private boolean dispatchTrackball(QueuedEvent qev, MotionEvent ev, int pid, int uid) {
3569 if (DEBUG_INPUT) Log.v(
3570 TAG, "dispatchTrackball [" + ev.getAction() +"] <" + ev.getX() + ", " + ev.getY() + ">");
3571
3572 Object focusObj = mKeyWaiter.waitForNextEventTarget(null, qev,
3573 ev, false, false);
3574 if (focusObj == null) {
3575 Log.w(TAG, "No focus window, dropping trackball: " + ev);
3576 if (qev != null) {
3577 mQueue.recycleEvent(qev);
3578 }
3579 ev.recycle();
3580 return false;
3581 }
3582 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
3583 if (qev != null) {
3584 mQueue.recycleEvent(qev);
3585 }
3586 ev.recycle();
3587 return true;
3588 }
3589
3590 WindowState focus = (WindowState)focusObj;
3591
3592 if (uid != 0 && uid != focus.mSession.mUid) {
3593 if (mContext.checkPermission(
3594 android.Manifest.permission.INJECT_EVENTS, pid, uid)
3595 != PackageManager.PERMISSION_GRANTED) {
3596 Log.w(TAG, "Permission denied: injecting key event from pid "
3597 + pid + " uid " + uid + " to window " + focus
3598 + " owned by uid " + focus.mSession.mUid);
3599 if (qev != null) {
3600 mQueue.recycleEvent(qev);
3601 }
3602 ev.recycle();
3603 return false;
3604 }
3605 }
3606
3607 final long eventTime = ev.getEventTime();
3608
3609 synchronized(mWindowMap) {
3610 if (qev != null && ev.getAction() == MotionEvent.ACTION_MOVE) {
3611 mKeyWaiter.bindTargetWindowLocked(focus,
3612 KeyWaiter.RETURN_PENDING_TRACKBALL, qev);
3613 // We don't deliver movement events to the client, we hold
3614 // them and wait for them to call back.
3615 ev = null;
3616 } else {
3617 mKeyWaiter.bindTargetWindowLocked(focus);
3618 }
3619 }
3620
3621 try {
3622 focus.mClient.dispatchTrackball(ev, eventTime);
3623 return true;
3624 } catch (android.os.RemoteException e) {
3625 Log.i(TAG, "WINDOW DIED during key dispatch: " + focus);
3626 try {
3627 removeWindow(focus.mSession, focus.mClient);
3628 } catch (java.util.NoSuchElementException ex) {
3629 // This will happen if the window has already been
3630 // removed.
3631 }
3632 }
3633
3634 return false;
3635 }
3636
3637 /**
3638 * @return Returns true if event was dispatched, false if it was dropped for any reason
3639 */
3640 private boolean dispatchKey(KeyEvent event, int pid, int uid) {
3641 if (DEBUG_INPUT) Log.v(TAG, "Dispatch key: " + event);
3642
3643 Object focusObj = mKeyWaiter.waitForNextEventTarget(event, null,
3644 null, false, false);
3645 if (focusObj == null) {
3646 Log.w(TAG, "No focus window, dropping: " + event);
3647 return false;
3648 }
3649 if (focusObj == mKeyWaiter.CONSUMED_EVENT_TOKEN) {
3650 return true;
3651 }
3652
3653 WindowState focus = (WindowState)focusObj;
3654
3655 if (DEBUG_INPUT) Log.v(
3656 TAG, "Dispatching to " + focus + ": " + event);
3657
3658 if (uid != 0 && uid != focus.mSession.mUid) {
3659 if (mContext.checkPermission(
3660 android.Manifest.permission.INJECT_EVENTS, pid, uid)
3661 != PackageManager.PERMISSION_GRANTED) {
3662 Log.w(TAG, "Permission denied: injecting key event from pid "
3663 + pid + " uid " + uid + " to window " + focus
3664 + " owned by uid " + focus.mSession.mUid);
3665 return false;
3666 }
3667 }
3668
3669 synchronized(mWindowMap) {
3670 mKeyWaiter.bindTargetWindowLocked(focus);
3671 }
3672
3673 try {
3674 if (DEBUG_INPUT || DEBUG_FOCUS) {
3675 Log.v(TAG, "Delivering key " + event.getKeyCode()
3676 + " to " + focus);
3677 }
3678 focus.mClient.dispatchKey(event);
3679 return true;
3680 } catch (android.os.RemoteException e) {
3681 Log.i(TAG, "WINDOW DIED during key dispatch: " + focus);
3682 try {
3683 removeWindow(focus.mSession, focus.mClient);
3684 } catch (java.util.NoSuchElementException ex) {
3685 // This will happen if the window has already been
3686 // removed.
3687 }
3688 }
3689
3690 return false;
3691 }
3692
3693 public void pauseKeyDispatching(IBinder _token) {
3694 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3695 "pauseKeyDispatching()")) {
3696 return;
3697 }
3698
3699 synchronized (mWindowMap) {
3700 WindowToken token = mTokenMap.get(_token);
3701 if (token != null) {
3702 mKeyWaiter.pauseDispatchingLocked(token);
3703 }
3704 }
3705 }
3706
3707 public void resumeKeyDispatching(IBinder _token) {
3708 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3709 "resumeKeyDispatching()")) {
3710 return;
3711 }
3712
3713 synchronized (mWindowMap) {
3714 WindowToken token = mTokenMap.get(_token);
3715 if (token != null) {
3716 mKeyWaiter.resumeDispatchingLocked(token);
3717 }
3718 }
3719 }
3720
3721 public void setEventDispatching(boolean enabled) {
3722 if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
3723 "resumeKeyDispatching()")) {
3724 return;
3725 }
3726
3727 synchronized (mWindowMap) {
3728 mKeyWaiter.setEventDispatchingLocked(enabled);
3729 }
3730 }
3731
3732 /**
3733 * Injects a keystroke event into the UI.
3734 *
3735 * @param ev A motion event describing the keystroke action. (Be sure to use
3736 * {@link SystemClock#uptimeMillis()} as the timebase.)
3737 * @param sync If true, wait for the event to be completed before returning to the caller.
3738 * @return Returns true if event was dispatched, false if it was dropped for any reason
3739 */
3740 public boolean injectKeyEvent(KeyEvent ev, boolean sync) {
3741 long downTime = ev.getDownTime();
3742 long eventTime = ev.getEventTime();
3743
3744 int action = ev.getAction();
3745 int code = ev.getKeyCode();
3746 int repeatCount = ev.getRepeatCount();
3747 int metaState = ev.getMetaState();
3748 int deviceId = ev.getDeviceId();
3749 int scancode = ev.getScanCode();
3750
3751 if (eventTime == 0) eventTime = SystemClock.uptimeMillis();
3752 if (downTime == 0) downTime = eventTime;
3753
3754 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
3755 deviceId, scancode);
3756
3757 boolean result = dispatchKey(newEvent, Binder.getCallingPid(), Binder.getCallingUid());
3758 if (sync) {
3759 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true);
3760 }
3761 return result;
3762 }
3763
3764 /**
3765 * Inject a pointer (touch) event into the UI.
3766 *
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003767 * @param ev A motion event describing the pointer (touch) action. (As noted in
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003768 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
3769 * {@link SystemClock#uptimeMillis()} as the timebase.)
3770 * @param sync If true, wait for the event to be completed before returning to the caller.
3771 * @return Returns true if event was dispatched, false if it was dropped for any reason
3772 */
3773 public boolean injectPointerEvent(MotionEvent ev, boolean sync) {
3774 boolean result = dispatchPointer(null, ev, Binder.getCallingPid(), Binder.getCallingUid());
3775 if (sync) {
3776 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true);
3777 }
3778 return result;
3779 }
3780
3781 /**
3782 * Inject a trackball (navigation device) event into the UI.
3783 *
3784 * @param ev A motion event describing the trackball action. (As noted in
3785 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
3786 * {@link SystemClock#uptimeMillis()} as the timebase.)
3787 * @param sync If true, wait for the event to be completed before returning to the caller.
3788 * @return Returns true if event was dispatched, false if it was dropped for any reason
3789 */
3790 public boolean injectTrackballEvent(MotionEvent ev, boolean sync) {
3791 boolean result = dispatchTrackball(null, ev, Binder.getCallingPid(), Binder.getCallingUid());
3792 if (sync) {
3793 mKeyWaiter.waitForNextEventTarget(null, null, null, false, true);
3794 }
3795 return result;
3796 }
3797
3798 private WindowState getFocusedWindow() {
3799 synchronized (mWindowMap) {
3800 return getFocusedWindowLocked();
3801 }
3802 }
3803
3804 private WindowState getFocusedWindowLocked() {
3805 return mCurrentFocus;
3806 }
3807
3808 /**
3809 * This class holds the state for dispatching key events. This state
3810 * is protected by the KeyWaiter instance, NOT by the window lock. You
3811 * can be holding the main window lock while acquire the KeyWaiter lock,
3812 * but not the other way around.
3813 */
3814 final class KeyWaiter {
3815 public static final int RETURN_NOTHING = 0;
3816 public static final int RETURN_PENDING_POINTER = 1;
3817 public static final int RETURN_PENDING_TRACKBALL = 2;
3818
3819 final Object SKIP_TARGET_TOKEN = new Object();
3820 final Object CONSUMED_EVENT_TOKEN = new Object();
3821
3822 private WindowState mLastWin = null;
3823 private IBinder mLastBinder = null;
3824 private boolean mFinished = true;
3825 private boolean mGotFirstWindow = false;
3826 private boolean mEventDispatching = true;
3827 private long mTimeToSwitch = 0;
3828 /* package */ boolean mWasFrozen = false;
3829
3830 // Target of Motion events
3831 WindowState mMotionTarget;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08003832
3833 // Windows above the target who would like to receive an "outside"
3834 // touch event for any down events outside of them.
3835 WindowState mOutsideTouchTargets;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07003836
3837 /**
3838 * Wait for the last event dispatch to complete, then find the next
3839 * target that should receive the given event and wait for that one
3840 * to be ready to receive it.
3841 */
3842 Object waitForNextEventTarget(KeyEvent nextKey, QueuedEvent qev,
3843 MotionEvent nextMotion, boolean isPointerEvent,
3844 boolean failIfTimeout) {
3845 long startTime = SystemClock.uptimeMillis();
3846 long keyDispatchingTimeout = 5 * 1000;
3847 long waitedFor = 0;
3848
3849 while (true) {
3850 // Figure out which window we care about. It is either the
3851 // last window we are waiting to have process the event or,
3852 // if none, then the next window we think the event should go
3853 // to. Note: we retrieve mLastWin outside of the lock, so
3854 // it may change before we lock. Thus we must check it again.
3855 WindowState targetWin = mLastWin;
3856 boolean targetIsNew = targetWin == null;
3857 if (DEBUG_INPUT) Log.v(
3858 TAG, "waitForLastKey: mFinished=" + mFinished +
3859 ", mLastWin=" + mLastWin);
3860 if (targetIsNew) {
3861 Object target = findTargetWindow(nextKey, qev, nextMotion,
3862 isPointerEvent);
3863 if (target == SKIP_TARGET_TOKEN) {
3864 // The user has pressed a special key, and we are
3865 // dropping all pending events before it.
3866 if (DEBUG_INPUT) Log.v(TAG, "Skipping: " + nextKey
3867 + " " + nextMotion);
3868 return null;
3869 }
3870 if (target == CONSUMED_EVENT_TOKEN) {
3871 if (DEBUG_INPUT) Log.v(TAG, "Consumed: " + nextKey
3872 + " " + nextMotion);
3873 return target;
3874 }
3875 targetWin = (WindowState)target;
3876 }
3877
3878 AppWindowToken targetApp = null;
3879
3880 // Now: is it okay to send the next event to this window?
3881 synchronized (this) {
3882 // First: did we come here based on the last window not
3883 // being null, but it changed by the time we got here?
3884 // If so, try again.
3885 if (!targetIsNew && mLastWin == null) {
3886 continue;
3887 }
3888
3889 // We never dispatch events if not finished with the
3890 // last one, or the display is frozen.
3891 if (mFinished && !mDisplayFrozen) {
3892 // If event dispatching is disabled, then we
3893 // just consume the events.
3894 if (!mEventDispatching) {
3895 if (DEBUG_INPUT) Log.v(TAG,
3896 "Skipping event; dispatching disabled: "
3897 + nextKey + " " + nextMotion);
3898 return null;
3899 }
3900 if (targetWin != null) {
3901 // If this is a new target, and that target is not
3902 // paused or unresponsive, then all looks good to
3903 // handle the event.
3904 if (targetIsNew && !targetWin.mToken.paused) {
3905 return targetWin;
3906 }
3907
3908 // If we didn't find a target window, and there is no
3909 // focused app window, then just eat the events.
3910 } else if (mFocusedApp == null) {
3911 if (DEBUG_INPUT) Log.v(TAG,
3912 "Skipping event; no focused app: "
3913 + nextKey + " " + nextMotion);
3914 return null;
3915 }
3916 }
3917
3918 if (DEBUG_INPUT) Log.v(
3919 TAG, "Waiting for last key in " + mLastBinder
3920 + " target=" + targetWin
3921 + " mFinished=" + mFinished
3922 + " mDisplayFrozen=" + mDisplayFrozen
3923 + " targetIsNew=" + targetIsNew
3924 + " paused="
3925 + (targetWin != null ? targetWin.mToken.paused : false)
3926 + " mFocusedApp=" + mFocusedApp);
3927
3928 targetApp = targetWin != null
3929 ? targetWin.mAppToken : mFocusedApp;
3930
3931 long curTimeout = keyDispatchingTimeout;
3932 if (mTimeToSwitch != 0) {
3933 long now = SystemClock.uptimeMillis();
3934 if (mTimeToSwitch <= now) {
3935 // If an app switch key has been pressed, and we have
3936 // waited too long for the current app to finish
3937 // processing keys, then wait no more!
3938 doFinishedKeyLocked(true);
3939 continue;
3940 }
3941 long switchTimeout = mTimeToSwitch - now;
3942 if (curTimeout > switchTimeout) {
3943 curTimeout = switchTimeout;
3944 }
3945 }
3946
3947 try {
3948 // after that continue
3949 // processing keys, so we don't get stuck.
3950 if (DEBUG_INPUT) Log.v(
3951 TAG, "Waiting for key dispatch: " + curTimeout);
3952 wait(curTimeout);
3953 if (DEBUG_INPUT) Log.v(TAG, "Finished waiting @"
3954 + SystemClock.uptimeMillis() + " startTime="
3955 + startTime + " switchTime=" + mTimeToSwitch);
3956 } catch (InterruptedException e) {
3957 }
3958 }
3959
3960 // If we were frozen during configuration change, restart the
3961 // timeout checks from now; otherwise look at whether we timed
3962 // out before awakening.
3963 if (mWasFrozen) {
3964 waitedFor = 0;
3965 mWasFrozen = false;
3966 } else {
3967 waitedFor = SystemClock.uptimeMillis() - startTime;
3968 }
3969
3970 if (waitedFor >= keyDispatchingTimeout && mTimeToSwitch == 0) {
3971 IApplicationToken at = null;
3972 synchronized (this) {
3973 Log.w(TAG, "Key dispatching timed out sending to " +
3974 (targetWin != null ? targetWin.mAttrs.getTitle()
3975 : "<null>"));
3976 //dump();
3977 if (targetWin != null) {
3978 at = targetWin.getAppToken();
3979 } else if (targetApp != null) {
3980 at = targetApp.appToken;
3981 }
3982 }
3983
3984 boolean abort = true;
3985 if (at != null) {
3986 try {
3987 long timeout = at.getKeyDispatchingTimeout();
3988 if (timeout > waitedFor) {
3989 // we did not wait the proper amount of time for this application.
3990 // set the timeout to be the real timeout and wait again.
3991 keyDispatchingTimeout = timeout - waitedFor;
3992 continue;
3993 } else {
3994 abort = at.keyDispatchingTimedOut();
3995 }
3996 } catch (RemoteException ex) {
3997 }
3998 }
3999
4000 synchronized (this) {
4001 if (abort && (mLastWin == targetWin || targetWin == null)) {
4002 mFinished = true;
4003 if (mLastWin != null) {
4004 if (DEBUG_INPUT) Log.v(TAG,
4005 "Window " + mLastWin +
4006 " timed out on key input");
4007 if (mLastWin.mToken.paused) {
4008 Log.w(TAG, "Un-pausing dispatching to this window");
4009 mLastWin.mToken.paused = false;
4010 }
4011 }
4012 if (mMotionTarget == targetWin) {
4013 mMotionTarget = null;
4014 }
4015 mLastWin = null;
4016 mLastBinder = null;
4017 if (failIfTimeout || targetWin == null) {
4018 return null;
4019 }
4020 } else {
4021 Log.w(TAG, "Continuing to wait for key to be dispatched");
4022 startTime = SystemClock.uptimeMillis();
4023 }
4024 }
4025 }
4026 }
4027 }
4028
4029 Object findTargetWindow(KeyEvent nextKey, QueuedEvent qev,
4030 MotionEvent nextMotion, boolean isPointerEvent) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004031 mOutsideTouchTargets = null;
4032
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004033 if (nextKey != null) {
4034 // Find the target window for a normal key event.
4035 final int keycode = nextKey.getKeyCode();
4036 final int repeatCount = nextKey.getRepeatCount();
4037 final boolean down = nextKey.getAction() != KeyEvent.ACTION_UP;
4038 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(keycode);
4039 if (!dispatch) {
4040 mPolicy.interceptKeyTi(null, keycode,
4041 nextKey.getMetaState(), down, repeatCount);
4042 Log.w(TAG, "Event timeout during app switch: dropping "
4043 + nextKey);
4044 return SKIP_TARGET_TOKEN;
4045 }
4046
4047 // System.out.println("##### [" + SystemClock.uptimeMillis() + "] WindowManagerService.dispatchKey(" + keycode + ", " + down + ", " + repeatCount + ")");
4048
4049 WindowState focus = null;
4050 synchronized(mWindowMap) {
4051 focus = getFocusedWindowLocked();
4052 }
4053
4054 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
4055
4056 if (mPolicy.interceptKeyTi(focus,
4057 keycode, nextKey.getMetaState(), down, repeatCount)) {
4058 return CONSUMED_EVENT_TOKEN;
4059 }
4060
4061 return focus;
4062
4063 } else if (!isPointerEvent) {
4064 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(-1);
4065 if (!dispatch) {
4066 Log.w(TAG, "Event timeout during app switch: dropping trackball "
4067 + nextMotion);
4068 return SKIP_TARGET_TOKEN;
4069 }
4070
4071 WindowState focus = null;
4072 synchronized(mWindowMap) {
4073 focus = getFocusedWindowLocked();
4074 }
4075
4076 wakeupIfNeeded(focus, LocalPowerManager.BUTTON_EVENT);
4077 return focus;
4078 }
4079
4080 if (nextMotion == null) {
4081 return SKIP_TARGET_TOKEN;
4082 }
4083
4084 boolean dispatch = mKeyWaiter.checkShouldDispatchKey(
4085 KeyEvent.KEYCODE_UNKNOWN);
4086 if (!dispatch) {
4087 Log.w(TAG, "Event timeout during app switch: dropping pointer "
4088 + nextMotion);
4089 return SKIP_TARGET_TOKEN;
4090 }
4091
4092 // Find the target window for a pointer event.
4093 int action = nextMotion.getAction();
4094 final float xf = nextMotion.getX();
4095 final float yf = nextMotion.getY();
4096 final long eventTime = nextMotion.getEventTime();
4097
4098 final boolean screenWasOff = qev != null
4099 && (qev.flags&WindowManagerPolicy.FLAG_BRIGHT_HERE) != 0;
4100
4101 WindowState target = null;
4102
4103 synchronized(mWindowMap) {
4104 synchronized (this) {
4105 if (action == MotionEvent.ACTION_DOWN) {
4106 if (mMotionTarget != null) {
4107 // this is weird, we got a pen down, but we thought it was
4108 // already down!
4109 // XXX: We should probably send an ACTION_UP to the current
4110 // target.
4111 Log.w(TAG, "Pointer down received while already down in: "
4112 + mMotionTarget);
4113 mMotionTarget = null;
4114 }
4115
4116 // ACTION_DOWN is special, because we need to lock next events to
4117 // the window we'll land onto.
4118 final int x = (int)xf;
4119 final int y = (int)yf;
4120
4121 final ArrayList windows = mWindows;
4122 final int N = windows.size();
4123 WindowState topErrWindow = null;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004124 final Rect tmpRect = mTempRect;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004125 for (int i=N-1; i>=0; i--) {
4126 WindowState child = (WindowState)windows.get(i);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004127 //Log.i(TAG, "Checking dispatch to: " + child);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004128 final int flags = child.mAttrs.flags;
4129 if ((flags & WindowManager.LayoutParams.FLAG_SYSTEM_ERROR) != 0) {
4130 if (topErrWindow == null) {
4131 topErrWindow = child;
4132 }
4133 }
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08004134 if (!child.isVisibleLw()) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004135 //Log.i(TAG, "Not visible!");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004136 continue;
4137 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004138 if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004139 //Log.i(TAG, "Not touchable!");
4140 if ((flags & WindowManager.LayoutParams
4141 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
4142 child.mNextOutsideTouch = mOutsideTouchTargets;
4143 mOutsideTouchTargets = child;
4144 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004145 continue;
4146 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004147 tmpRect.set(child.mFrame);
4148 if (child.mTouchableInsets == ViewTreeObserver
4149 .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
4150 // The touch is inside of the window if it is
4151 // inside the frame, AND the content part of that
4152 // frame that was given by the application.
4153 tmpRect.left += child.mGivenContentInsets.left;
4154 tmpRect.top += child.mGivenContentInsets.top;
4155 tmpRect.right -= child.mGivenContentInsets.right;
4156 tmpRect.bottom -= child.mGivenContentInsets.bottom;
4157 } else if (child.mTouchableInsets == ViewTreeObserver
4158 .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
4159 // The touch is inside of the window if it is
4160 // inside the frame, AND the visible part of that
4161 // frame that was given by the application.
4162 tmpRect.left += child.mGivenVisibleInsets.left;
4163 tmpRect.top += child.mGivenVisibleInsets.top;
4164 tmpRect.right -= child.mGivenVisibleInsets.right;
4165 tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
4166 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004167 final int touchFlags = flags &
4168 (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
4169 |WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004170 if (tmpRect.contains(x, y) || touchFlags == 0) {
4171 //Log.i(TAG, "Using this target!");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004172 if (!screenWasOff || (flags &
4173 WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING) != 0) {
4174 mMotionTarget = child;
4175 } else {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004176 //Log.i(TAG, "Waking, skip!");
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004177 mMotionTarget = null;
4178 }
4179 break;
4180 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004181
4182 if ((flags & WindowManager.LayoutParams
4183 .FLAG_WATCH_OUTSIDE_TOUCH) != 0) {
4184 child.mNextOutsideTouch = mOutsideTouchTargets;
4185 mOutsideTouchTargets = child;
4186 //Log.i(TAG, "Adding to outside target list: " + child);
4187 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004188 }
4189
4190 // if there's an error window but it's not accepting
4191 // focus (typically because it is not yet visible) just
4192 // wait for it -- any other focused window may in fact
4193 // be in ANR state.
4194 if (topErrWindow != null && mMotionTarget != topErrWindow) {
4195 mMotionTarget = null;
4196 }
4197 }
4198
4199 target = mMotionTarget;
4200 }
4201 }
4202
4203 wakeupIfNeeded(target, eventType(nextMotion));
4204
4205 // Pointer events are a little different -- if there isn't a
4206 // target found for any event, then just drop it.
4207 return target != null ? target : SKIP_TARGET_TOKEN;
4208 }
4209
4210 boolean checkShouldDispatchKey(int keycode) {
4211 synchronized (this) {
4212 if (mPolicy.isAppSwitchKeyTqTiLwLi(keycode)) {
4213 mTimeToSwitch = 0;
4214 return true;
4215 }
4216 if (mTimeToSwitch != 0
4217 && mTimeToSwitch < SystemClock.uptimeMillis()) {
4218 return false;
4219 }
4220 return true;
4221 }
4222 }
4223
4224 void bindTargetWindowLocked(WindowState win,
4225 int pendingWhat, QueuedEvent pendingMotion) {
4226 synchronized (this) {
4227 bindTargetWindowLockedLocked(win, pendingWhat, pendingMotion);
4228 }
4229 }
4230
4231 void bindTargetWindowLocked(WindowState win) {
4232 synchronized (this) {
4233 bindTargetWindowLockedLocked(win, RETURN_NOTHING, null);
4234 }
4235 }
4236
4237 void bindTargetWindowLockedLocked(WindowState win,
4238 int pendingWhat, QueuedEvent pendingMotion) {
4239 mLastWin = win;
4240 mLastBinder = win.mClient.asBinder();
4241 mFinished = false;
4242 if (pendingMotion != null) {
4243 final Session s = win.mSession;
4244 if (pendingWhat == RETURN_PENDING_POINTER) {
4245 releasePendingPointerLocked(s);
4246 s.mPendingPointerMove = pendingMotion;
4247 s.mPendingPointerWindow = win;
4248 if (DEBUG_INPUT) Log.v(TAG,
4249 "bindTargetToWindow " + s.mPendingPointerMove);
4250 } else if (pendingWhat == RETURN_PENDING_TRACKBALL) {
4251 releasePendingTrackballLocked(s);
4252 s.mPendingTrackballMove = pendingMotion;
4253 s.mPendingTrackballWindow = win;
4254 }
4255 }
4256 }
4257
4258 void releasePendingPointerLocked(Session s) {
4259 if (DEBUG_INPUT) Log.v(TAG,
4260 "releasePendingPointer " + s.mPendingPointerMove);
4261 if (s.mPendingPointerMove != null) {
4262 mQueue.recycleEvent(s.mPendingPointerMove);
4263 s.mPendingPointerMove = null;
4264 }
4265 }
4266
4267 void releasePendingTrackballLocked(Session s) {
4268 if (s.mPendingTrackballMove != null) {
4269 mQueue.recycleEvent(s.mPendingTrackballMove);
4270 s.mPendingTrackballMove = null;
4271 }
4272 }
4273
4274 MotionEvent finishedKey(Session session, IWindow client, boolean force,
4275 int returnWhat) {
4276 if (DEBUG_INPUT) Log.v(
4277 TAG, "finishedKey: client=" + client + ", force=" + force);
4278
4279 if (client == null) {
4280 return null;
4281 }
4282
4283 synchronized (this) {
4284 if (DEBUG_INPUT) Log.v(
4285 TAG, "finishedKey: client=" + client.asBinder()
4286 + ", force=" + force + ", last=" + mLastBinder
4287 + " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
4288
4289 QueuedEvent qev = null;
4290 WindowState win = null;
4291 if (returnWhat == RETURN_PENDING_POINTER) {
4292 qev = session.mPendingPointerMove;
4293 win = session.mPendingPointerWindow;
4294 session.mPendingPointerMove = null;
4295 session.mPendingPointerWindow = null;
4296 } else if (returnWhat == RETURN_PENDING_TRACKBALL) {
4297 qev = session.mPendingTrackballMove;
4298 win = session.mPendingTrackballWindow;
4299 session.mPendingTrackballMove = null;
4300 session.mPendingTrackballWindow = null;
4301 }
4302
4303 if (mLastBinder == client.asBinder()) {
4304 if (DEBUG_INPUT) Log.v(
4305 TAG, "finishedKey: last paused="
4306 + ((mLastWin != null) ? mLastWin.mToken.paused : "null"));
4307 if (mLastWin != null && (!mLastWin.mToken.paused || force
4308 || !mEventDispatching)) {
4309 doFinishedKeyLocked(false);
4310 } else {
4311 // Make sure to wake up anyone currently waiting to
4312 // dispatch a key, so they can re-evaluate their
4313 // current situation.
4314 mFinished = true;
4315 notifyAll();
4316 }
4317 }
4318
4319 if (qev != null) {
4320 MotionEvent res = (MotionEvent)qev.event;
4321 if (DEBUG_INPUT) Log.v(TAG,
4322 "Returning pending motion: " + res);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004323 mQueue.recycleEvent(qev);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004324 if (win != null && returnWhat == RETURN_PENDING_POINTER) {
4325 res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
4326 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004327 return res;
4328 }
4329 return null;
4330 }
4331 }
4332
4333 void tickle() {
4334 synchronized (this) {
4335 notifyAll();
4336 }
4337 }
4338
4339 void handleNewWindowLocked(WindowState newWindow) {
4340 if (!newWindow.canReceiveKeys()) {
4341 return;
4342 }
4343 synchronized (this) {
4344 if (DEBUG_INPUT) Log.v(
4345 TAG, "New key dispatch window: win="
4346 + newWindow.mClient.asBinder()
4347 + ", last=" + mLastBinder
4348 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
4349 + "), finished=" + mFinished + ", paused="
4350 + newWindow.mToken.paused);
4351
4352 // Displaying a window implicitly causes dispatching to
4353 // be unpaused. (This is to protect against bugs if someone
4354 // pauses dispatching but forgets to resume.)
4355 newWindow.mToken.paused = false;
4356
4357 mGotFirstWindow = true;
4358 boolean doNotify = true;
4359
4360 if ((newWindow.mAttrs.flags & FLAG_SYSTEM_ERROR) != 0) {
4361 if (DEBUG_INPUT) Log.v(TAG,
4362 "New SYSTEM_ERROR window; resetting state");
4363 mLastWin = null;
4364 mLastBinder = null;
4365 mMotionTarget = null;
4366 mFinished = true;
4367 } else if (mLastWin != null) {
4368 // If the new window is above the window we are
4369 // waiting on, then stop waiting and let key dispatching
4370 // start on the new guy.
4371 if (DEBUG_INPUT) Log.v(
4372 TAG, "Last win layer=" + mLastWin.mLayer
4373 + ", new win layer=" + newWindow.mLayer);
4374 if (newWindow.mLayer >= mLastWin.mLayer) {
4375 if (!mLastWin.canReceiveKeys()) {
4376 mLastWin.mToken.paused = false;
4377 doFinishedKeyLocked(true); // does a notifyAll()
4378 doNotify = false;
4379 }
4380 } else {
4381 // the new window is lower; no need to wake key waiters
4382 doNotify = false;
4383 }
4384 }
4385
4386 if (doNotify) {
4387 notifyAll();
4388 }
4389 }
4390 }
4391
4392 void pauseDispatchingLocked(WindowToken token) {
4393 synchronized (this)
4394 {
4395 if (DEBUG_INPUT) Log.v(TAG, "Pausing WindowToken " + token);
4396 token.paused = true;
4397
4398 /*
4399 if (mLastWin != null && !mFinished && mLastWin.mBaseLayer <= layer) {
4400 mPaused = true;
4401 } else {
4402 if (mLastWin == null) {
4403 if (Config.LOGI) Log.i(
4404 TAG, "Key dispatching not paused: no last window.");
4405 } else if (mFinished) {
4406 if (Config.LOGI) Log.i(
4407 TAG, "Key dispatching not paused: finished last key.");
4408 } else {
4409 if (Config.LOGI) Log.i(
4410 TAG, "Key dispatching not paused: window in higher layer.");
4411 }
4412 }
4413 */
4414 }
4415 }
4416
4417 void resumeDispatchingLocked(WindowToken token) {
4418 synchronized (this) {
4419 if (token.paused) {
4420 if (DEBUG_INPUT) Log.v(
4421 TAG, "Resuming WindowToken " + token
4422 + ", last=" + mLastBinder
4423 + " (token=" + (mLastWin != null ? mLastWin.mToken : null)
4424 + "), finished=" + mFinished + ", paused="
4425 + token.paused);
4426 token.paused = false;
4427 if (mLastWin != null && mLastWin.mToken == token && mFinished) {
4428 doFinishedKeyLocked(true);
4429 } else {
4430 notifyAll();
4431 }
4432 }
4433 }
4434 }
4435
4436 void setEventDispatchingLocked(boolean enabled) {
4437 synchronized (this) {
4438 mEventDispatching = enabled;
4439 notifyAll();
4440 }
4441 }
4442
4443 void appSwitchComing() {
4444 synchronized (this) {
4445 // Don't wait for more than .5 seconds for app to finish
4446 // processing the pending events.
4447 long now = SystemClock.uptimeMillis() + 500;
4448 if (DEBUG_INPUT) Log.v(TAG, "appSwitchComing: " + now);
4449 if (mTimeToSwitch == 0 || now < mTimeToSwitch) {
4450 mTimeToSwitch = now;
4451 }
4452 notifyAll();
4453 }
4454 }
4455
4456 private final void doFinishedKeyLocked(boolean doRecycle) {
4457 if (mLastWin != null) {
4458 releasePendingPointerLocked(mLastWin.mSession);
4459 releasePendingTrackballLocked(mLastWin.mSession);
4460 }
4461
4462 if (mLastWin == null || !mLastWin.mToken.paused
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08004463 || !mLastWin.isVisibleLw()) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004464 // If the current window has been paused, we aren't -really-
4465 // finished... so let the waiters still wait.
4466 mLastWin = null;
4467 mLastBinder = null;
4468 }
4469 mFinished = true;
4470 notifyAll();
4471 }
4472 }
4473
4474 private class KeyQ extends KeyInputQueue
4475 implements KeyInputQueue.FilterCallback {
4476 PowerManager.WakeLock mHoldingScreen;
4477
4478 KeyQ() {
4479 super(mContext);
4480 PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
4481 mHoldingScreen = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
4482 | PowerManager.ON_AFTER_RELEASE, "KEEP_SCREEN_ON_FLAG");
4483 mHoldingScreen.setReferenceCounted(false);
4484 }
4485
4486 @Override
4487 boolean preprocessEvent(InputDevice device, RawInputEvent event) {
4488 if (mPolicy.preprocessInputEventTq(event)) {
4489 return true;
4490 }
4491
4492 switch (event.type) {
4493 case RawInputEvent.EV_KEY: {
4494 // XXX begin hack
4495 if (DEBUG) {
4496 if (event.keycode == KeyEvent.KEYCODE_G) {
4497 if (event.value != 0) {
4498 // G down
4499 mPolicy.screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
4500 }
4501 return false;
4502 }
4503 if (event.keycode == KeyEvent.KEYCODE_D) {
4504 if (event.value != 0) {
4505 //dump();
4506 }
4507 return false;
4508 }
4509 }
4510 // XXX end hack
4511
4512 boolean screenIsOff = !mPowerManager.screenIsOn();
4513 boolean screenIsDim = !mPowerManager.screenIsBright();
4514 int actions = mPolicy.interceptKeyTq(event, !screenIsOff);
4515
4516 if ((actions & WindowManagerPolicy.ACTION_GO_TO_SLEEP) != 0) {
4517 mPowerManager.goToSleep(event.when);
4518 }
4519
4520 if (screenIsOff) {
4521 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
4522 }
4523 if (screenIsDim) {
4524 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
4525 }
4526 if ((actions & WindowManagerPolicy.ACTION_POKE_USER_ACTIVITY) != 0) {
4527 mPowerManager.userActivity(event.when, false,
4528 LocalPowerManager.BUTTON_EVENT);
4529 }
4530
4531 if ((actions & WindowManagerPolicy.ACTION_PASS_TO_USER) != 0) {
4532 if (event.value != 0 && mPolicy.isAppSwitchKeyTqTiLwLi(event.keycode)) {
4533 filterQueue(this);
4534 mKeyWaiter.appSwitchComing();
4535 }
4536 return true;
4537 } else {
4538 return false;
4539 }
4540 }
4541
4542 case RawInputEvent.EV_REL: {
4543 boolean screenIsOff = !mPowerManager.screenIsOn();
4544 boolean screenIsDim = !mPowerManager.screenIsBright();
4545 if (screenIsOff) {
4546 if (!mPolicy.isWakeRelMovementTq(event.deviceId,
4547 device.classes, event)) {
4548 //Log.i(TAG, "dropping because screenIsOff and !isWakeKey");
4549 return false;
4550 }
4551 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
4552 }
4553 if (screenIsDim) {
4554 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
4555 }
4556 return true;
4557 }
4558
4559 case RawInputEvent.EV_ABS: {
4560 boolean screenIsOff = !mPowerManager.screenIsOn();
4561 boolean screenIsDim = !mPowerManager.screenIsBright();
4562 if (screenIsOff) {
4563 if (!mPolicy.isWakeAbsMovementTq(event.deviceId,
4564 device.classes, event)) {
4565 //Log.i(TAG, "dropping because screenIsOff and !isWakeKey");
4566 return false;
4567 }
4568 event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
4569 }
4570 if (screenIsDim) {
4571 event.flags |= WindowManagerPolicy.FLAG_BRIGHT_HERE;
4572 }
4573 return true;
4574 }
4575
4576 default:
4577 return true;
4578 }
4579 }
4580
4581 public int filterEvent(QueuedEvent ev) {
4582 switch (ev.classType) {
4583 case RawInputEvent.CLASS_KEYBOARD:
4584 KeyEvent ke = (KeyEvent)ev.event;
4585 if (mPolicy.isMovementKeyTi(ke.getKeyCode())) {
4586 Log.w(TAG, "Dropping movement key during app switch: "
4587 + ke.getKeyCode() + ", action=" + ke.getAction());
4588 return FILTER_REMOVE;
4589 }
4590 return FILTER_ABORT;
4591 default:
4592 return FILTER_KEEP;
4593 }
4594 }
4595
4596 /**
4597 * Must be called with the main window manager lock held.
4598 */
4599 void setHoldScreenLocked(boolean holding) {
4600 boolean state = mHoldingScreen.isHeld();
4601 if (holding != state) {
4602 if (holding) {
4603 mHoldingScreen.acquire();
4604 } else {
4605 long curTime = SystemClock.uptimeMillis();
4606 mPowerManager.userActivity(curTime, false, LocalPowerManager.OTHER_EVENT);
4607 mHoldingScreen.release();
4608 }
4609 }
4610 }
4611 };
4612
4613 public void systemReady() {
4614 mPolicy.systemReady();
4615 }
4616
4617 private final class InputDispatcherThread extends Thread {
4618 // Time to wait when there is nothing to do: 9999 seconds.
4619 static final int LONG_WAIT=9999*1000;
4620
4621 public InputDispatcherThread() {
4622 super("InputDispatcher");
4623 }
4624
4625 @Override
4626 public void run() {
4627 while (true) {
4628 try {
4629 process();
4630 } catch (Exception e) {
4631 Log.e(TAG, "Exception in input dispatcher", e);
4632 }
4633 }
4634 }
4635
4636 private void process() {
4637 android.os.Process.setThreadPriority(
4638 android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY);
4639
4640 // The last key event we saw
4641 KeyEvent lastKey = null;
4642
4643 // Last keydown time for auto-repeating keys
4644 long lastKeyTime = SystemClock.uptimeMillis();
4645 long nextKeyTime = lastKeyTime+LONG_WAIT;
4646
4647 // How many successive repeats we generated
4648 int keyRepeatCount = 0;
4649
4650 // Need to report that configuration has changed?
4651 boolean configChanged = false;
4652
4653 while (true) {
4654 long curTime = SystemClock.uptimeMillis();
4655
4656 if (DEBUG_INPUT) Log.v(
4657 TAG, "Waiting for next key: now=" + curTime
4658 + ", repeat @ " + nextKeyTime);
4659
4660 // Retrieve next event, waiting only as long as the next
4661 // repeat timeout. If the configuration has changed, then
4662 // don't wait at all -- we'll report the change as soon as
4663 // we have processed all events.
4664 QueuedEvent ev = mQueue.getEvent(
4665 (int)((!configChanged && curTime < nextKeyTime)
4666 ? (nextKeyTime-curTime) : 0));
4667
4668 if (DEBUG_INPUT && ev != null) Log.v(
4669 TAG, "Event: type=" + ev.classType + " data=" + ev.event);
4670
4671 try {
4672 if (ev != null) {
4673 curTime = ev.when;
4674 int eventType;
4675 if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
4676 eventType = eventType((MotionEvent)ev.event);
4677 } else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
4678 ev.classType == RawInputEvent.CLASS_TRACKBALL) {
4679 eventType = LocalPowerManager.BUTTON_EVENT;
4680 } else {
4681 eventType = LocalPowerManager.OTHER_EVENT;
4682 }
4683 mPowerManager.userActivity(curTime, false, eventType);
4684 switch (ev.classType) {
4685 case RawInputEvent.CLASS_KEYBOARD:
4686 KeyEvent ke = (KeyEvent)ev.event;
4687 if (ke.isDown()) {
4688 lastKey = ke;
4689 keyRepeatCount = 0;
4690 lastKeyTime = curTime;
4691 nextKeyTime = lastKeyTime
4692 + KEY_REPEAT_FIRST_DELAY;
4693 if (DEBUG_INPUT) Log.v(
4694 TAG, "Received key down: first repeat @ "
4695 + nextKeyTime);
4696 } else {
4697 lastKey = null;
4698 // Arbitrary long timeout.
4699 lastKeyTime = curTime;
4700 nextKeyTime = curTime + LONG_WAIT;
4701 if (DEBUG_INPUT) Log.v(
4702 TAG, "Received key up: ignore repeat @ "
4703 + nextKeyTime);
4704 }
4705 dispatchKey((KeyEvent)ev.event, 0, 0);
4706 mQueue.recycleEvent(ev);
4707 break;
4708 case RawInputEvent.CLASS_TOUCHSCREEN:
4709 //Log.i(TAG, "Read next event " + ev);
4710 dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
4711 break;
4712 case RawInputEvent.CLASS_TRACKBALL:
4713 dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
4714 break;
4715 case RawInputEvent.CLASS_CONFIGURATION_CHANGED:
4716 configChanged = true;
4717 break;
4718 default:
4719 mQueue.recycleEvent(ev);
4720 break;
4721 }
4722
4723 } else if (configChanged) {
4724 configChanged = false;
4725 sendNewConfiguration();
4726
4727 } else if (lastKey != null) {
4728 curTime = SystemClock.uptimeMillis();
4729
4730 // Timeout occurred while key was down. If it is at or
4731 // past the key repeat time, dispatch the repeat.
4732 if (DEBUG_INPUT) Log.v(
4733 TAG, "Key timeout: repeat=" + nextKeyTime
4734 + ", now=" + curTime);
4735 if (curTime < nextKeyTime) {
4736 continue;
4737 }
4738
4739 lastKeyTime = nextKeyTime;
4740 nextKeyTime = nextKeyTime + KEY_REPEAT_DELAY;
4741 keyRepeatCount++;
4742 if (DEBUG_INPUT) Log.v(
4743 TAG, "Key repeat: count=" + keyRepeatCount
4744 + ", next @ " + nextKeyTime);
4745 dispatchKey(new KeyEvent(lastKey, curTime, keyRepeatCount), 0, 0);
4746
4747 } else {
4748 curTime = SystemClock.uptimeMillis();
4749
4750 lastKeyTime = curTime;
4751 nextKeyTime = curTime + LONG_WAIT;
4752 }
4753
4754 } catch (Exception e) {
4755 Log.e(TAG,
4756 "Input thread received uncaught exception: " + e, e);
4757 }
4758 }
4759 }
4760 }
4761
4762 // -------------------------------------------------------------
4763 // Client Session State
4764 // -------------------------------------------------------------
4765
4766 private final class Session extends IWindowSession.Stub
4767 implements IBinder.DeathRecipient {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004768 final IInputMethodClient mClient;
4769 final IInputContext mInputContext;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004770 final int mUid;
4771 final int mPid;
4772 SurfaceSession mSurfaceSession;
4773 int mNumWindow = 0;
4774 boolean mClientDead = false;
4775
4776 /**
4777 * Current pointer move event being dispatched to client window... must
4778 * hold key lock to access.
4779 */
4780 QueuedEvent mPendingPointerMove;
4781 WindowState mPendingPointerWindow;
4782
4783 /**
4784 * Current trackball move event being dispatched to client window... must
4785 * hold key lock to access.
4786 */
4787 QueuedEvent mPendingTrackballMove;
4788 WindowState mPendingTrackballWindow;
4789
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004790 public Session(IInputMethodClient client, IInputContext inputContext) {
4791 mClient = client;
4792 mInputContext = inputContext;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004793 mUid = Binder.getCallingUid();
4794 mPid = Binder.getCallingPid();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004795 synchronized (mWindowMap) {
4796 if (mInputMethodManager == null && mHaveInputMethods) {
4797 IBinder b = ServiceManager.getService(
4798 Context.INPUT_METHOD_SERVICE);
4799 mInputMethodManager = IInputMethodManager.Stub.asInterface(b);
4800 }
4801 }
4802 long ident = Binder.clearCallingIdentity();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004803 try {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004804 // Note: it is safe to call in to the input method manager
4805 // here because we are not holding our lock.
4806 if (mInputMethodManager != null) {
4807 mInputMethodManager.addClient(client, inputContext,
4808 mUid, mPid);
4809 } else {
4810 client.setUsingInputMethod(false);
4811 }
4812 client.asBinder().linkToDeath(this, 0);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004813 } catch (RemoteException e) {
4814 // The caller has died, so we can just forget about this.
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004815 try {
4816 if (mInputMethodManager != null) {
4817 mInputMethodManager.removeClient(client);
4818 }
4819 } catch (RemoteException ee) {
4820 }
4821 } finally {
4822 Binder.restoreCallingIdentity(ident);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004823 }
4824 }
4825
4826 @Override
4827 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
4828 throws RemoteException {
4829 try {
4830 return super.onTransact(code, data, reply, flags);
4831 } catch (RuntimeException e) {
4832 // Log all 'real' exceptions thrown to the caller
4833 if (!(e instanceof SecurityException)) {
4834 Log.e(TAG, "Window Session Crash", e);
4835 }
4836 throw e;
4837 }
4838 }
4839
4840 public void binderDied() {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004841 // Note: it is safe to call in to the input method manager
4842 // here because we are not holding our lock.
4843 try {
4844 if (mInputMethodManager != null) {
4845 mInputMethodManager.removeClient(mClient);
4846 }
4847 } catch (RemoteException e) {
4848 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004849 synchronized(mWindowMap) {
4850 mClientDead = true;
4851 killSessionLocked();
4852 }
4853 }
4854
4855 public int add(IWindow window, WindowManager.LayoutParams attrs,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004856 int viewVisibility, Rect outContentInsets) {
4857 return addWindow(this, window, attrs, viewVisibility, outContentInsets);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004858 }
4859
4860 public void remove(IWindow window) {
4861 removeWindow(this, window);
4862 }
4863
4864 public int relayout(IWindow window, WindowManager.LayoutParams attrs,
4865 int requestedWidth, int requestedHeight, int viewFlags,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004866 boolean insetsPending, Rect outFrame, Rect outContentInsets,
4867 Rect outVisibleInsets, Surface outSurface) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004868 return relayoutWindow(this, window, attrs,
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004869 requestedWidth, requestedHeight, viewFlags, insetsPending,
4870 outFrame, outContentInsets, outVisibleInsets, outSurface);
4871 }
4872
4873 public void setTransparentRegion(IWindow window, Region region) {
4874 setTransparentRegionWindow(this, window, region);
4875 }
4876
4877 public void setInsets(IWindow window, int touchableInsets,
4878 Rect contentInsets, Rect visibleInsets) {
4879 setInsetsWindow(this, window, touchableInsets, contentInsets,
4880 visibleInsets);
4881 }
4882
4883 public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
4884 getWindowDisplayFrame(this, window, outDisplayFrame);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004885 }
4886
4887 public void finishDrawing(IWindow window) {
4888 if (localLOGV) Log.v(
4889 TAG, "IWindow finishDrawing called for " + window);
4890 finishDrawingWindow(this, window);
4891 }
4892
4893 public void finishKey(IWindow window) {
4894 if (localLOGV) Log.v(
4895 TAG, "IWindow finishKey called for " + window);
4896 mKeyWaiter.finishedKey(this, window, false,
4897 KeyWaiter.RETURN_NOTHING);
4898 }
4899
4900 public MotionEvent getPendingPointerMove(IWindow window) {
4901 if (localLOGV) Log.v(
4902 TAG, "IWindow getPendingMotionEvent called for " + window);
4903 return mKeyWaiter.finishedKey(this, window, false,
4904 KeyWaiter.RETURN_PENDING_POINTER);
4905 }
4906
4907 public MotionEvent getPendingTrackballMove(IWindow window) {
4908 if (localLOGV) Log.v(
4909 TAG, "IWindow getPendingMotionEvent called for " + window);
4910 return mKeyWaiter.finishedKey(this, window, false,
4911 KeyWaiter.RETURN_PENDING_TRACKBALL);
4912 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004913
4914 public void setInTouchMode(boolean mode) {
4915 synchronized(mWindowMap) {
4916 mInTouchMode = mode;
4917 }
4918 }
4919
4920 public boolean getInTouchMode() {
4921 synchronized(mWindowMap) {
4922 return mInTouchMode;
4923 }
4924 }
4925
4926 void windowAddedLocked() {
4927 if (mSurfaceSession == null) {
4928 if (localLOGV) Log.v(
4929 TAG, "First window added to " + this + ", creating SurfaceSession");
4930 mSurfaceSession = new SurfaceSession();
4931 mSessions.add(this);
4932 }
4933 mNumWindow++;
4934 }
4935
4936 void windowRemovedLocked() {
4937 mNumWindow--;
4938 killSessionLocked();
4939 }
4940
4941 void killSessionLocked() {
4942 if (mNumWindow <= 0 && mClientDead) {
4943 mSessions.remove(this);
4944 if (mSurfaceSession != null) {
4945 if (localLOGV) Log.v(
4946 TAG, "Last window removed from " + this
4947 + ", destroying " + mSurfaceSession);
4948 try {
4949 mSurfaceSession.kill();
4950 } catch (Exception e) {
4951 Log.w(TAG, "Exception thrown when killing surface session "
4952 + mSurfaceSession + " in session " + this
4953 + ": " + e.toString());
4954 }
4955 mSurfaceSession = null;
4956 }
4957 }
4958 }
4959
4960 void dump(PrintWriter pw, String prefix) {
4961 pw.println(prefix + this);
4962 pw.println(prefix + "mNumWindow=" + mNumWindow
4963 + " mClientDead=" + mClientDead
4964 + " mSurfaceSession=" + mSurfaceSession);
4965 pw.println(prefix + "mPendingPointerWindow=" + mPendingPointerWindow
4966 + " mPendingPointerMove=" + mPendingPointerMove);
4967 pw.println(prefix + "mPendingTrackballWindow=" + mPendingTrackballWindow
4968 + " mPendingTrackballMove=" + mPendingTrackballMove);
4969 }
4970
4971 @Override
4972 public String toString() {
4973 return "Session{"
4974 + Integer.toHexString(System.identityHashCode(this)) + "}";
4975 }
4976 }
4977
4978 // -------------------------------------------------------------
4979 // Client Window State
4980 // -------------------------------------------------------------
4981
4982 private final class WindowState implements WindowManagerPolicy.WindowState {
4983 final Session mSession;
4984 final IWindow mClient;
4985 WindowToken mToken;
4986 AppWindowToken mAppToken;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004987 AppWindowToken mTargetAppToken;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004988 final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
4989 final DeathRecipient mDeathRecipient;
4990 final WindowState mAttachedWindow;
4991 final ArrayList mChildWindows = new ArrayList();
4992 final int mBaseLayer;
4993 final int mSubLayer;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08004994 final boolean mLayoutAttached;
The Android Open Source Project9266c5582009-01-15 16:12:10 -08004995 final boolean mIsImWindow;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004996 int mViewVisibility;
4997 boolean mPolicyVisibility = true;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08004998 boolean mPolicyVisibilityAfterAnim = true;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07004999 boolean mAppFreezing;
5000 Surface mSurface;
5001 boolean mAttachedHidden; // is our parent window hidden?
5002 boolean mLastHidden; // was this window last hidden?
5003 int mRequestedWidth;
5004 int mRequestedHeight;
5005 int mLastRequestedWidth;
5006 int mLastRequestedHeight;
5007 int mReqXPos;
5008 int mReqYPos;
5009 int mLayer;
5010 int mAnimLayer;
5011 int mLastLayer;
5012 boolean mHaveFrame;
5013
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005014 WindowState mNextOutsideTouch;
5015
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005016 // Actual frame shown on-screen (may be modified by animation)
5017 final Rect mShownFrame = new Rect();
5018 final Rect mLastShownFrame = new Rect();
5019
5020 /**
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005021 * Insets that determine the actually visible area
5022 */
5023 final Rect mVisibleInsets = new Rect();
5024 final Rect mLastVisibleInsets = new Rect();
5025 boolean mVisibleInsetsChanged;
5026
5027 /**
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005028 * Insets that are covered by system windows
5029 */
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005030 final Rect mContentInsets = new Rect();
5031 final Rect mLastContentInsets = new Rect();
5032 boolean mContentInsetsChanged;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005033
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005034 /**
5035 * Set to true if we are waiting for this window to receive its
5036 * given internal insets before laying out other windows based on it.
5037 */
5038 boolean mGivenInsetsPending;
5039
5040 /**
5041 * These are the content insets that were given during layout for
5042 * this window, to be applied to windows behind it.
5043 */
5044 final Rect mGivenContentInsets = new Rect();
5045
5046 /**
5047 * These are the visible insets that were given during layout for
5048 * this window, to be applied to windows behind it.
5049 */
5050 final Rect mGivenVisibleInsets = new Rect();
5051
5052 /**
5053 * Flag indicating whether the touchable region should be adjusted by
5054 * the visible insets; if false the area outside the visible insets is
5055 * NOT touchable, so we must use those to adjust the frame during hit
5056 * tests.
5057 */
5058 int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
5059
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005060 // Current transformation being applied.
5061 float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
5062 float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
5063 float mHScale=1, mVScale=1;
5064 float mLastHScale=1, mLastVScale=1;
5065 final Matrix mTmpMatrix = new Matrix();
5066
5067 // "Real" frame that the application sees.
5068 final Rect mFrame = new Rect();
5069 final Rect mLastFrame = new Rect();
5070
5071 final Rect mContainingFrame = new Rect();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005072 final Rect mDisplayFrame = new Rect();
5073 final Rect mContentFrame = new Rect();
5074 final Rect mVisibleFrame = new Rect();
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005075
5076 float mShownAlpha = 1;
5077 float mAlpha = 1;
5078 float mLastAlpha = 1;
5079
5080 // Set to true if, when the window gets displayed, it should perform
5081 // an enter animation.
5082 boolean mEnterAnimationPending;
5083
5084 // Currently running animation.
5085 boolean mAnimating;
5086 Animation mAnimation;
5087 boolean mAnimationIsEntrance;
5088 boolean mHasTransformation;
5089 final Transformation mTransformation = new Transformation();
5090
5091 // This is set after IWindowSession.relayout() has been called at
5092 // least once for the window. It allows us to detect the situation
5093 // where we don't yet have a surface, but should have one soon, so
5094 // we can give the window focus before waiting for the relayout.
5095 boolean mRelayoutCalled;
5096
5097 // This is set after the Surface has been created but before the
5098 // window has been drawn. During this time the surface is hidden.
5099 boolean mDrawPending;
5100
5101 // This is set after the window has finished drawing for the first
5102 // time but before its surface is shown. The surface will be
5103 // displayed when the next layout is run.
5104 boolean mCommitDrawPending;
5105
5106 // This is set during the time after the window's drawing has been
5107 // committed, and before its surface is actually shown. It is used
5108 // to delay showing the surface until all windows in a token are ready
5109 // to be shown.
5110 boolean mReadyToShow;
5111
5112 // Set when the window has been shown in the screen the first time.
5113 boolean mHasDrawn;
5114
5115 // Currently running an exit animation?
5116 boolean mExiting;
5117
5118 // Currently on the mDestroySurface list?
5119 boolean mDestroying;
5120
5121 // Completely remove from window manager after exit animation?
5122 boolean mRemoveOnExit;
5123
5124 // Set when the orientation is changing and this window has not yet
5125 // been updated for the new orientation.
5126 boolean mOrientationChanging;
5127
5128 WindowState(Session s, IWindow c, WindowToken token,
5129 WindowState attachedWindow, WindowManager.LayoutParams a,
5130 int viewVisibility) {
5131 mSession = s;
5132 mClient = c;
5133 mToken = token;
5134 mAttrs.copyFrom(a);
5135 mViewVisibility = viewVisibility;
5136 DeathRecipient deathRecipient = new DeathRecipient();
5137 mAlpha = a.alpha;
5138 if (localLOGV) Log.v(
5139 TAG, "Window " + this + " client=" + c.asBinder()
5140 + " token=" + token + " (" + mAttrs.token + ")");
5141 try {
5142 c.asBinder().linkToDeath(deathRecipient, 0);
5143 } catch (RemoteException e) {
5144 mDeathRecipient = null;
5145 mAttachedWindow = null;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005146 mLayoutAttached = false;
The Android Open Source Project9266c5582009-01-15 16:12:10 -08005147 mIsImWindow = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005148 mBaseLayer = 0;
5149 mSubLayer = 0;
5150 return;
5151 }
5152 mDeathRecipient = deathRecipient;
5153
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005154 if ((mAttrs.type >= FIRST_SUB_WINDOW &&
5155 mAttrs.type <= LAST_SUB_WINDOW)) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005156 // The multiplier here is to reserve space for multiple
5157 // windows in the same type layer.
5158 mBaseLayer = mPolicy.windowTypeToLayerLw(
5159 attachedWindow.mAttrs.type) * TYPE_LAYER_MULTIPLIER
5160 + TYPE_LAYER_OFFSET;
5161 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
5162 mAttachedWindow = attachedWindow;
5163 mAttachedWindow.mChildWindows.add(this);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005164 mLayoutAttached = mAttrs.type !=
5165 WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
The Android Open Source Project9266c5582009-01-15 16:12:10 -08005166 mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
5167 || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005168 } else {
5169 // The multiplier here is to reserve space for multiple
5170 // windows in the same type layer.
5171 mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
5172 * TYPE_LAYER_MULTIPLIER
5173 + TYPE_LAYER_OFFSET;
5174 mSubLayer = 0;
5175 mAttachedWindow = null;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005176 mLayoutAttached = false;
The Android Open Source Project9266c5582009-01-15 16:12:10 -08005177 mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
5178 || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005179 }
5180
5181 WindowState appWin = this;
5182 while (appWin.mAttachedWindow != null) {
5183 appWin = mAttachedWindow;
5184 }
5185 WindowToken appToken = appWin.mToken;
5186 while (appToken.appWindowToken == null) {
5187 WindowToken parent = mTokenMap.get(appToken.token);
5188 if (parent == null || appToken == parent) {
5189 break;
5190 }
5191 appToken = parent;
5192 }
5193 mAppToken = appToken.appWindowToken;
5194
5195 mSurface = null;
5196 mRequestedWidth = 0;
5197 mRequestedHeight = 0;
5198 mLastRequestedWidth = 0;
5199 mLastRequestedHeight = 0;
5200 mReqXPos = 0;
5201 mReqYPos = 0;
5202 mLayer = 0;
5203 mAnimLayer = 0;
5204 mLastLayer = 0;
5205 }
5206
5207 void attach() {
5208 if (localLOGV) Log.v(
5209 TAG, "Attaching " + this + " token=" + mToken
5210 + ", list=" + mToken.windows);
5211 mSession.windowAddedLocked();
5212 }
5213
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005214 public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005215 mHaveFrame = true;
5216
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005217 final int pw = pf.right-pf.left;
5218 final int ph = pf.bottom-pf.top;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005219
5220 int w,h;
5221 if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) {
5222 w = mAttrs.width < 0 ? pw : mAttrs.width;
5223 h = mAttrs.height< 0 ? ph : mAttrs.height;
5224 } else {
5225 w = mAttrs.width == mAttrs.FILL_PARENT ? pw : mRequestedWidth;
5226 h = mAttrs.height== mAttrs.FILL_PARENT ? ph : mRequestedHeight;
5227 }
5228
5229 final Rect container = mContainingFrame;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005230 container.set(pf);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005231
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005232 final Rect display = mDisplayFrame;
5233 display.set(df);
5234
5235 final Rect content = mContentFrame;
5236 content.set(cf);
5237
5238 final Rect visible = mVisibleFrame;
5239 visible.set(vf);
5240
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005241 final Rect frame = mFrame;
5242
5243 //System.out.println("In: w=" + w + " h=" + h + " container=" +
5244 // container + " x=" + mAttrs.x + " y=" + mAttrs.y);
5245
5246 Gravity.apply(mAttrs.gravity, w, h, container,
5247 (int) (mAttrs.x + mAttrs.horizontalMargin * pw),
5248 (int) (mAttrs.y + mAttrs.verticalMargin * ph), frame);
5249
5250 //System.out.println("Out: " + mFrame);
5251
5252 // Now make sure the window fits in the overall display.
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005253 Gravity.applyDisplay(mAttrs.gravity, df, frame);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005254
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005255 // Make sure the content and visible frames are inside of the
5256 // final window frame.
5257 if (content.left < frame.left) content.left = frame.left;
5258 if (content.top < frame.top) content.top = frame.top;
5259 if (content.right > frame.right) content.right = frame.right;
5260 if (content.bottom > frame.bottom) content.bottom = frame.bottom;
5261 if (visible.left < frame.left) visible.left = frame.left;
5262 if (visible.top < frame.top) visible.top = frame.top;
5263 if (visible.right > frame.right) visible.right = frame.right;
5264 if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
5265
5266 final Rect contentInsets = mContentInsets;
5267 contentInsets.left = content.left-frame.left;
5268 contentInsets.top = content.top-frame.top;
5269 contentInsets.right = frame.right-content.right;
5270 contentInsets.bottom = frame.bottom-content.bottom;
5271
5272 final Rect visibleInsets = mVisibleInsets;
5273 visibleInsets.left = visible.left-frame.left;
5274 visibleInsets.top = visible.top-frame.top;
5275 visibleInsets.right = frame.right-visible.right;
5276 visibleInsets.bottom = frame.bottom-visible.bottom;
5277
5278 if (localLOGV) {
5279 //if ("com.google.android.youtube".equals(mAttrs.packageName)
5280 // && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
5281 Log.v(TAG, "Resolving (mRequestedWidth="
5282 + mRequestedWidth + ", mRequestedheight="
5283 + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
5284 + "): frame=" + mFrame.toShortString()
5285 + " ci=" + contentInsets.toShortString()
5286 + " vi=" + visibleInsets.toShortString());
5287 //}
5288 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005289 }
5290
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005291 public Rect getFrameLw() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005292 return mFrame;
5293 }
5294
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005295 public Rect getDisplayFrameLw() {
5296 return mDisplayFrame;
5297 }
5298
5299 public Rect getContentFrameLw() {
5300 return mContentFrame;
5301 }
5302
5303 public Rect getVisibleFrameLw() {
5304 return mVisibleFrame;
5305 }
5306
5307 public boolean getGivenInsetsPendingLw() {
5308 return mGivenInsetsPending;
5309 }
5310
5311 public Rect getGivenContentInsetsLw() {
5312 return mGivenContentInsets;
5313 }
5314
5315 public Rect getGivenVisibleInsetsLw() {
5316 return mGivenVisibleInsets;
5317 }
5318
5319 public WindowManager.LayoutParams getAttrs() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005320 return mAttrs;
5321 }
5322
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005323 public int getSurfaceLayer() {
5324 return mLayer;
5325 }
5326
5327 public IApplicationToken getAppToken() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005328 return mAppToken != null ? mAppToken.appToken : null;
5329 }
5330
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005331 public boolean hasAppShownWindows() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005332 return mAppToken != null ? mAppToken.firstWindowDrawn : false;
5333 }
5334
5335 public boolean hasAppStartingIcon() {
5336 return mAppToken != null ? (mAppToken.startingData != null) : false;
5337 }
5338
5339 public WindowManagerPolicy.WindowState getAppStartingWindow() {
5340 return mAppToken != null ? mAppToken.startingWindow : null;
5341 }
5342
5343 public void setAnimation(Animation anim) {
5344 if (localLOGV) Log.v(
5345 TAG, "Setting animation in " + this + ": " + anim);
5346 mAnimating = false;
5347 mAnimation = anim;
5348 mAnimation.restrictDuration(MAX_ANIMATION_DURATION);
5349 mAnimation.scaleCurrentDuration(mWindowAnimationScale);
5350 }
5351
5352 public void clearAnimation() {
5353 if (mAnimation != null) {
5354 mAnimating = true;
5355 mAnimation = null;
5356 }
5357 }
5358
5359 Surface createSurfaceLocked() {
5360 if (mSurface == null) {
5361 mDrawPending = true;
5362 mCommitDrawPending = false;
5363 mReadyToShow = false;
5364 if (mAppToken != null) {
5365 mAppToken.allDrawn = false;
5366 }
5367
5368 int flags = 0;
5369 if (mAttrs.memoryType == MEMORY_TYPE_HARDWARE) {
5370 flags |= Surface.HARDWARE;
5371 } else if (mAttrs.memoryType == MEMORY_TYPE_GPU) {
5372 flags |= Surface.GPU;
5373 } else if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
5374 flags |= Surface.PUSH_BUFFERS;
5375 }
5376
5377 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
5378 flags |= Surface.SECURE;
5379 }
5380 if (DEBUG_VISIBILITY) Log.v(
5381 TAG, "Creating surface in session "
5382 + mSession.mSurfaceSession + " window " + this
5383 + " w=" + mFrame.width()
5384 + " h=" + mFrame.height() + " format="
5385 + mAttrs.format + " flags=" + flags);
5386
5387 int w = mFrame.width();
5388 int h = mFrame.height();
5389 if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
5390 // for a scaled surface, we always want the requested
5391 // size.
5392 w = mRequestedWidth;
5393 h = mRequestedHeight;
5394 }
5395
5396 try {
5397 mSurface = new Surface(
5398 mSession.mSurfaceSession, mSession.mPid,
5399 0, w, h, mAttrs.format, flags);
5400 } catch (Surface.OutOfResourcesException e) {
5401 Log.w(TAG, "OutOfResourcesException creating surface");
5402 reclaimSomeSurfaceMemoryLocked(this, "create");
5403 return null;
5404 } catch (Exception e) {
5405 Log.e(TAG, "Exception creating surface", e);
5406 return null;
5407 }
5408
5409 if (localLOGV) Log.v(
5410 TAG, "Got surface: " + mSurface
5411 + ", set left=" + mFrame.left + " top=" + mFrame.top
5412 + ", animLayer=" + mAnimLayer);
5413 if (SHOW_TRANSACTIONS) {
5414 Log.i(TAG, ">>> OPEN TRANSACTION");
5415 Log.i(TAG, " SURFACE " + mSurface + ": CREATE ("
5416 + mAttrs.getTitle() + ") pos=(" +
5417 mFrame.left + "," + mFrame.top + ") (" +
5418 mFrame.width() + "x" + mFrame.height() + "), layer=" +
5419 mAnimLayer + " HIDE");
5420 }
5421 Surface.openTransaction();
5422 try {
5423 try {
5424 mSurface.setPosition(mFrame.left, mFrame.top);
5425 mSurface.setLayer(mAnimLayer);
5426 mSurface.hide();
5427 if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
5428 mSurface.setFlags(Surface.SURFACE_DITHER,
5429 Surface.SURFACE_DITHER);
5430 }
5431 } catch (RuntimeException e) {
5432 Log.w(TAG, "Error creating surface in " + w, e);
5433 reclaimSomeSurfaceMemoryLocked(this, "create-init");
5434 }
5435 mLastHidden = true;
5436 } finally {
5437 if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION");
5438 Surface.closeTransaction();
5439 }
5440 if (localLOGV) Log.v(
5441 TAG, "Created surface " + this);
5442 }
5443 return mSurface;
5444 }
5445
5446 void destroySurfaceLocked() {
5447 // Window is no longer on-screen, so can no longer receive
5448 // key events... if we were waiting for it to finish
5449 // handling a key event, the wait is over!
5450 mKeyWaiter.finishedKey(mSession, mClient, true,
5451 KeyWaiter.RETURN_NOTHING);
5452 mKeyWaiter.releasePendingPointerLocked(mSession);
5453 mKeyWaiter.releasePendingTrackballLocked(mSession);
5454
5455 if (mAppToken != null && this == mAppToken.startingWindow) {
5456 mAppToken.startingDisplayed = false;
5457 }
5458
5459 if (localLOGV) Log.v(
5460 TAG, "Window " + this
5461 + " destroying surface " + mSurface + ", session " + mSession);
5462 if (mSurface != null) {
5463 try {
5464 if (SHOW_TRANSACTIONS) {
5465 RuntimeException ex = new RuntimeException();
5466 ex.fillInStackTrace();
5467 Log.i(TAG, " SURFACE " + mSurface + ": DESTROY ("
5468 + mAttrs.getTitle() + ")", ex);
5469 }
5470 mSurface.clear();
5471 } catch (RuntimeException e) {
5472 Log.w(TAG, "Exception thrown when destroying Window " + this
5473 + " surface " + mSurface + " session " + mSession
5474 + ": " + e.toString());
5475 }
5476 mSurface = null;
5477 mDrawPending = false;
5478 mCommitDrawPending = false;
5479 mReadyToShow = false;
5480
5481 int i = mChildWindows.size();
5482 while (i > 0) {
5483 i--;
5484 WindowState c = (WindowState)mChildWindows.get(i);
5485 c.mAttachedHidden = true;
5486 }
5487 }
5488 }
5489
5490 boolean finishDrawingLocked() {
5491 if (mDrawPending) {
5492 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Log.v(
5493 TAG, "finishDrawingLocked: " + mSurface);
5494 mCommitDrawPending = true;
5495 mDrawPending = false;
5496 return true;
5497 }
5498 return false;
5499 }
5500
5501 // This must be called while inside a transaction.
5502 void commitFinishDrawingLocked(long currentTime) {
5503 //Log.i(TAG, "commitFinishDrawingLocked: " + mSurface);
5504 if (!mCommitDrawPending) {
5505 return;
5506 }
5507 mCommitDrawPending = false;
5508 mReadyToShow = true;
5509 final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
5510 final AppWindowToken atoken = mAppToken;
5511 if (atoken == null || atoken.allDrawn || starting) {
5512 performShowLocked();
5513 }
5514 }
5515
5516 // This must be called while inside a transaction.
5517 boolean performShowLocked() {
5518 if (DEBUG_VISIBILITY) {
5519 RuntimeException e = new RuntimeException();
5520 e.fillInStackTrace();
5521 Log.v(TAG, "performShow on " + this
5522 + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
5523 + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
5524 }
5525 if (mReadyToShow && isReadyForDisplay()) {
5526 if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION) Log.i(
5527 TAG, " SURFACE " + mSurface + ": SHOW (performShowLocked)");
5528 if (DEBUG_VISIBILITY) Log.v(TAG, "Showing " + this
5529 + " during animation: policyVis=" + mPolicyVisibility
5530 + " attHidden=" + mAttachedHidden
5531 + " tok.hiddenRequested="
5532 + (mAppToken != null ? mAppToken.hiddenRequested : false)
5533 + " tok.idden="
5534 + (mAppToken != null ? mAppToken.hidden : false)
5535 + " animating=" + mAnimating
5536 + " tok animating="
5537 + (mAppToken != null ? mAppToken.animating : false));
5538 if (!showSurfaceRobustlyLocked(this)) {
5539 return false;
5540 }
5541 mLastAlpha = -1;
5542 mHasDrawn = true;
5543 mLastHidden = false;
5544 mReadyToShow = false;
5545 enableScreenIfNeededLocked();
5546
5547 applyEnterAnimationLocked(this);
5548
5549 int i = mChildWindows.size();
5550 while (i > 0) {
5551 i--;
5552 WindowState c = (WindowState)mChildWindows.get(i);
5553 if (c.mSurface != null && c.mAttachedHidden) {
5554 c.mAttachedHidden = false;
5555 c.performShowLocked();
5556 }
5557 }
5558
5559 if (mAttrs.type != TYPE_APPLICATION_STARTING
5560 && mAppToken != null) {
5561 mAppToken.firstWindowDrawn = true;
5562 if (mAnimation == null && mAppToken.startingData != null) {
5563 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Finish starting "
5564 + mToken
5565 + ": first real window is shown, no animation");
5566 mFinishedStarting.add(mAppToken);
5567 mH.sendEmptyMessage(H.FINISHED_STARTING);
5568 }
5569 mAppToken.updateReportedVisibilityLocked();
5570 }
5571 }
5572 return true;
5573 }
5574
5575 // This must be called while inside a transaction. Returns true if
5576 // there is more animation to run.
5577 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
5578 if (!mDisplayFrozen) {
5579 // We will run animations as long as the display isn't frozen.
5580
5581 if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
5582 mHasTransformation = true;
5583 if (!mAnimating) {
5584 if (DEBUG_ANIM) Log.v(
5585 TAG, "Starting animation in " + this +
5586 " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
5587 " dw=" + dw + " dh=" + dh + " scale=" + mWindowAnimationScale);
5588 mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
5589 mAnimation.setStartTime(currentTime);
5590 mAnimating = true;
5591 }
5592 mTransformation.clear();
5593 final boolean more = mAnimation.getTransformation(
5594 currentTime, mTransformation);
5595 if (DEBUG_ANIM) Log.v(
5596 TAG, "Stepped animation in " + this +
5597 ": more=" + more + ", xform=" + mTransformation);
5598 if (mAppToken != null && mAppToken.hasTransformation) {
5599 mTransformation.compose(mAppToken.transformation);
5600 }
5601 if (more) {
5602 // we're not done!
5603 return true;
5604 }
5605 if (DEBUG_ANIM) Log.v(
5606 TAG, "Finished animation in " + this +
5607 " @ " + currentTime);
5608 mAnimation = null;
5609 //WindowManagerService.this.dump();
5610 }
5611 if (mAppToken != null && mAppToken.hasTransformation) {
5612 mAnimating = true;
5613 mHasTransformation = true;
5614 mTransformation.set(mAppToken.transformation);
5615 return false;
5616 } else if (mHasTransformation) {
5617 // Little trick to get through the path below to act like
5618 // we have finished an animation.
5619 mAnimating = true;
5620 } else if (isAnimating()) {
5621 mAnimating = true;
5622 }
5623 } else if (mAnimation != null) {
5624 // If the display is frozen, and there is a pending animation,
5625 // clear it and make sure we run the cleanup code.
5626 mAnimating = true;
5627 mAnimation = null;
5628 }
5629
5630 if (!mAnimating) {
5631 return false;
5632 }
5633
5634 if (DEBUG_ANIM) Log.v(
5635 TAG, "Animation done in " + this + ": exiting=" + mExiting
5636 + ", reportedVisible="
5637 + (mAppToken != null ? mAppToken.reportedVisible : false));
5638
5639 mAnimating = false;
5640 mAnimation = null;
5641 mAnimLayer = mLayer;
5642 mHasTransformation = false;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08005643 mPolicyVisibility = mPolicyVisibilityAfterAnim;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005644 mTransformation.clear();
5645 if (mHasDrawn
5646 && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
5647 && mAppToken != null
5648 && mAppToken.firstWindowDrawn
5649 && mAppToken.startingData != null) {
5650 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Finish starting "
5651 + mToken + ": first real window done animating");
5652 mFinishedStarting.add(mAppToken);
5653 mH.sendEmptyMessage(H.FINISHED_STARTING);
5654 }
5655
5656 finishExit();
5657
5658 if (mAppToken != null) {
5659 mAppToken.updateReportedVisibilityLocked();
5660 }
5661
5662 return false;
5663 }
5664
5665 void finishExit() {
5666 if (DEBUG_ANIM) Log.v(
5667 TAG, "finishExit in " + this
5668 + ": exiting=" + mExiting
5669 + " remove=" + mRemoveOnExit
5670 + " windowAnimating=" + isWindowAnimating());
5671
5672 final int N = mChildWindows.size();
5673 for (int i=0; i<N; i++) {
5674 ((WindowState)mChildWindows.get(i)).finishExit();
5675 }
5676
5677 if (!mExiting) {
5678 return;
5679 }
5680
5681 if (isWindowAnimating()) {
5682 return;
5683 }
5684
5685 if (localLOGV) Log.v(
5686 TAG, "Exit animation finished in " + this
5687 + ": remove=" + mRemoveOnExit);
5688 if (mSurface != null) {
5689 mDestroySurface.add(this);
5690 mDestroying = true;
5691 if (SHOW_TRANSACTIONS) Log.i(
5692 TAG, " SURFACE " + mSurface + ": HIDE (finishExit)");
5693 try {
5694 mSurface.hide();
5695 } catch (RuntimeException e) {
5696 Log.w(TAG, "Error hiding surface in " + this, e);
5697 }
5698 mLastHidden = true;
5699 mKeyWaiter.releasePendingPointerLocked(mSession);
5700 }
5701 mExiting = false;
5702 if (mRemoveOnExit) {
5703 mPendingRemove.add(this);
5704 mRemoveOnExit = false;
5705 }
5706 }
5707
5708 boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
5709 if (dsdx < .99999f || dsdx > 1.00001f) return false;
5710 if (dtdy < .99999f || dtdy > 1.00001f) return false;
5711 if (dtdx < -.000001f || dtdx > .000001f) return false;
5712 if (dsdy < -.000001f || dsdy > .000001f) return false;
5713 return true;
5714 }
5715
5716 void computeShownFrameLocked() {
5717 final boolean selfTransformation = mHasTransformation;
5718 final boolean attachedTransformation = (mAttachedWindow != null
5719 && mAttachedWindow.mHasTransformation);
5720 if (selfTransformation || attachedTransformation) {
5721 // cache often used attributes locally
5722 final Rect frame = mFrame;
5723 final float tmpFloats[] = mTmpFloats;
5724 final Matrix tmpMatrix = mTmpMatrix;
5725
5726 // Compute the desired transformation.
5727 tmpMatrix.setTranslate(frame.left, frame.top);
5728 if (selfTransformation) {
5729 tmpMatrix.preConcat(mTransformation.getMatrix());
5730 }
5731 if (attachedTransformation) {
5732 tmpMatrix.preConcat(mAttachedWindow.mTransformation.getMatrix());
5733 }
5734
5735 // "convert" it into SurfaceFlinger's format
5736 // (a 2x2 matrix + an offset)
5737 // Here we must not transform the position of the surface
5738 // since it is already included in the transformation.
5739 //Log.i(TAG, "Transform: " + matrix);
5740
5741 tmpMatrix.getValues(tmpFloats);
5742 mDsDx = tmpFloats[Matrix.MSCALE_X];
5743 mDtDx = tmpFloats[Matrix.MSKEW_X];
5744 mDsDy = tmpFloats[Matrix.MSKEW_Y];
5745 mDtDy = tmpFloats[Matrix.MSCALE_Y];
5746 int x = (int)tmpFloats[Matrix.MTRANS_X];
5747 int y = (int)tmpFloats[Matrix.MTRANS_Y];
5748 int w = frame.width();
5749 int h = frame.height();
5750 mShownFrame.set(x, y, x+w, y+h);
5751
5752 // Now set the alpha... but because our current hardware
5753 // can't do alpha transformation on a non-opaque surface,
5754 // turn it off if we are running an animation that is also
5755 // transforming since it is more important to have that
5756 // animation be smooth.
5757 mShownAlpha = mAlpha;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005758 if (false && (!PixelFormat.formatHasAlpha(mAttrs.format)
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005759 || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005760 && x == frame.left && y == frame.top))) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005761 //Log.i(TAG, "Applying alpha transform");
5762 if (selfTransformation) {
5763 mShownAlpha *= mTransformation.getAlpha();
5764 }
5765 if (attachedTransformation) {
5766 mShownAlpha *= mAttachedWindow.mTransformation.getAlpha();
5767 }
5768 } else {
5769 //Log.i(TAG, "Not applying alpha transform");
5770 }
5771
5772 if (localLOGV) Log.v(
5773 TAG, "Continuing animation in " + this +
5774 ": " + mShownFrame +
5775 ", alpha=" + mTransformation.getAlpha());
5776 return;
5777 }
5778
5779 mShownFrame.set(mFrame);
5780 mShownAlpha = mAlpha;
5781 mDsDx = 1;
5782 mDtDx = 0;
5783 mDsDy = 0;
5784 mDtDy = 1;
5785 }
5786
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005787 /**
5788 * Is this window visible? It is not visible if there is no
5789 * surface, or we are in the process of running an exit animation
5790 * that will remove the surface.
5791 */
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08005792 public boolean isVisibleLw() {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005793 final AppWindowToken atoken = mAppToken;
5794 return mSurface != null && mPolicyVisibility && !mAttachedHidden
5795 && (atoken == null || !atoken.hiddenRequested)
5796 && !mExiting && !mDestroying;
5797 }
5798
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005799 /**
5800 * The same as isVisible(), but follows the current hidden state of
5801 * the associated app token, not the pending requested hidden state.
5802 */
5803 boolean isVisibleNow() {
5804 return mSurface != null && mPolicyVisibility && !mAttachedHidden
5805 && !mToken.hidden && !mExiting && !mDestroying;
5806 }
5807
5808 /**
5809 * Same as isVisible(), but we also count it as visible between the
5810 * call to IWindowSession.add() and the first relayout().
5811 */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005812 boolean isVisibleOrAdding() {
5813 final AppWindowToken atoken = mAppToken;
5814 return (mSurface != null
5815 || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
5816 && mPolicyVisibility && !mAttachedHidden
5817 && (atoken == null || !atoken.hiddenRequested)
5818 && !mExiting && !mDestroying;
5819 }
5820
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005821 /**
5822 * Is this window currently on-screen? It is on-screen either if it
5823 * is visible or it is currently running an animation before no longer
5824 * being visible.
5825 */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005826 boolean isOnScreen() {
5827 final AppWindowToken atoken = mAppToken;
5828 if (atoken != null) {
5829 return mSurface != null && mPolicyVisibility && !mDestroying
5830 && ((!mAttachedHidden && !atoken.hiddenRequested)
5831 || mAnimating || atoken.animating);
5832 } else {
5833 return mSurface != null && mPolicyVisibility && !mDestroying
5834 && (!mAttachedHidden || mAnimating);
5835 }
5836 }
5837
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005838 /**
5839 * Like isOnScreen(), but we don't return true if the window is part
5840 * of a transition that has not yet been started.
5841 */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005842 boolean isReadyForDisplay() {
5843 final AppWindowToken atoken = mAppToken;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005844 final boolean animating = atoken != null ? atoken.animating : false;
5845 return mSurface != null && mPolicyVisibility && !mDestroying
5846 && ((!mAttachedHidden && !mToken.hidden)
5847 || mAnimating || animating);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005848 }
5849
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005850 /** Is the window or its container currently animating? */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005851 boolean isAnimating() {
5852 final WindowState attached = mAttachedWindow;
5853 final AppWindowToken atoken = mAppToken;
5854 return mAnimation != null
5855 || (attached != null && attached.mAnimation != null)
5856 || (atoken != null &&
5857 (atoken.animation != null
5858 || atoken.inPendingTransaction));
5859 }
5860
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005861 /** Is this window currently animating? */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005862 boolean isWindowAnimating() {
5863 return mAnimation != null;
5864 }
5865
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005866 /**
5867 * Like isOnScreen, but returns false if the surface hasn't yet
5868 * been drawn.
5869 */
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005870 public boolean isDisplayedLw() {
5871 final AppWindowToken atoken = mAppToken;
5872 return mSurface != null && mPolicyVisibility && !mDestroying
5873 && !mDrawPending && !mCommitDrawPending
5874 && ((!mAttachedHidden &&
5875 (atoken == null || !atoken.hiddenRequested))
5876 || mAnimating);
5877 }
5878
5879 public boolean fillsScreenLw(int screenWidth, int screenHeight,
5880 boolean shownFrame) {
5881 if (mSurface == null) {
5882 return false;
5883 }
5884 final Rect frame = shownFrame ? mShownFrame : mFrame;
5885 if (frame.left <= 0 && frame.top <= 0
5886 && frame.right >= screenWidth
5887 && frame.bottom >= screenHeight) {
5888 return true;
5889 }
5890 return false;
5891 }
5892
5893 boolean isFullscreenOpaque(int screenWidth, int screenHeight) {
5894 if (mAttrs.format != PixelFormat.OPAQUE || mSurface == null
5895 || mAnimation != null || mDrawPending || mCommitDrawPending) {
5896 return false;
5897 }
5898 if (mFrame.left <= 0 && mFrame.top <= 0 &&
5899 mFrame.right >= screenWidth && mFrame.bottom >= screenHeight) {
5900 return true;
5901 }
5902 return false;
5903 }
5904
5905 void removeLocked() {
5906 if (mAttachedWindow != null) {
5907 mAttachedWindow.mChildWindows.remove(this);
5908 }
5909 destroySurfaceLocked();
5910 mSession.windowRemovedLocked();
5911 try {
5912 mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
5913 } catch (RuntimeException e) {
5914 // Ignore if it has already been removed (usually because
5915 // we are doing this as part of processing a death note.)
5916 }
5917 }
5918
5919 private class DeathRecipient implements IBinder.DeathRecipient {
5920 public void binderDied() {
5921 try {
5922 synchronized(mWindowMap) {
5923 WindowState win = windowForClientLocked(mSession, mClient);
5924 Log.i(TAG, "WIN DEATH: " + win);
5925 if (win != null) {
5926 removeWindowLocked(mSession, win);
5927 }
5928 }
5929 } catch (IllegalArgumentException ex) {
5930 // This will happen if the window has already been
5931 // removed.
5932 }
5933 }
5934 }
5935
5936 /** Returns true if this window desires key events. */
5937 public final boolean canReceiveKeys() {
5938 return isVisibleOrAdding()
5939 && (mViewVisibility == View.VISIBLE)
5940 && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
5941 }
5942
5943 public boolean hasDrawnLw() {
5944 return mHasDrawn;
5945 }
5946
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08005947 public void showLw(boolean doAnimation) {
5948 if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005949 mSurfacesChanged = true;
5950 mPolicyVisibility = true;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08005951 mPolicyVisibilityAfterAnim = true;
5952 if (doAnimation) {
5953 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
5954 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005955 requestAnimationLocked(0);
5956 }
5957 }
5958
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08005959 public void hideLw(boolean doAnimation) {
5960 if (mPolicyVisibility || mPolicyVisibilityAfterAnim) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005961 mSurfacesChanged = true;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08005962 if (doAnimation) {
5963 applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
5964 if (mAnimation == null) {
5965 doAnimation = false;
5966 }
5967 }
5968 if (doAnimation) {
5969 mPolicyVisibilityAfterAnim = false;
5970 } else {
5971 mPolicyVisibility = false;
5972 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005973 requestAnimationLocked(0);
5974 }
5975 }
5976
5977 void dump(PrintWriter pw, String prefix) {
5978 pw.println(prefix + this);
5979 pw.println(prefix + "mSession=" + mSession
5980 + " mClient=" + mClient.asBinder());
5981 pw.println(prefix + "mAttrs=" + mAttrs);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005982 pw.println(prefix + "mAttachedWindow=" + mAttachedWindow
The Android Open Source Project9266c5582009-01-15 16:12:10 -08005983 + " mLayoutAttached=" + mLayoutAttached
5984 + " mIsImWindow=" + mIsImWindow);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005985 pw.println(prefix + "mBaseLayer=" + mBaseLayer
5986 + " mSubLayer=" + mSubLayer
5987 + " mAnimLayer=" + mLayer + "+"
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005988 + (mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
5989 : (mAppToken != null ? mAppToken.animLayerAdjustment : 0))
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005990 + "=" + mAnimLayer
5991 + " mLastLayer=" + mLastLayer);
5992 pw.println(prefix + "mSurface=" + mSurface);
5993 pw.println(prefix + "mToken=" + mToken);
5994 pw.println(prefix + "mAppToken=" + mAppToken);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08005995 pw.println(prefix + "mTargetAppToken=" + mTargetAppToken);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005996 pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility)
5997 + " mPolicyVisibility=" + mPolicyVisibility
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08005998 + " (after=" + mPolicyVisibilityAfterAnim
5999 + ") mAttachedHidden=" + mAttachedHidden
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006000 + " mLastHidden=" + mLastHidden
6001 + " mHaveFrame=" + mHaveFrame);
6002 pw.println(prefix + "Requested w=" + mRequestedWidth + " h=" + mRequestedHeight
6003 + " x=" + mReqXPos + " y=" + mReqYPos);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006004 pw.println(prefix + "mGivenContentInsets=" + mGivenContentInsets.toShortString()
6005 + " mGivenVisibleInsets=" + mGivenVisibleInsets.toShortString()
6006 + " mTouchableInsets=" + mTouchableInsets
6007 + " pending=" + mGivenInsetsPending);
6008 pw.println(prefix + "mShownFrame=" + mShownFrame.toShortString()
6009 + " last=" + mLastShownFrame.toShortString());
6010 pw.println(prefix + "mFrame=" + mFrame.toShortString()
6011 + " last=" + mLastFrame.toShortString());
6012 pw.println(prefix + "mContainingFrame=" + mContainingFrame.toShortString()
6013 + " mDisplayFrame=" + mDisplayFrame.toShortString());
6014 pw.println(prefix + "mContentFrame=" + mContentFrame.toShortString()
6015 + " mVisibleFrame=" + mVisibleFrame.toShortString());
6016 pw.println(prefix + "mContentInsets=" + mContentInsets.toShortString()
6017 + " last=" + mLastContentInsets.toShortString()
6018 + " mVisibleInsets=" + mVisibleInsets.toShortString()
6019 + " last=" + mLastVisibleInsets.toShortString());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006020 pw.println(prefix + "mShownAlpha=" + mShownAlpha
6021 + " mAlpha=" + mAlpha + " mLastAlpha=" + mLastAlpha);
6022 pw.println(prefix + "mAnimating=" + mAnimating
6023 + " mAnimationIsEntrance=" + mAnimationIsEntrance
6024 + " mAnimation=" + mAnimation);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006025 pw.println(prefix + "XForm: has=" + mHasTransformation
6026 + " " + mTransformation.toShortString());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006027 pw.println(prefix + "mDrawPending=" + mDrawPending
6028 + " mCommitDrawPending=" + mCommitDrawPending
6029 + " mReadyToShow=" + mReadyToShow
6030 + " mHasDrawn=" + mHasDrawn);
6031 pw.println(prefix + "mExiting=" + mExiting
6032 + " mRemoveOnExit=" + mRemoveOnExit
6033 + " mDestroying=" + mDestroying);
6034 pw.println(prefix + "mOrientationChanging=" + mOrientationChanging
6035 + " mAppFreezing=" + mAppFreezing);
6036 }
6037
6038 @Override
6039 public String toString() {
6040 return "Window{"
6041 + Integer.toHexString(System.identityHashCode(this))
6042 + " " + mAttrs.getTitle() + "}";
6043 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006044 }
6045
6046 // -------------------------------------------------------------
6047 // Window Token State
6048 // -------------------------------------------------------------
6049
6050 class WindowToken {
6051 // The actual token.
6052 final IBinder token;
6053
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006054 // The type of window this token is for, as per WindowManager.LayoutParams.
6055 final int windowType;
6056
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006057 // If this is an AppWindowToken, this is non-null.
6058 AppWindowToken appWindowToken;
6059
6060 // All of the windows associated with this token.
6061 final ArrayList<WindowState> windows = new ArrayList<WindowState>();
6062
6063 // Is key dispatching paused for this token?
6064 boolean paused = false;
6065
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006066 // Should this token's windows be hidden?
6067 boolean hidden;
6068
6069 // Temporary for finding which tokens no longer have visible windows.
6070 boolean hasVisible;
6071
6072 WindowToken(IBinder _token, int type) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006073 token = _token;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006074 windowType = type;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006075 }
6076
6077 void dump(PrintWriter pw, String prefix) {
6078 pw.println(prefix + this);
6079 pw.println(prefix + "token=" + token);
6080 pw.println(prefix + "windows=" + windows);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006081 pw.println(prefix + "windowType=" + windowType + " hidden=" + hidden
6082 + " hasVisible=" + hasVisible);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006083 }
6084
6085 @Override
6086 public String toString() {
6087 return "WindowToken{"
6088 + Integer.toHexString(System.identityHashCode(this))
6089 + " token=" + token + "}";
6090 }
6091 };
6092
6093 class AppWindowToken extends WindowToken {
6094 // Non-null only for application tokens.
6095 final IApplicationToken appToken;
6096
6097 // All of the windows and child windows that are included in this
6098 // application token. Note this list is NOT sorted!
6099 final ArrayList<WindowState> allAppWindows = new ArrayList<WindowState>();
6100
6101 int groupId = -1;
6102 boolean appFullscreen;
6103 int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
6104
6105 // These are used for determining when all windows associated with
6106 // an activity have been drawn, so they can be made visible together
6107 // at the same time.
6108 int lastTransactionSequence = mTransactionSequence-1;
6109 int numInterestingWindows;
6110 int numDrawnWindows;
6111 boolean inPendingTransaction;
6112 boolean allDrawn;
6113
6114 // Is this token going to be hidden in a little while? If so, it
6115 // won't be taken into account for setting the screen orientation.
6116 boolean willBeHidden;
6117
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006118 // Is this window's surface needed? This is almost like hidden, except
6119 // it will sometimes be true a little earlier: when the token has
6120 // been shown, but is still waiting for its app transition to execute
6121 // before making its windows shown.
6122 boolean hiddenRequested;
6123
6124 // Have we told the window clients to hide themselves?
6125 boolean clientHidden;
6126
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006127 // Last visibility state we reported to the app token.
6128 boolean reportedVisible;
6129
6130 // Set to true when the token has been removed from the window mgr.
6131 boolean removed;
6132
6133 // Have we been asked to have this token keep the screen frozen?
6134 boolean freezingScreen;
6135
6136 boolean animating;
6137 Animation animation;
6138 boolean hasTransformation;
6139 final Transformation transformation = new Transformation();
6140
6141 // Offset to the window of all layers in the token, for use by
6142 // AppWindowToken animations.
6143 int animLayerAdjustment;
6144
6145 // Information about an application starting window if displayed.
6146 StartingData startingData;
6147 WindowState startingWindow;
6148 View startingView;
6149 boolean startingDisplayed;
6150 boolean startingMoved;
6151 boolean firstWindowDrawn;
6152
6153 AppWindowToken(IApplicationToken _token) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006154 super(_token.asBinder(), WindowManager.LayoutParams.TYPE_APPLICATION);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006155 appWindowToken = this;
6156 appToken = _token;
6157 }
6158
6159 public void setAnimation(Animation anim) {
6160 if (localLOGV) Log.v(
6161 TAG, "Setting animation in " + this + ": " + anim);
6162 animation = anim;
6163 animating = false;
6164 anim.restrictDuration(MAX_ANIMATION_DURATION);
6165 anim.scaleCurrentDuration(mTransitionAnimationScale);
6166 int zorder = anim.getZAdjustment();
6167 int adj = 0;
6168 if (zorder == Animation.ZORDER_TOP) {
6169 adj = TYPE_LAYER_OFFSET;
6170 } else if (zorder == Animation.ZORDER_BOTTOM) {
6171 adj = -TYPE_LAYER_OFFSET;
6172 }
6173
6174 if (animLayerAdjustment != adj) {
6175 animLayerAdjustment = adj;
6176 updateLayers();
6177 }
6178 }
6179
6180 public void setDummyAnimation() {
6181 if (animation == null) {
6182 if (localLOGV) Log.v(
6183 TAG, "Setting dummy animation in " + this);
6184 animation = sDummyAnimation;
6185 }
6186 }
6187
6188 public void clearAnimation() {
6189 if (animation != null) {
6190 animation = null;
6191 animating = true;
6192 }
6193 }
6194
6195 void updateLayers() {
6196 final int N = allAppWindows.size();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006197 final int adj = animLayerAdjustment;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006198 for (int i=0; i<N; i++) {
6199 WindowState w = allAppWindows.get(i);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006200 w.mAnimLayer = w.mLayer + adj;
6201 if (w == mInputMethodTarget) {
6202 WindowState imw = mInputMethodWindow;
6203 if (imw != null) {
6204 imw.mAnimLayer = imw.mLayer + adj;
6205 }
6206 int di = mInputMethodDialogs.size();
6207 while (di > 0) {
6208 di --;
6209 imw = mInputMethodDialogs.get(di);
6210 imw.mAnimLayer = imw.mLayer + adj;
6211 }
6212 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006213 }
6214 }
6215
6216 void sendAppVisibilityToClients() {
6217 final int N = allAppWindows.size();
6218 for (int i=0; i<N; i++) {
6219 WindowState win = allAppWindows.get(i);
6220 if (win == startingWindow && clientHidden) {
6221 // Don't hide the starting window.
6222 continue;
6223 }
6224 try {
6225 if (DEBUG_VISIBILITY) Log.v(TAG,
6226 "Setting visibility of " + win + ": " + (!clientHidden));
6227 win.mClient.dispatchAppVisibility(!clientHidden);
6228 } catch (RemoteException e) {
6229 }
6230 }
6231 }
6232
6233 void showAllWindowsLocked() {
6234 final int NW = allAppWindows.size();
6235 for (int i=0; i<NW; i++) {
6236 WindowState w = allAppWindows.get(i);
6237 if (DEBUG_VISIBILITY) Log.v(TAG,
6238 "performing show on: " + w);
6239 w.performShowLocked();
6240 }
6241 }
6242
6243 // This must be called while inside a transaction.
6244 boolean stepAnimationLocked(long currentTime, int dw, int dh) {
6245 if (!mDisplayFrozen) {
6246 // We will run animations as long as the display isn't frozen.
6247
6248 if (animation == sDummyAnimation) {
6249 // This guy is going to animate, but not yet. For now count
6250 // it is not animating for purposes of scheduling transactions;
6251 // when it is really time to animate, this will be set to
6252 // a real animation and the next call will execute normally.
6253 return false;
6254 }
6255
6256 if ((allDrawn || animating || startingDisplayed) && animation != null) {
6257 if (!animating) {
6258 if (DEBUG_ANIM) Log.v(
6259 TAG, "Starting animation in " + this +
6260 " @ " + currentTime + ": dw=" + dw + " dh=" + dh
6261 + " scale=" + mTransitionAnimationScale
6262 + " allDrawn=" + allDrawn + " animating=" + animating);
6263 animation.initialize(dw, dh, dw, dh);
6264 animation.setStartTime(currentTime);
6265 animating = true;
6266 }
6267 transformation.clear();
6268 final boolean more = animation.getTransformation(
6269 currentTime, transformation);
6270 if (DEBUG_ANIM) Log.v(
6271 TAG, "Stepped animation in " + this +
6272 ": more=" + more + ", xform=" + transformation);
6273 if (more) {
6274 // we're done!
6275 hasTransformation = true;
6276 return true;
6277 }
6278 if (DEBUG_ANIM) Log.v(
6279 TAG, "Finished animation in " + this +
6280 " @ " + currentTime);
6281 animation = null;
6282 }
6283 } else if (animation != null) {
6284 // If the display is frozen, and there is a pending animation,
6285 // clear it and make sure we run the cleanup code.
6286 animating = true;
6287 animation = null;
6288 }
6289
6290 hasTransformation = false;
6291
6292 if (!animating) {
6293 return false;
6294 }
6295
6296 clearAnimation();
6297 animating = false;
6298
6299 if (DEBUG_ANIM) Log.v(
6300 TAG, "Animation done in " + this
6301 + ": reportedVisible=" + reportedVisible);
6302
6303 transformation.clear();
6304 if (animLayerAdjustment != 0) {
6305 animLayerAdjustment = 0;
6306 updateLayers();
6307 }
6308
6309 final int N = windows.size();
6310 for (int i=0; i<N; i++) {
6311 ((WindowState)windows.get(i)).finishExit();
6312 }
6313 updateReportedVisibilityLocked();
6314
6315 return false;
6316 }
6317
6318 void updateReportedVisibilityLocked() {
6319 if (appToken == null) {
6320 return;
6321 }
6322
6323 int numInteresting = 0;
6324 int numVisible = 0;
6325 boolean nowGone = true;
6326
6327 if (DEBUG_VISIBILITY) Log.v(TAG, "Update reported visibility: " + this);
6328 final int N = allAppWindows.size();
6329 for (int i=0; i<N; i++) {
6330 WindowState win = allAppWindows.get(i);
6331 if (win == startingWindow || win.mAppFreezing) {
6332 continue;
6333 }
6334 if (DEBUG_VISIBILITY) {
6335 Log.v(TAG, "Win " + win + ": isDisplayed="
6336 + win.isDisplayedLw()
6337 + ", isAnimating=" + win.isAnimating());
6338 if (!win.isDisplayedLw()) {
6339 Log.v(TAG, "Not displayed: s=" + win.mSurface
6340 + " pv=" + win.mPolicyVisibility
6341 + " dp=" + win.mDrawPending
6342 + " cdp=" + win.mCommitDrawPending
6343 + " ah=" + win.mAttachedHidden
6344 + " th="
6345 + (win.mAppToken != null
6346 ? win.mAppToken.hiddenRequested : false)
6347 + " a=" + win.mAnimating);
6348 }
6349 }
6350 numInteresting++;
6351 if (win.isDisplayedLw()) {
6352 if (!win.isAnimating()) {
6353 numVisible++;
6354 }
6355 nowGone = false;
6356 } else if (win.isAnimating()) {
6357 nowGone = false;
6358 }
6359 }
6360
6361 boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
6362 if (DEBUG_VISIBILITY) Log.v(TAG, "VIS " + this + ": interesting="
6363 + numInteresting + " visible=" + numVisible);
6364 if (nowVisible != reportedVisible) {
6365 if (DEBUG_VISIBILITY) Log.v(
6366 TAG, "Visibility changed in " + this
6367 + ": vis=" + nowVisible);
6368 reportedVisible = nowVisible;
6369 Message m = mH.obtainMessage(
6370 H.REPORT_APPLICATION_TOKEN_WINDOWS,
6371 nowVisible ? 1 : 0,
6372 nowGone ? 1 : 0,
6373 this);
6374 mH.sendMessage(m);
6375 }
6376 }
6377
6378 void dump(PrintWriter pw, String prefix) {
6379 super.dump(pw, prefix);
6380 pw.println(prefix + "app=" + (appToken != null));
6381 pw.println(prefix + "allAppWindows=" + allAppWindows);
6382 pw.println(prefix + "groupId=" + groupId
6383 + " requestedOrientation=" + requestedOrientation);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006384 pw.println(prefix + "hiddenRequested=" + hiddenRequested
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006385 + " clientHidden=" + clientHidden
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006386 + " willBeHidden=" + willBeHidden
6387 + " reportedVisible=" + reportedVisible);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006388 pw.println(prefix + "paused=" + paused
6389 + " freezingScreen=" + freezingScreen);
6390 pw.println(prefix + "numInterestingWindows=" + numInterestingWindows
6391 + " numDrawnWindows=" + numDrawnWindows
6392 + " inPendingTransaction=" + inPendingTransaction
6393 + " allDrawn=" + allDrawn);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006394 pw.println(prefix + "animating=" + animating
6395 + " animation=" + animation);
6396 pw.println(prefix + "animLayerAdjustment=" + animLayerAdjustment
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006397 + " transformation=" + transformation.toShortString());
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006398 pw.println(prefix + "startingData=" + startingData
6399 + " removed=" + removed
6400 + " firstWindowDrawn=" + firstWindowDrawn);
6401 pw.println(prefix + "startingWindow=" + startingWindow
6402 + " startingView=" + startingView
6403 + " startingDisplayed=" + startingDisplayed
6404 + " startingMoved" + startingMoved);
6405 }
6406
6407 @Override
6408 public String toString() {
6409 return "AppWindowToken{"
6410 + Integer.toHexString(System.identityHashCode(this))
6411 + " token=" + token + "}";
6412 }
6413 }
6414
6415 public static WindowManager.LayoutParams findAnimations(
6416 ArrayList<AppWindowToken> order,
6417 ArrayList<AppWindowToken> tokenList1,
6418 ArrayList<AppWindowToken> tokenList2) {
6419 // We need to figure out which animation to use...
6420 WindowManager.LayoutParams animParams = null;
6421 int animSrc = 0;
6422
6423 //Log.i(TAG, "Looking for animations...");
6424 for (int i=order.size()-1; i>=0; i--) {
6425 AppWindowToken wtoken = order.get(i);
6426 //Log.i(TAG, "Token " + wtoken + " with " + wtoken.windows.size() + " windows");
6427 if (tokenList1.contains(wtoken) || tokenList2.contains(wtoken)) {
6428 int j = wtoken.windows.size();
6429 while (j > 0) {
6430 j--;
6431 WindowState win = wtoken.windows.get(j);
6432 //Log.i(TAG, "Window " + win + ": type=" + win.mAttrs.type);
6433 if (win.mAttrs.type == WindowManager.LayoutParams.TYPE_BASE_APPLICATION
6434 || win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
6435 //Log.i(TAG, "Found base or application window, done!");
6436 if (wtoken.appFullscreen) {
6437 return win.mAttrs;
6438 }
6439 if (animSrc < 2) {
6440 animParams = win.mAttrs;
6441 animSrc = 2;
6442 }
6443 } else if (animSrc < 1 && win.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION) {
6444 //Log.i(TAG, "Found normal window, we may use this...");
6445 animParams = win.mAttrs;
6446 animSrc = 1;
6447 }
6448 }
6449 }
6450 }
6451
6452 return animParams;
6453 }
6454
6455 // -------------------------------------------------------------
6456 // DummyAnimation
6457 // -------------------------------------------------------------
6458
6459 // This is an animation that does nothing: it just immediately finishes
6460 // itself every time it is called. It is used as a stub animation in cases
6461 // where we want to synchronize multiple things that may be animating.
6462 static final class DummyAnimation extends Animation {
6463 public boolean getTransformation(long currentTime, Transformation outTransformation) {
6464 return false;
6465 }
6466 }
6467 static final Animation sDummyAnimation = new DummyAnimation();
6468
6469 // -------------------------------------------------------------
6470 // Async Handler
6471 // -------------------------------------------------------------
6472
6473 static final class StartingData {
6474 final String pkg;
6475 final int theme;
6476 final CharSequence nonLocalizedLabel;
6477 final int labelRes;
6478 final int icon;
6479
6480 StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel,
6481 int _labelRes, int _icon) {
6482 pkg = _pkg;
6483 theme = _theme;
6484 nonLocalizedLabel = _nonLocalizedLabel;
6485 labelRes = _labelRes;
6486 icon = _icon;
6487 }
6488 }
6489
6490 private final class H extends Handler {
6491 public static final int REPORT_FOCUS_CHANGE = 2;
6492 public static final int REPORT_LOSING_FOCUS = 3;
6493 public static final int ANIMATE = 4;
6494 public static final int ADD_STARTING = 5;
6495 public static final int REMOVE_STARTING = 6;
6496 public static final int FINISHED_STARTING = 7;
6497 public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
6498 public static final int UPDATE_ORIENTATION = 10;
6499 public static final int WINDOW_FREEZE_TIMEOUT = 11;
6500 public static final int HOLD_SCREEN_CHANGED = 12;
6501 public static final int APP_TRANSITION_TIMEOUT = 13;
6502 public static final int PERSIST_ANIMATION_SCALE = 14;
6503 public static final int FORCE_GC = 15;
6504 public static final int ENABLE_SCREEN = 16;
6505 public static final int APP_FREEZE_TIMEOUT = 17;
6506
6507 private Session mLastReportedHold;
6508
6509 public H() {
6510 }
6511
6512 @Override
6513 public void handleMessage(Message msg) {
6514 switch (msg.what) {
6515 case REPORT_FOCUS_CHANGE: {
6516 WindowState lastFocus;
6517 WindowState newFocus;
6518
6519 synchronized(mWindowMap) {
6520 lastFocus = mLastFocus;
6521 newFocus = mCurrentFocus;
6522 mLastFocus = newFocus;
6523 //Log.i(TAG, "Focus moving from " + lastFocus
6524 // + " to " + newFocus);
6525 if (newFocus != null && lastFocus != null
6526 && !newFocus.isDisplayedLw()) {
6527 //Log.i(TAG, "Delaying loss of focus...");
6528 mLosingFocus.add(lastFocus);
6529 lastFocus = null;
6530 }
6531 }
6532
6533 if (lastFocus != newFocus) {
6534 //System.out.println("Changing focus from " + lastFocus
6535 // + " to " + newFocus);
6536 if (newFocus != null) {
6537 try {
6538 //Log.i(TAG, "Gaining focus: " + newFocus);
6539 newFocus.mClient.windowFocusChanged(true, mInTouchMode);
6540 } catch (RemoteException e) {
6541 // Ignore if process has died.
6542 }
6543 }
6544
6545 if (lastFocus != null) {
6546 try {
6547 //Log.i(TAG, "Losing focus: " + lastFocus);
6548 lastFocus.mClient.windowFocusChanged(false, mInTouchMode);
6549 } catch (RemoteException e) {
6550 // Ignore if process has died.
6551 }
6552 }
6553 }
6554 } break;
6555
6556 case REPORT_LOSING_FOCUS: {
6557 ArrayList<WindowState> losers;
6558
6559 synchronized(mWindowMap) {
6560 losers = mLosingFocus;
6561 mLosingFocus = new ArrayList<WindowState>();
6562 }
6563
6564 final int N = losers.size();
6565 for (int i=0; i<N; i++) {
6566 try {
6567 //Log.i(TAG, "Losing delayed focus: " + losers.get(i));
6568 losers.get(i).mClient.windowFocusChanged(false, mInTouchMode);
6569 } catch (RemoteException e) {
6570 // Ignore if process has died.
6571 }
6572 }
6573 } break;
6574
6575 case ANIMATE: {
6576 synchronized(mWindowMap) {
6577 mAnimationPending = false;
6578 performLayoutAndPlaceSurfacesLocked();
6579 }
6580 } break;
6581
6582 case ADD_STARTING: {
6583 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
6584 final StartingData sd = wtoken.startingData;
6585
6586 if (sd == null) {
6587 // Animation has been canceled... do nothing.
6588 return;
6589 }
6590
6591 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Add starting "
6592 + wtoken + ": pkg=" + sd.pkg);
6593
6594 View view = null;
6595 try {
6596 view = mPolicy.addStartingWindow(
6597 wtoken.token, sd.pkg,
6598 sd.theme, sd.nonLocalizedLabel, sd.labelRes,
6599 sd.icon);
6600 } catch (Exception e) {
6601 Log.w(TAG, "Exception when adding starting window", e);
6602 }
6603
6604 if (view != null) {
6605 boolean abort = false;
6606
6607 synchronized(mWindowMap) {
6608 if (wtoken.removed || wtoken.startingData == null) {
6609 // If the window was successfully added, then
6610 // we need to remove it.
6611 if (wtoken.startingWindow != null) {
6612 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
6613 "Aborted starting " + wtoken
6614 + ": removed=" + wtoken.removed
6615 + " startingData=" + wtoken.startingData);
6616 wtoken.startingWindow = null;
6617 wtoken.startingData = null;
6618 abort = true;
6619 }
6620 } else {
6621 wtoken.startingView = view;
6622 }
6623 if (DEBUG_STARTING_WINDOW && !abort) Log.v(TAG,
6624 "Added starting " + wtoken
6625 + ": startingWindow="
6626 + wtoken.startingWindow + " startingView="
6627 + wtoken.startingView);
6628 }
6629
6630 if (abort) {
6631 try {
6632 mPolicy.removeStartingWindow(wtoken.token, view);
6633 } catch (Exception e) {
6634 Log.w(TAG, "Exception when removing starting window", e);
6635 }
6636 }
6637 }
6638 } break;
6639
6640 case REMOVE_STARTING: {
6641 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
6642 IBinder token = null;
6643 View view = null;
6644 synchronized (mWindowMap) {
6645 if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Remove starting "
6646 + wtoken + ": startingWindow="
6647 + wtoken.startingWindow + " startingView="
6648 + wtoken.startingView);
6649 if (wtoken.startingWindow != null) {
6650 view = wtoken.startingView;
6651 token = wtoken.token;
6652 wtoken.startingData = null;
6653 wtoken.startingView = null;
6654 wtoken.startingWindow = null;
6655 }
6656 }
6657 if (view != null) {
6658 try {
6659 mPolicy.removeStartingWindow(token, view);
6660 } catch (Exception e) {
6661 Log.w(TAG, "Exception when removing starting window", e);
6662 }
6663 }
6664 } break;
6665
6666 case FINISHED_STARTING: {
6667 IBinder token = null;
6668 View view = null;
6669 while (true) {
6670 synchronized (mWindowMap) {
6671 final int N = mFinishedStarting.size();
6672 if (N <= 0) {
6673 break;
6674 }
6675 AppWindowToken wtoken = mFinishedStarting.remove(N-1);
6676
6677 if (DEBUG_STARTING_WINDOW) Log.v(TAG,
6678 "Finished starting " + wtoken
6679 + ": startingWindow=" + wtoken.startingWindow
6680 + " startingView=" + wtoken.startingView);
6681
6682 if (wtoken.startingWindow == null) {
6683 continue;
6684 }
6685
6686 view = wtoken.startingView;
6687 token = wtoken.token;
6688 wtoken.startingData = null;
6689 wtoken.startingView = null;
6690 wtoken.startingWindow = null;
6691 }
6692
6693 try {
6694 mPolicy.removeStartingWindow(token, view);
6695 } catch (Exception e) {
6696 Log.w(TAG, "Exception when removing starting window", e);
6697 }
6698 }
6699 } break;
6700
6701 case REPORT_APPLICATION_TOKEN_WINDOWS: {
6702 final AppWindowToken wtoken = (AppWindowToken)msg.obj;
6703
6704 boolean nowVisible = msg.arg1 != 0;
6705 boolean nowGone = msg.arg2 != 0;
6706
6707 try {
6708 if (DEBUG_VISIBILITY) Log.v(
6709 TAG, "Reporting visible in " + wtoken
6710 + " visible=" + nowVisible
6711 + " gone=" + nowGone);
6712 if (nowVisible) {
6713 wtoken.appToken.windowsVisible();
6714 } else {
6715 wtoken.appToken.windowsGone();
6716 }
6717 } catch (RemoteException ex) {
6718 }
6719 } break;
6720
6721 case UPDATE_ORIENTATION: {
6722 setRotationUnchecked(WindowManagerPolicy.USE_LAST_ROTATION, false);
6723 break;
6724 }
6725
6726 case WINDOW_FREEZE_TIMEOUT: {
6727 synchronized (mWindowMap) {
6728 Log.w(TAG, "Window freeze timeout expired.");
6729 int i = mWindows.size();
6730 while (i > 0) {
6731 i--;
6732 WindowState w = (WindowState)mWindows.get(i);
6733 if (w.mOrientationChanging) {
6734 w.mOrientationChanging = false;
6735 Log.w(TAG, "Force clearing orientation change: " + w);
6736 }
6737 }
6738 performLayoutAndPlaceSurfacesLocked();
6739 }
6740 break;
6741 }
6742
6743 case HOLD_SCREEN_CHANGED: {
6744 Session oldHold;
6745 Session newHold;
6746 synchronized (mWindowMap) {
6747 oldHold = mLastReportedHold;
6748 newHold = (Session)msg.obj;
6749 mLastReportedHold = newHold;
6750 }
6751
6752 if (oldHold != newHold) {
6753 try {
6754 if (oldHold != null) {
6755 mBatteryStats.noteStopWakelock(oldHold.mUid,
6756 "window",
6757 BatteryStats.WAKE_TYPE_WINDOW);
6758 }
6759 if (newHold != null) {
6760 mBatteryStats.noteStartWakelock(newHold.mUid,
6761 "window",
6762 BatteryStats.WAKE_TYPE_WINDOW);
6763 }
6764 } catch (RemoteException e) {
6765 }
6766 }
6767 break;
6768 }
6769
6770 case APP_TRANSITION_TIMEOUT: {
6771 synchronized (mWindowMap) {
6772 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
6773 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
6774 "*** APP TRANSITION TIMEOUT");
6775 mAppTransitionReady = true;
6776 mAppTransitionTimeout = true;
6777 performLayoutAndPlaceSurfacesLocked();
6778 }
6779 }
6780 break;
6781 }
6782
6783 case PERSIST_ANIMATION_SCALE: {
6784 Settings.System.putFloat(mContext.getContentResolver(),
6785 Settings.System.WINDOW_ANIMATION_SCALE, mWindowAnimationScale);
6786 Settings.System.putFloat(mContext.getContentResolver(),
6787 Settings.System.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScale);
6788 break;
6789 }
6790
6791 case FORCE_GC: {
6792 synchronized(mWindowMap) {
6793 if (mAnimationPending) {
6794 // If we are animating, don't do the gc now but
6795 // delay a bit so we don't interrupt the animation.
6796 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
6797 2000);
6798 return;
6799 }
6800 // If we are currently rotating the display, it will
6801 // schedule a new message when done.
6802 if (mDisplayFrozen) {
6803 return;
6804 }
6805 mFreezeGcPending = 0;
6806 }
6807 Runtime.getRuntime().gc();
6808 break;
6809 }
6810
6811 case ENABLE_SCREEN: {
6812 performEnableScreen();
6813 break;
6814 }
6815
6816 case APP_FREEZE_TIMEOUT: {
6817 synchronized (mWindowMap) {
6818 Log.w(TAG, "App freeze timeout expired.");
6819 int i = mAppTokens.size();
6820 while (i > 0) {
6821 i--;
6822 AppWindowToken tok = mAppTokens.get(i);
6823 if (tok.freezingScreen) {
6824 Log.w(TAG, "Force clearing freeze: " + tok);
6825 unsetAppFreezingScreenLocked(tok, true, true);
6826 }
6827 }
6828 }
6829 break;
6830 }
6831
6832 }
6833 }
6834 }
6835
6836 // -------------------------------------------------------------
6837 // IWindowManager API
6838 // -------------------------------------------------------------
6839
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006840 public IWindowSession openSession(IInputMethodClient client,
6841 IInputContext inputContext) {
6842 if (client == null) throw new IllegalArgumentException("null client");
6843 if (inputContext == null) throw new IllegalArgumentException("null inputContext");
6844 return new Session(client, inputContext);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006845 }
6846
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006847 public boolean inputMethodClientHasFocus(IInputMethodClient client) {
6848 synchronized (mWindowMap) {
6849 // The focus for the client is the window immediately below
6850 // where we would place the input method window.
6851 int idx = findDesiredInputMethodWindowIndexLocked();
6852 if (idx > 0) {
6853 WindowState imFocus = (WindowState)mWindows.get(idx-1);
6854 if (imFocus != null && imFocus.mSession.mClient != null &&
6855 imFocus.mSession.mClient.asBinder() == client.asBinder()) {
6856 return true;
6857 }
6858 }
6859 }
6860 return false;
6861 }
6862
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006863 // -------------------------------------------------------------
6864 // Internals
6865 // -------------------------------------------------------------
6866
6867 final WindowState windowForClientLocked(Session session, IWindow client) {
6868 return windowForClientLocked(session, client.asBinder());
6869 }
6870
6871 final WindowState windowForClientLocked(Session session, IBinder client) {
6872 WindowState win = mWindowMap.get(client);
6873 if (localLOGV) Log.v(
6874 TAG, "Looking up client " + client + ": " + win);
6875 if (win == null) {
6876 RuntimeException ex = new RuntimeException();
6877 Log.w(TAG, "Requested window " + client + " does not exist", ex);
6878 return null;
6879 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006880 if (session != null && win.mSession != session) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006881 RuntimeException ex = new RuntimeException();
6882 Log.w(TAG, "Requested window " + client + " is in session " +
6883 win.mSession + ", not " + session, ex);
6884 return null;
6885 }
6886
6887 return win;
6888 }
6889
6890 private final void assignLayersLocked() {
6891 if (mInLayout) {
6892 if (Config.DEBUG) {
6893 throw new RuntimeException("Recursive call!");
6894 }
6895 return;
6896 }
6897
6898 int N = mWindows.size();
6899 int curBaseLayer = 0;
6900 int curLayer = 0;
6901 int i;
6902
6903 for (i=0; i<N; i++) {
6904 WindowState w = (WindowState)mWindows.get(i);
The Android Open Source Project9266c5582009-01-15 16:12:10 -08006905 if (w.mBaseLayer == curBaseLayer || w.mIsImWindow) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006906 curLayer += WINDOW_LAYER_MULTIPLIER;
6907 w.mLayer = curLayer;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006908 } else {
6909 curBaseLayer = curLayer = w.mBaseLayer;
6910 w.mLayer = curLayer;
6911 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08006912 if (w.mTargetAppToken != null) {
6913 w.mAnimLayer = w.mLayer + w.mTargetAppToken.animLayerAdjustment;
6914 } else if (w.mAppToken != null) {
6915 w.mAnimLayer = w.mLayer + w.mAppToken.animLayerAdjustment;
6916 } else {
6917 w.mAnimLayer = w.mLayer;
6918 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07006919 //System.out.println(
6920 // "Assigned layer " + curLayer + " to " + w.mClient.asBinder());
6921 }
6922 }
6923
6924 private boolean mInLayout = false;
6925 private final void performLayoutAndPlaceSurfacesLocked() {
6926 if (mInLayout) {
6927 if (Config.DEBUG) {
6928 throw new RuntimeException("Recursive call!");
6929 }
6930 return;
6931 }
6932
6933 boolean recoveringMemory = false;
6934 if (mForceRemoves != null) {
6935 recoveringMemory = true;
6936 // Wait a little it for things to settle down, and off we go.
6937 for (int i=0; i<mForceRemoves.size(); i++) {
6938 WindowState ws = mForceRemoves.get(i);
6939 Log.i(TAG, "Force removing: " + ws);
6940 removeWindowInnerLocked(ws.mSession, ws);
6941 }
6942 mForceRemoves = null;
6943 Log.w(TAG, "Due to memory failure, waiting a bit for next layout");
6944 Object tmp = new Object();
6945 synchronized (tmp) {
6946 try {
6947 tmp.wait(250);
6948 } catch (InterruptedException e) {
6949 }
6950 }
6951 }
6952
6953 mInLayout = true;
6954 try {
6955 performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
6956
6957 int i = mPendingRemove.size()-1;
6958 if (i >= 0) {
6959 while (i >= 0) {
6960 WindowState w = mPendingRemove.get(i);
6961 removeWindowInnerLocked(w.mSession, w);
6962 i--;
6963 }
6964 mPendingRemove.clear();
6965
6966 mInLayout = false;
6967 assignLayersLocked();
6968 mLayoutNeeded = true;
6969 performLayoutAndPlaceSurfacesLocked();
6970
6971 } else {
6972 mInLayout = false;
6973 if (mLayoutNeeded) {
6974 requestAnimationLocked(0);
6975 }
6976 }
6977 } catch (RuntimeException e) {
6978 mInLayout = false;
6979 Log.e(TAG, "Unhandled exception while layout out windows", e);
6980 }
6981 }
6982
6983 private final void performLayoutLockedInner() {
6984 final int dw = mDisplay.getWidth();
6985 final int dh = mDisplay.getHeight();
6986
6987 final int N = mWindows.size();
6988 int i;
6989
6990 // FIRST LOOP: Perform a layout, if needed.
6991
6992 if (mLayoutNeeded) {
6993 mPolicy.beginLayoutLw(dw, dh);
6994
6995 // First perform layout of any root windows (not attached
6996 // to another window).
6997 int topAttached = -1;
6998 for (i = N-1; i >= 0; i--) {
6999 WindowState win = (WindowState) mWindows.get(i);
7000
7001 boolean gone = win.mViewVisibility == View.GONE
7002 || !win.mRelayoutCalled;
7003
7004 // If this view is GONE, then skip it -- keep the current
7005 // frame, and let the caller know so they can ignore it
7006 // if they want. (We do the normal layout for INVISIBLE
7007 // windows, since that means "perform layout as normal,
7008 // just don't display").
7009 if (!gone || !win.mHaveFrame) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007010 if (!win.mLayoutAttached) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007011 mPolicy.layoutWindowLw(win, win.mAttrs, null);
7012 } else {
7013 if (topAttached < 0) topAttached = i;
7014 }
7015 }
7016 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007017
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007018 // Now perform layout of attached windows, which usually
7019 // depend on the position of the window they are attached to.
7020 // XXX does not deal with windows that are attached to windows
7021 // that are themselves attached.
7022 for (i = topAttached; i >= 0; i--) {
7023 WindowState win = (WindowState) mWindows.get(i);
7024
7025 // If this view is GONE, then skip it -- keep the current
7026 // frame, and let the caller know so they can ignore it
7027 // if they want. (We do the normal layout for INVISIBLE
7028 // windows, since that means "perform layout as normal,
7029 // just don't display").
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007030 if (win.mLayoutAttached) {
7031 if ((win.mViewVisibility != View.GONE && win.mRelayoutCalled)
7032 || !win.mHaveFrame) {
7033 mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
7034 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007035 }
7036 }
7037
7038 mPolicy.finishLayoutLw();
7039 mLayoutNeeded = false;
7040 }
7041 }
7042
7043 private final void performLayoutAndPlaceSurfacesLockedInner(
7044 boolean recoveringMemory) {
7045 final long currentTime = SystemClock.uptimeMillis();
7046 final int dw = mDisplay.getWidth();
7047 final int dh = mDisplay.getHeight();
7048
7049 final int N = mWindows.size();
7050 int i;
7051
7052 // FIRST LOOP: Perform a layout, if needed.
7053
7054 performLayoutLockedInner();
7055
7056 if (mFxSession == null) {
7057 mFxSession = new SurfaceSession();
7058 }
7059
7060 if (SHOW_TRANSACTIONS) Log.i(TAG, ">>> OPEN TRANSACTION");
7061
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007062 // Initialize state of exiting tokens.
7063 for (i=mExitingTokens.size()-1; i>=0; i--) {
7064 mExitingTokens.get(i).hasVisible = false;
7065 }
7066
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007067 // Initialize state of exiting applications.
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007068 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007069 mExitingAppTokens.get(i).hasVisible = false;
7070 }
7071
7072 // SECOND LOOP: Execute animations and update visibility of windows.
7073
7074 boolean orientationChangeComplete = true;
7075 Session holdScreen = null;
7076 boolean focusDisplayed = false;
7077 boolean animating = false;
7078
7079 Surface.openTransaction();
7080 try {
7081 boolean restart;
7082
7083 do {
7084 final int transactionSequence = ++mTransactionSequence;
7085
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007086 // Update animations of all applications, including those
7087 // associated with exiting/removed apps
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007088 boolean tokensAnimating = false;
7089 final int NAT = mAppTokens.size();
7090 for (i=0; i<NAT; i++) {
7091 if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
7092 tokensAnimating = true;
7093 }
7094 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007095 final int NEAT = mExitingAppTokens.size();
7096 for (i=0; i<NEAT; i++) {
7097 if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
7098 tokensAnimating = true;
7099 }
7100 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007101
7102 animating = tokensAnimating;
7103 restart = false;
7104
7105 boolean tokenMayBeDrawn = false;
7106
7107 mPolicy.beginAnimationLw(dw, dh);
7108
7109 for (i=N-1; i>=0; i--) {
7110 WindowState w = (WindowState)mWindows.get(i);
7111
7112 final WindowManager.LayoutParams attrs = w.mAttrs;
7113
7114 if (w.mSurface != null) {
7115 // Execute animation.
7116 w.commitFinishDrawingLocked(currentTime);
7117 if (w.stepAnimationLocked(currentTime, dw, dh)) {
7118 animating = true;
7119 //w.dump(" ");
7120 }
7121
7122 mPolicy.animatingWindowLw(w, attrs);
7123 }
7124
7125 final AppWindowToken atoken = w.mAppToken;
7126 if (atoken != null && (!atoken.allDrawn || atoken.freezingScreen)) {
7127 if (atoken.lastTransactionSequence != transactionSequence) {
7128 atoken.lastTransactionSequence = transactionSequence;
7129 atoken.numInterestingWindows = atoken.numDrawnWindows = 0;
7130 atoken.startingDisplayed = false;
7131 }
7132 if ((w.isOnScreen() || w.mAttrs.type
7133 == WindowManager.LayoutParams.TYPE_BASE_APPLICATION)
7134 && !w.mExiting && !w.mDestroying) {
7135 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) {
7136 Log.v(TAG, "Eval win " + w + ": isDisplayed="
7137 + w.isDisplayedLw()
7138 + ", isAnimating=" + w.isAnimating());
7139 if (!w.isDisplayedLw()) {
7140 Log.v(TAG, "Not displayed: s=" + w.mSurface
7141 + " pv=" + w.mPolicyVisibility
7142 + " dp=" + w.mDrawPending
7143 + " cdp=" + w.mCommitDrawPending
7144 + " ah=" + w.mAttachedHidden
7145 + " th=" + atoken.hiddenRequested
7146 + " a=" + w.mAnimating);
7147 }
7148 }
7149 if (w != atoken.startingWindow) {
7150 if (!atoken.freezingScreen || !w.mAppFreezing) {
7151 atoken.numInterestingWindows++;
7152 if (w.isDisplayedLw()) {
7153 atoken.numDrawnWindows++;
7154 if (DEBUG_VISIBILITY || DEBUG_ORIENTATION) Log.v(TAG,
7155 "tokenMayBeDrawn: " + atoken
7156 + " freezingScreen=" + atoken.freezingScreen
7157 + " mAppFreezing=" + w.mAppFreezing);
7158 tokenMayBeDrawn = true;
7159 }
7160 }
7161 } else if (w.isDisplayedLw()) {
7162 atoken.startingDisplayed = true;
7163 }
7164 }
7165 } else if (w.mReadyToShow) {
7166 w.performShowLocked();
7167 }
7168 }
7169
7170 if (mPolicy.finishAnimationLw()) {
7171 restart = true;
7172 }
7173
7174 if (tokenMayBeDrawn) {
7175 // See if any windows have been drawn, so they (and others
7176 // associated with them) can now be shown.
7177 final int NT = mTokenList.size();
7178 for (i=0; i<NT; i++) {
7179 AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
7180 if (wtoken == null) {
7181 continue;
7182 }
7183 if (wtoken.freezingScreen) {
7184 int numInteresting = wtoken.numInterestingWindows;
7185 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
7186 if (DEBUG_VISIBILITY) Log.v(TAG,
7187 "allDrawn: " + wtoken
7188 + " interesting=" + numInteresting
7189 + " drawn=" + wtoken.numDrawnWindows);
7190 wtoken.showAllWindowsLocked();
7191 unsetAppFreezingScreenLocked(wtoken, false, true);
7192 orientationChangeComplete = true;
7193 }
7194 } else if (!wtoken.allDrawn) {
7195 int numInteresting = wtoken.numInterestingWindows;
7196 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
7197 if (DEBUG_VISIBILITY) Log.v(TAG,
7198 "allDrawn: " + wtoken
7199 + " interesting=" + numInteresting
7200 + " drawn=" + wtoken.numDrawnWindows);
7201 wtoken.allDrawn = true;
7202 restart = true;
7203
7204 // We can now show all of the drawn windows!
7205 if (!mOpeningApps.contains(wtoken)) {
7206 wtoken.showAllWindowsLocked();
7207 }
7208 }
7209 }
7210 }
7211 }
7212
7213 // If we are ready to perform an app transition, check through
7214 // all of the app tokens to be shown and see if they are ready
7215 // to go.
7216 if (mAppTransitionReady) {
7217 int NN = mOpeningApps.size();
7218 boolean goodToGo = true;
7219 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
7220 "Checking " + NN + " opening apps (frozen="
7221 + mDisplayFrozen + " timeout="
7222 + mAppTransitionTimeout + ")...");
7223 if (!mDisplayFrozen && !mAppTransitionTimeout) {
7224 // If the display isn't frozen, wait to do anything until
7225 // all of the apps are ready. Otherwise just go because
7226 // we'll unfreeze the display when everyone is ready.
7227 for (i=0; i<NN && goodToGo; i++) {
7228 AppWindowToken wtoken = mOpeningApps.get(i);
7229 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
7230 "Check opening app" + wtoken + ": allDrawn="
7231 + wtoken.allDrawn + " startingDisplayed="
7232 + wtoken.startingDisplayed);
7233 if (!wtoken.allDrawn && !wtoken.startingDisplayed
7234 && !wtoken.startingMoved) {
7235 goodToGo = false;
7236 }
7237 }
7238 }
7239 if (goodToGo) {
7240 if (DEBUG_APP_TRANSITIONS) Log.v(TAG, "**** GOOD TO GO");
7241 int transit = mNextAppTransition;
7242 if (mSkipAppTransitionAnimation) {
7243 transit = WindowManagerPolicy.TRANSIT_NONE;
7244 }
7245 mNextAppTransition = WindowManagerPolicy.TRANSIT_NONE;
7246 mAppTransitionReady = false;
7247 mAppTransitionTimeout = false;
7248 mStartingIconInTransition = false;
7249 mSkipAppTransitionAnimation = false;
7250
7251 mH.removeMessages(H.APP_TRANSITION_TIMEOUT);
7252
7253 // We need to figure out which animation to use...
7254 WindowManager.LayoutParams lp = findAnimations(mAppTokens,
7255 mOpeningApps, mClosingApps);
7256
7257 NN = mOpeningApps.size();
7258 for (i=0; i<NN; i++) {
7259 AppWindowToken wtoken = mOpeningApps.get(i);
7260 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
7261 "Now opening app" + wtoken);
7262 wtoken.reportedVisible = false;
7263 wtoken.inPendingTransaction = false;
7264 setTokenVisibilityLocked(wtoken, lp, true, transit, false);
7265 wtoken.updateReportedVisibilityLocked();
7266 wtoken.showAllWindowsLocked();
7267 }
7268 NN = mClosingApps.size();
7269 for (i=0; i<NN; i++) {
7270 AppWindowToken wtoken = mClosingApps.get(i);
7271 if (DEBUG_APP_TRANSITIONS) Log.v(TAG,
7272 "Now closing app" + wtoken);
7273 wtoken.inPendingTransaction = false;
7274 setTokenVisibilityLocked(wtoken, lp, false, transit, false);
7275 wtoken.updateReportedVisibilityLocked();
7276 // Force the allDrawn flag, because we want to start
7277 // this guy's animations regardless of whether it's
7278 // gotten drawn.
7279 wtoken.allDrawn = true;
7280 }
7281
7282 mOpeningApps.clear();
7283 mClosingApps.clear();
7284
7285 // This has changed the visibility of windows, so perform
7286 // a new layout to get them all up-to-date.
7287 mLayoutNeeded = true;
7288 performLayoutLockedInner();
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007289 updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007290
7291 restart = true;
7292 }
7293 }
7294 } while (restart);
7295
7296 // THIRD LOOP: Update the surfaces of all windows.
7297
7298 final boolean someoneLosingFocus = mLosingFocus.size() != 0;
7299
7300 mSurfacesChanged = false;
7301 boolean obscured = false;
7302 boolean blurring = false;
7303 boolean dimming = false;
7304 boolean covered = false;
7305 int tint = 0;
7306
7307 for (i=N-1; i>=0; i--) {
7308 WindowState w = (WindowState)mWindows.get(i);
7309
7310 boolean displayed = false;
7311 final WindowManager.LayoutParams attrs = w.mAttrs;
7312 final int attrFlags = attrs.flags;
7313
7314 if (w.mSurface != null) {
7315 w.computeShownFrameLocked();
7316 if (localLOGV) Log.v(
7317 TAG, "Placing surface #" + i + " " + w.mSurface
7318 + ": new=" + w.mShownFrame + ", old="
7319 + w.mLastShownFrame);
7320
7321 boolean resize;
7322 int width, height;
7323 if ((w.mAttrs.flags & w.mAttrs.FLAG_SCALED) != 0) {
7324 resize = w.mLastRequestedWidth != w.mRequestedWidth ||
7325 w.mLastRequestedHeight != w.mRequestedHeight;
7326 // for a scaled surface, we just want to use
7327 // the requested size.
7328 width = w.mRequestedWidth;
7329 height = w.mRequestedHeight;
7330 w.mLastRequestedWidth = width;
7331 w.mLastRequestedHeight = height;
7332 w.mLastShownFrame.set(w.mShownFrame);
7333 try {
7334 w.mSurface.setPosition(w.mShownFrame.left, w.mShownFrame.top);
7335 } catch (RuntimeException e) {
7336 Log.w(TAG, "Error positioning surface in " + w, e);
7337 if (!recoveringMemory) {
7338 reclaimSomeSurfaceMemoryLocked(w, "position");
7339 }
7340 }
7341 } else {
7342 resize = !w.mLastShownFrame.equals(w.mShownFrame);
7343 width = w.mShownFrame.width();
7344 height = w.mShownFrame.height();
7345 w.mLastShownFrame.set(w.mShownFrame);
7346 if (resize) {
7347 if (SHOW_TRANSACTIONS) Log.i(
7348 TAG, " SURFACE " + w.mSurface + ": ("
7349 + w.mShownFrame.left + ","
7350 + w.mShownFrame.top + ") ("
7351 + w.mShownFrame.width() + "x"
7352 + w.mShownFrame.height() + ")");
7353 }
7354 }
7355
7356 if (resize) {
7357 if (width < 1) width = 1;
7358 if (height < 1) height = 1;
7359 if (w.mSurface != null) {
7360 try {
7361 w.mSurface.setSize(width, height);
7362 w.mSurface.setPosition(w.mShownFrame.left,
7363 w.mShownFrame.top);
7364 } catch (RuntimeException e) {
7365 // If something goes wrong with the surface (such
7366 // as running out of memory), don't take down the
7367 // entire system.
7368 Log.e(TAG, "Failure updating surface of " + w
7369 + "size=(" + width + "x" + height
7370 + "), pos=(" + w.mShownFrame.left
7371 + "," + w.mShownFrame.top + ")", e);
7372 if (!recoveringMemory) {
7373 reclaimSomeSurfaceMemoryLocked(w, "size");
7374 }
7375 }
7376 }
7377 }
7378 if (!w.mAppFreezing) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007379 w.mContentInsetsChanged =
7380 !w.mLastContentInsets.equals(w.mContentInsets);
7381 w.mVisibleInsetsChanged =
7382 !w.mLastVisibleInsets.equals(w.mVisibleInsets);
7383 if (!w.mLastFrame.equals(w.mFrame)
7384 || w.mContentInsetsChanged
7385 || w.mVisibleInsetsChanged) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007386 w.mLastFrame.set(w.mFrame);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007387 w.mLastContentInsets.set(w.mContentInsets);
7388 w.mLastVisibleInsets.set(w.mVisibleInsets);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007389 // If the orientation is changing, then we need to
7390 // hold off on unfreezing the display until this
7391 // window has been redrawn; to do that, we need
7392 // to go through the process of getting informed
7393 // by the application when it has finished drawing.
7394 if (w.mOrientationChanging) {
7395 if (DEBUG_ORIENTATION) Log.v(TAG,
7396 "Orientation start waiting for draw in "
7397 + w + ", surface " + w.mSurface);
7398 w.mDrawPending = true;
7399 w.mCommitDrawPending = false;
7400 w.mReadyToShow = false;
7401 if (w.mAppToken != null) {
7402 w.mAppToken.allDrawn = false;
7403 }
7404 }
7405 if (DEBUG_ORIENTATION) Log.v(TAG,
7406 "Resizing window " + w + " to " + w.mFrame);
7407 mResizingWindows.add(w);
7408 } else if (w.mOrientationChanging) {
7409 if (!w.mDrawPending && !w.mCommitDrawPending) {
7410 if (DEBUG_ORIENTATION) Log.v(TAG,
7411 "Orientation not waiting for draw in "
7412 + w + ", surface " + w.mSurface);
7413 w.mOrientationChanging = false;
7414 }
7415 }
7416 }
7417
7418 if (w.mAttachedHidden) {
7419 if (!w.mLastHidden) {
7420 //dump();
7421 w.mLastHidden = true;
7422 if (SHOW_TRANSACTIONS) Log.i(
7423 TAG, " SURFACE " + w.mSurface + ": HIDE (performLayout-attached)");
7424 if (w.mSurface != null) {
7425 try {
7426 w.mSurface.hide();
7427 } catch (RuntimeException e) {
7428 Log.w(TAG, "Exception hiding surface in " + w);
7429 }
7430 }
7431 mKeyWaiter.releasePendingPointerLocked(w.mSession);
7432 }
7433 // If we are waiting for this window to handle an
7434 // orientation change, well, it is hidden, so
7435 // doesn't really matter. Note that this does
7436 // introduce a potential glitch if the window
7437 // becomes unhidden before it has drawn for the
7438 // new orientation.
7439 if (w.mOrientationChanging) {
7440 w.mOrientationChanging = false;
7441 if (DEBUG_ORIENTATION) Log.v(TAG,
7442 "Orientation change skips hidden " + w);
7443 }
7444 } else if (!w.isReadyForDisplay()) {
7445 if (!w.mLastHidden) {
7446 //dump();
7447 w.mLastHidden = true;
7448 if (SHOW_TRANSACTIONS) Log.i(
7449 TAG, " SURFACE " + w.mSurface + ": HIDE (performLayout-ready)");
7450 if (w.mSurface != null) {
7451 try {
7452 w.mSurface.hide();
7453 } catch (RuntimeException e) {
7454 Log.w(TAG, "Exception exception hiding surface in " + w);
7455 }
7456 }
7457 mKeyWaiter.releasePendingPointerLocked(w.mSession);
7458 }
7459 // If we are waiting for this window to handle an
7460 // orientation change, well, it is hidden, so
7461 // doesn't really matter. Note that this does
7462 // introduce a potential glitch if the window
7463 // becomes unhidden before it has drawn for the
7464 // new orientation.
7465 if (w.mOrientationChanging) {
7466 w.mOrientationChanging = false;
7467 if (DEBUG_ORIENTATION) Log.v(TAG,
7468 "Orientation change skips hidden " + w);
7469 }
7470 } else if (w.mLastLayer != w.mAnimLayer
7471 || w.mLastAlpha != w.mShownAlpha
7472 || w.mLastDsDx != w.mDsDx
7473 || w.mLastDtDx != w.mDtDx
7474 || w.mLastDsDy != w.mDsDy
7475 || w.mLastDtDy != w.mDtDy
7476 || w.mLastHScale != w.mHScale
7477 || w.mLastVScale != w.mVScale
7478 || w.mLastHidden) {
7479 displayed = true;
7480 w.mLastAlpha = w.mShownAlpha;
7481 w.mLastLayer = w.mAnimLayer;
7482 w.mLastDsDx = w.mDsDx;
7483 w.mLastDtDx = w.mDtDx;
7484 w.mLastDsDy = w.mDsDy;
7485 w.mLastDtDy = w.mDtDy;
7486 w.mLastHScale = w.mHScale;
7487 w.mLastVScale = w.mVScale;
7488 if (SHOW_TRANSACTIONS) Log.i(
7489 TAG, " SURFACE " + w.mSurface + ": alpha="
7490 + w.mShownAlpha + " layer=" + w.mAnimLayer);
7491 if (w.mSurface != null) {
7492 try {
7493 w.mSurface.setAlpha(w.mShownAlpha);
7494 w.mSurface.setLayer(w.mAnimLayer);
7495 w.mSurface.setMatrix(
7496 w.mDsDx*w.mHScale, w.mDtDx*w.mVScale,
7497 w.mDsDy*w.mHScale, w.mDtDy*w.mVScale);
7498 } catch (RuntimeException e) {
7499 Log.w(TAG, "Error updating surface in " + w, e);
7500 if (!recoveringMemory) {
7501 reclaimSomeSurfaceMemoryLocked(w, "update");
7502 }
7503 }
7504 }
7505
7506 if (w.mLastHidden && !w.mDrawPending
7507 && !w.mCommitDrawPending
7508 && !w.mReadyToShow) {
7509 if (SHOW_TRANSACTIONS) Log.i(
7510 TAG, " SURFACE " + w.mSurface + ": SHOW (performLayout)");
7511 if (DEBUG_VISIBILITY) Log.v(TAG, "Showing " + w
7512 + " during relayout");
7513 if (showSurfaceRobustlyLocked(w)) {
7514 w.mHasDrawn = true;
7515 w.mLastHidden = false;
7516 } else {
7517 w.mOrientationChanging = false;
7518 }
7519 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007520 if (w.mSurface != null) {
7521 w.mToken.hasVisible = true;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007522 }
7523 } else {
7524 displayed = true;
7525 }
7526
7527 if (displayed) {
7528 if (!covered) {
7529 if (attrs.width == LayoutParams.FILL_PARENT
7530 && attrs.height == LayoutParams.FILL_PARENT) {
7531 covered = true;
7532 }
7533 }
7534 if (w.mOrientationChanging) {
7535 if (w.mDrawPending || w.mCommitDrawPending) {
7536 orientationChangeComplete = false;
7537 if (DEBUG_ORIENTATION) Log.v(TAG,
7538 "Orientation continue waiting for draw in " + w);
7539 } else {
7540 w.mOrientationChanging = false;
7541 if (DEBUG_ORIENTATION) Log.v(TAG,
7542 "Orientation change complete in " + w);
7543 }
7544 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007545 w.mToken.hasVisible = true;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007546 }
7547 } else if (w.mOrientationChanging) {
7548 if (DEBUG_ORIENTATION) Log.v(TAG,
7549 "Orientation change skips hidden " + w);
7550 w.mOrientationChanging = false;
7551 }
7552
7553 final boolean canBeSeen = w.isDisplayedLw();
7554
7555 if (someoneLosingFocus && w == mCurrentFocus && canBeSeen) {
7556 focusDisplayed = true;
7557 }
7558
7559 // Update effect.
7560 if (!obscured) {
7561 if (w.mSurface != null &&
7562 (attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
7563 holdScreen = w.mSession;
7564 }
7565 if (w.isFullscreenOpaque(dw, dh)) {
7566 // This window completely covers everything behind it,
7567 // so we want to leave all of them as unblurred (for
7568 // performance reasons).
7569 obscured = true;
7570 } else if (canBeSeen && !obscured &&
7571 (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) {
7572 if (localLOGV) Log.v(TAG, "Win " + w
7573 + ": blurring=" + blurring
7574 + " obscured=" + obscured
7575 + " displayed=" + displayed);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007576 if ((attrFlags&FLAG_DIM_BEHIND) != 0) {
7577 if (!dimming) {
7578 //Log.i(TAG, "DIM BEHIND: " + w);
7579 dimming = true;
7580 mDimShown = true;
7581 if (mDimSurface == null) {
7582 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
7583 + mDimSurface + ": CREATE");
7584 try {
7585 mDimSurface = new Surface(mFxSession, 0,
7586 -1, 16, 16,
7587 PixelFormat.OPAQUE,
7588 Surface.FX_SURFACE_DIM);
7589 } catch (Exception e) {
7590 Log.e(TAG, "Exception creating Dim surface", e);
7591 }
7592 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007593 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007594 + mDimSurface + ": SHOW pos=(0,0) (" +
7595 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
7596 if (mDimSurface != null) {
7597 try {
7598 mDimSurface.setPosition(0, 0);
7599 mDimSurface.setSize(dw, dh);
7600 mDimSurface.show();
7601 } catch (RuntimeException e) {
7602 Log.w(TAG, "Failure showing dim surface", e);
7603 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007604 }
7605 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007606 mDimSurface.setLayer(w.mAnimLayer-1);
7607 final float target = w.mExiting ? 0 : attrs.dimAmount;
7608 if (mDimTargetAlpha != target) {
7609 // If the desired dim level has changed, then
7610 // start an animation to it.
7611 mLastDimAnimTime = currentTime;
7612 long duration = (w.mAnimating && w.mAnimation != null)
7613 ? w.mAnimation.computeDurationHint()
7614 : DEFAULT_DIM_DURATION;
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08007615 if (target > mDimTargetAlpha) {
7616 // This is happening behind the activity UI,
7617 // so we can make it run a little longer to
7618 // give a stronger impression without disrupting
7619 // the user.
7620 duration *= DIM_DURATION_MULTIPLIER;
7621 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007622 mDimTargetAlpha = target;
7623 mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha)
7624 / duration;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007625 }
7626 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007627 if ((attrFlags&FLAG_BLUR_BEHIND) != 0) {
7628 if (!blurring) {
7629 //Log.i(TAG, "BLUR BEHIND: " + w);
7630 blurring = true;
7631 mBlurShown = true;
7632 if (mBlurSurface == null) {
7633 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR "
7634 + mBlurSurface + ": CREATE");
7635 try {
7636 mBlurSurface = new Surface(mFxSession, 0,
7637 -1, 16, 16,
7638 PixelFormat.OPAQUE,
7639 Surface.FX_SURFACE_BLUR);
7640 } catch (Exception e) {
7641 Log.e(TAG, "Exception creating Blur surface", e);
7642 }
7643 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007644 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR "
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007645 + mBlurSurface + ": SHOW pos=(0,0) (" +
7646 dw + "x" + dh + "), layer=" + (w.mAnimLayer-1));
7647 if (mBlurSurface != null) {
7648 mBlurSurface.setPosition(0, 0);
7649 mBlurSurface.setSize(dw, dh);
7650 try {
7651 mBlurSurface.show();
7652 } catch (RuntimeException e) {
7653 Log.w(TAG, "Failure showing blur surface", e);
7654 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007655 }
7656 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007657 mBlurSurface.setLayer(w.mAnimLayer-2);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007658 }
7659 }
7660 }
7661 }
7662
7663 if (!dimming && mDimShown) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007664 // Time to hide the dim surface... start fading.
7665 if (mDimTargetAlpha != 0) {
7666 mLastDimAnimTime = currentTime;
7667 mDimTargetAlpha = 0;
7668 mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007669 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007670 }
7671
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007672 if (mDimShown && mLastDimAnimTime != 0) {
7673 mDimCurrentAlpha += mDimDeltaPerMs
7674 * (currentTime-mLastDimAnimTime);
7675 boolean more = true;
7676 if (mDimDeltaPerMs > 0) {
7677 if (mDimCurrentAlpha > mDimTargetAlpha) {
7678 more = false;
7679 }
7680 } else if (mDimDeltaPerMs < 0) {
7681 if (mDimCurrentAlpha < mDimTargetAlpha) {
7682 more = false;
7683 }
7684 } else {
7685 more = false;
7686 }
7687
7688 // Do we need to continue animating?
7689 if (more) {
7690 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
7691 + mDimSurface + ": alpha=" + mDimCurrentAlpha);
The Android Open Source Projectf1e484a2009-01-22 00:13:42 -08007692 mLastDimAnimTime = currentTime;
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007693 mDimSurface.setAlpha(mDimCurrentAlpha);
7694 animating = true;
7695 } else {
7696 mDimCurrentAlpha = mDimTargetAlpha;
7697 mLastDimAnimTime = 0;
7698 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM "
7699 + mDimSurface + ": final alpha=" + mDimCurrentAlpha);
7700 mDimSurface.setAlpha(mDimCurrentAlpha);
7701 if (!dimming) {
7702 if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface
7703 + ": HIDE");
7704 try {
7705 mDimSurface.hide();
7706 } catch (RuntimeException e) {
7707 Log.w(TAG, "Illegal argument exception hiding dim surface");
7708 }
7709 mDimShown = false;
7710 }
7711 }
7712 }
7713
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007714 if (!blurring && mBlurShown) {
7715 if (SHOW_TRANSACTIONS) Log.i(TAG, " BLUR " + mBlurSurface
7716 + ": HIDE");
7717 try {
7718 mBlurSurface.hide();
7719 } catch (IllegalArgumentException e) {
7720 Log.w(TAG, "Illegal argument exception hiding blur surface");
7721 }
7722 mBlurShown = false;
7723 }
7724
7725 if (SHOW_TRANSACTIONS) Log.i(TAG, "<<< CLOSE TRANSACTION");
7726 } catch (RuntimeException e) {
7727 Log.e(TAG, "Unhandled exception in Window Manager", e);
7728 }
7729
7730 Surface.closeTransaction();
7731
7732 if (DEBUG_ORIENTATION && mDisplayFrozen) Log.v(TAG,
7733 "With display frozen, orientationChangeComplete="
7734 + orientationChangeComplete);
7735 if (orientationChangeComplete) {
7736 if (mWindowsFreezingScreen) {
7737 mWindowsFreezingScreen = false;
7738 mH.removeMessages(H.WINDOW_FREEZE_TIMEOUT);
7739 }
7740 if (mAppsFreezingScreen == 0) {
7741 stopFreezingDisplayLocked();
7742 }
7743 }
7744
7745 i = mResizingWindows.size();
7746 if (i > 0) {
7747 do {
7748 i--;
7749 WindowState win = mResizingWindows.get(i);
7750 try {
7751 win.mClient.resized(win.mFrame.width(),
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007752 win.mFrame.height(), win.mLastContentInsets,
7753 win.mLastVisibleInsets, win.mDrawPending);
7754 win.mContentInsetsChanged = false;
7755 win.mVisibleInsetsChanged = false;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007756 } catch (RemoteException e) {
7757 win.mOrientationChanging = false;
7758 }
7759 } while (i > 0);
7760 mResizingWindows.clear();
7761 }
7762
7763 // Destroy the surface of any windows that are no longer visible.
7764 i = mDestroySurface.size();
7765 if (i > 0) {
7766 do {
7767 i--;
7768 WindowState win = mDestroySurface.get(i);
7769 win.mDestroying = false;
7770 win.destroySurfaceLocked();
7771 } while (i > 0);
7772 mDestroySurface.clear();
7773 }
7774
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007775 // Time to remove any exiting tokens?
7776 for (i=mExitingTokens.size()-1; i>=0; i--) {
7777 WindowToken token = mExitingTokens.get(i);
7778 if (!token.hasVisible) {
7779 mExitingTokens.remove(i);
7780 }
7781 }
7782
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007783 // Time to remove any exiting applications?
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007784 for (i=mExitingAppTokens.size()-1; i>=0; i--) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007785 AppWindowToken token = mExitingAppTokens.get(i);
7786 if (!token.hasVisible && !mClosingApps.contains(token)) {
7787 mAppTokens.remove(token);
7788 mExitingAppTokens.remove(i);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007789 }
7790 }
7791
7792 if (focusDisplayed) {
7793 mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
7794 }
7795 if (animating) {
7796 requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
7797 }
7798 mQueue.setHoldScreenLocked(holdScreen != null);
7799 if (holdScreen != mHoldingScreenOn) {
7800 mHoldingScreenOn = holdScreen;
7801 Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
7802 mH.sendMessage(m);
7803 }
7804 }
7805
7806 void requestAnimationLocked(long delay) {
7807 if (!mAnimationPending) {
7808 mAnimationPending = true;
7809 mH.sendMessageDelayed(mH.obtainMessage(H.ANIMATE), delay);
7810 }
7811 }
7812
7813 /**
7814 * Have the surface flinger show a surface, robustly dealing wit
7815 * error conditions. In particular, if there is not enough memory
7816 * to show the surface, then we will try to get rid of other surfaces
7817 * in order to succeed.
7818 *
7819 * @return Returns true if the surface was successfully shown.
7820 */
7821 boolean showSurfaceRobustlyLocked(WindowState win) {
7822 try {
7823 if (win.mSurface != null) {
7824 win.mSurface.show();
7825 }
7826 return true;
7827 } catch (RuntimeException e) {
7828 Log.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
7829 }
7830
7831 reclaimSomeSurfaceMemoryLocked(win, "show");
7832
7833 return false;
7834 }
7835
7836 void reclaimSomeSurfaceMemoryLocked(WindowState win, String operation) {
7837 final Surface surface = win.mSurface;
7838
7839 EventLog.writeEvent(LOG_WM_NO_SURFACE_MEMORY, win.toString(),
7840 win.mSession.mPid, operation);
7841
7842 if (mForceRemoves == null) {
7843 mForceRemoves = new ArrayList<WindowState>();
7844 }
7845
7846 long callingIdentity = Binder.clearCallingIdentity();
7847 try {
7848 // There was some problem... first, do a sanity check of the
7849 // window list to make sure we haven't left any dangling surfaces
7850 // around.
7851 int N = mWindows.size();
7852 boolean leakedSurface = false;
7853 Log.i(TAG, "Out of memory for surface! Looking for leaks...");
7854 for (int i=0; i<N; i++) {
7855 WindowState ws = (WindowState)mWindows.get(i);
7856 if (ws.mSurface != null) {
7857 if (!mSessions.contains(ws.mSession)) {
7858 Log.w(TAG, "LEAKED SURFACE (session doesn't exist): "
7859 + ws + " surface=" + ws.mSurface
7860 + " token=" + win.mToken
7861 + " pid=" + ws.mSession.mPid
7862 + " uid=" + ws.mSession.mUid);
7863 ws.mSurface.clear();
7864 ws.mSurface = null;
7865 mForceRemoves.add(ws);
7866 i--;
7867 N--;
7868 leakedSurface = true;
7869 } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
7870 Log.w(TAG, "LEAKED SURFACE (app token hidden): "
7871 + ws + " surface=" + ws.mSurface
7872 + " token=" + win.mAppToken);
7873 ws.mSurface.clear();
7874 ws.mSurface = null;
7875 leakedSurface = true;
7876 }
7877 }
7878 }
7879
7880 boolean killedApps = false;
7881 if (!leakedSurface) {
7882 Log.w(TAG, "No leaked surfaces; killing applicatons!");
7883 SparseIntArray pidCandidates = new SparseIntArray();
7884 for (int i=0; i<N; i++) {
7885 WindowState ws = (WindowState)mWindows.get(i);
7886 if (ws.mSurface != null) {
7887 pidCandidates.append(ws.mSession.mPid, ws.mSession.mPid);
7888 }
7889 }
7890 if (pidCandidates.size() > 0) {
7891 int[] pids = new int[pidCandidates.size()];
7892 for (int i=0; i<pids.length; i++) {
7893 pids[i] = pidCandidates.keyAt(i);
7894 }
7895 try {
7896 if (mActivityManager.killPidsForMemory(pids)) {
7897 killedApps = true;
7898 }
7899 } catch (RemoteException e) {
7900 }
7901 }
7902 }
7903
7904 if (leakedSurface || killedApps) {
7905 // We managed to reclaim some memory, so get rid of the trouble
7906 // surface and ask the app to request another one.
7907 Log.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
7908 if (surface != null) {
7909 surface.clear();
7910 win.mSurface = null;
7911 }
7912
7913 try {
7914 win.mClient.dispatchGetNewSurface();
7915 } catch (RemoteException e) {
7916 }
7917 }
7918 } finally {
7919 Binder.restoreCallingIdentity(callingIdentity);
7920 }
7921 }
7922
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007923 private boolean updateFocusedWindowLocked(int mode) {
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007924 WindowState newFocus = computeFocusedWindowLocked();
7925 if (mCurrentFocus != newFocus) {
7926 // This check makes sure that we don't already have the focus
7927 // change message pending.
7928 if (mLastFocus == mCurrentFocus) {
7929 mH.sendEmptyMessage(H.REPORT_FOCUS_CHANGE);
7930 }
7931 if (localLOGV) Log.v(
7932 TAG, "Changing focus from " + mCurrentFocus + " to " + newFocus);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007933 final WindowState oldFocus = mCurrentFocus;
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007934 mCurrentFocus = newFocus;
7935 mLosingFocus.remove(newFocus);
7936 if (newFocus != null) {
7937 mKeyWaiter.handleNewWindowLocked(newFocus);
7938 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08007939
7940 final WindowState imWindow = mInputMethodWindow;
7941 if (newFocus != imWindow && oldFocus != imWindow) {
7942 moveInputMethodWindowsIfNeededLocked(
7943 mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS &&
7944 mode != UPDATE_FOCUS_WILL_PLACE_SURFACES);
7945 mLayoutNeeded = true;
7946 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
7947 performLayoutLockedInner();
7948 } else if (mode != UPDATE_FOCUS_WILL_PLACE_SURFACES) {
7949 mLayoutNeeded = true;
7950 performLayoutAndPlaceSurfacesLocked();
7951 }
7952 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007953 return true;
7954 }
7955 return false;
7956 }
7957
7958 private WindowState computeFocusedWindowLocked() {
7959 WindowState result = null;
7960 WindowState win;
7961
7962 int i = mWindows.size() - 1;
7963 int nextAppIndex = mAppTokens.size()-1;
7964 WindowToken nextApp = nextAppIndex >= 0
7965 ? mAppTokens.get(nextAppIndex) : null;
7966
7967 while (i >= 0) {
7968 win = (WindowState)mWindows.get(i);
7969
7970 if (localLOGV || DEBUG_FOCUS) Log.v(
7971 TAG, "Looking for focus: " + i
7972 + " = " + win
7973 + ", flags=" + win.mAttrs.flags
7974 + ", canReceive=" + win.canReceiveKeys());
7975
7976 AppWindowToken thisApp = win.mAppToken;
7977
7978 // If this window's application has been removed, just skip it.
7979 if (thisApp != null && thisApp.removed) {
7980 i--;
7981 continue;
7982 }
7983
7984 // If there is a focused app, don't allow focus to go to any
7985 // windows below it. If this is an application window, step
7986 // through the app tokens until we find its app.
7987 if (thisApp != null && nextApp != null && thisApp != nextApp
7988 && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
7989 int origAppIndex = nextAppIndex;
7990 while (nextAppIndex > 0) {
7991 if (nextApp == mFocusedApp) {
7992 // Whoops, we are below the focused app... no focus
7993 // for you!
7994 if (localLOGV || DEBUG_FOCUS) Log.v(
7995 TAG, "Reached focused app: " + mFocusedApp);
7996 return null;
7997 }
7998 nextAppIndex--;
7999 nextApp = mAppTokens.get(nextAppIndex);
8000 if (nextApp == thisApp) {
8001 break;
8002 }
8003 }
8004 if (thisApp != nextApp) {
8005 // Uh oh, the app token doesn't exist! This shouldn't
8006 // happen, but if it does we can get totally hosed...
8007 // so restart at the original app.
8008 nextAppIndex = origAppIndex;
8009 nextApp = mAppTokens.get(nextAppIndex);
8010 }
8011 }
8012
8013 // Dispatch to this window if it is wants key events.
8014 if (win.canReceiveKeys()) {
8015 if (DEBUG_FOCUS) Log.v(
8016 TAG, "Found focus @ " + i + " = " + win);
8017 result = win;
8018 break;
8019 }
8020
8021 i--;
8022 }
8023
8024 return result;
8025 }
8026
8027 private void startFreezingDisplayLocked() {
8028 if (mDisplayFrozen) {
8029 return;
8030 }
8031
8032 long now = SystemClock.uptimeMillis();
8033 //Log.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now);
8034 if (mFreezeGcPending != 0) {
8035 if (now > (mFreezeGcPending+1000)) {
8036 //Log.i(TAG, "Gc! " + now + " > " + (mFreezeGcPending+1000));
8037 mH.removeMessages(H.FORCE_GC);
8038 Runtime.getRuntime().gc();
8039 mFreezeGcPending = now;
8040 }
8041 } else {
8042 mFreezeGcPending = now;
8043 }
8044
8045 mDisplayFrozen = true;
8046 if (mNextAppTransition != WindowManagerPolicy.TRANSIT_NONE) {
8047 mNextAppTransition = WindowManagerPolicy.TRANSIT_NONE;
8048 mAppTransitionReady = true;
8049 }
8050
8051 if (PROFILE_ORIENTATION) {
8052 File file = new File("/data/system/frozen");
8053 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
8054 }
8055 Surface.freezeDisplay(0);
8056 }
8057
8058 private void stopFreezingDisplayLocked() {
8059 if (!mDisplayFrozen) {
8060 return;
8061 }
8062
8063 mDisplayFrozen = false;
8064 mH.removeMessages(H.APP_FREEZE_TIMEOUT);
8065 if (PROFILE_ORIENTATION) {
8066 Debug.stopMethodTracing();
8067 }
8068 Surface.unfreezeDisplay(0);
8069
8070 // Freezing the display also suspends key event delivery, to
8071 // keep events from going astray while the display is reconfigured.
8072 // Now that we're back, notify the key waiter that we're alive
8073 // again and it should restart its timeouts.
8074 synchronized (mKeyWaiter) {
8075 mKeyWaiter.mWasFrozen = true;
8076 mKeyWaiter.notifyAll();
8077 }
8078
8079 // A little kludge: a lot could have happened while the
8080 // display was frozen, so now that we are coming back we
8081 // do a gc so that any remote references the system
8082 // processes holds on others can be released if they are
8083 // no longer needed.
8084 mH.removeMessages(H.FORCE_GC);
8085 mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC),
8086 2000);
8087 }
8088
8089 @Override
8090 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
8091 if (mContext.checkCallingOrSelfPermission("android.permission.DUMP")
8092 != PackageManager.PERMISSION_GRANTED) {
8093 pw.println("Permission Denial: can't dump WindowManager from from pid="
8094 + Binder.getCallingPid()
8095 + ", uid=" + Binder.getCallingUid());
8096 return;
8097 }
8098
8099 synchronized(mWindowMap) {
8100 pw.println("Current Window Manager state:");
8101 for (int i=mWindows.size()-1; i>=0; i--) {
8102 WindowState w = (WindowState)mWindows.get(i);
8103 pw.println(" Window #" + i + ":");
8104 w.dump(pw, " ");
8105 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08008106 if (mInputMethodDialogs.size() > 0) {
8107 pw.println(" ");
8108 pw.println(" Input method dialogs:");
8109 for (int i=mInputMethodDialogs.size()-1; i>=0; i--) {
8110 WindowState w = mInputMethodDialogs.get(i);
8111 pw.println(" IM Dialog #" + i + ": " + w);
8112 }
8113 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07008114 if (mPendingRemove.size() > 0) {
8115 pw.println(" ");
8116 pw.println(" Remove pending for:");
8117 for (int i=mPendingRemove.size()-1; i>=0; i--) {
8118 WindowState w = mPendingRemove.get(i);
8119 pw.println(" Remove #" + i + ":");
8120 w.dump(pw, " ");
8121 }
8122 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08008123 if (mForceRemoves != null && mForceRemoves.size() > 0) {
8124 pw.println(" ");
8125 pw.println(" Windows force removing:");
8126 for (int i=mForceRemoves.size()-1; i>=0; i--) {
8127 WindowState w = mForceRemoves.get(i);
8128 pw.println(" Removing #" + i + ":");
8129 w.dump(pw, " ");
8130 }
8131 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07008132 if (mDestroySurface.size() > 0) {
8133 pw.println(" ");
8134 pw.println(" Windows waiting to destroy their surface:");
8135 for (int i=mDestroySurface.size()-1; i>=0; i--) {
8136 WindowState w = mDestroySurface.get(i);
8137 pw.println(" Destroy #" + i + ":");
8138 w.dump(pw, " ");
8139 }
8140 }
8141 if (mLosingFocus.size() > 0) {
8142 pw.println(" ");
8143 pw.println(" Windows losing focus:");
8144 for (int i=mLosingFocus.size()-1; i>=0; i--) {
8145 WindowState w = mLosingFocus.get(i);
8146 pw.println(" Losing #" + i + ":");
8147 w.dump(pw, " ");
8148 }
8149 }
8150 if (mSessions.size() > 0) {
8151 pw.println(" ");
8152 pw.println(" All active sessions:");
8153 Iterator<Session> it = mSessions.iterator();
8154 while (it.hasNext()) {
8155 Session s = it.next();
8156 pw.println(" Session " + s);
8157 s.dump(pw, " ");
8158 }
8159 }
8160 if (mTokenMap.size() > 0) {
8161 pw.println(" ");
8162 pw.println(" All tokens:");
8163 Iterator<WindowToken> it = mTokenMap.values().iterator();
8164 while (it.hasNext()) {
8165 WindowToken token = it.next();
8166 pw.println(" Token " + token.token);
8167 token.dump(pw, " ");
8168 }
8169 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08008170 if (mTokenList.size() > 0) {
8171 pw.println(" ");
8172 pw.println(" Window token list:");
8173 for (int i=0; i<mTokenList.size(); i++) {
8174 pw.println(" WindowToken #" + i + ": " + mTokenList.get(i));
8175 }
8176 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07008177 if (mAppTokens.size() > 0) {
8178 pw.println(" ");
8179 pw.println(" Application tokens in Z order:");
8180 for (int i=mAppTokens.size()-1; i>=0; i--) {
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08008181 pw.println(" AppWindowToken #" + i + ": " + mAppTokens.get(i));
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07008182 }
8183 }
8184 if (mFinishedStarting.size() > 0) {
8185 pw.println(" ");
8186 pw.println(" Finishing start of application tokens:");
8187 for (int i=mFinishedStarting.size()-1; i>=0; i--) {
8188 WindowToken token = mFinishedStarting.get(i);
8189 pw.println(" Finish Starting App Token #" + i + ":");
8190 token.dump(pw, " ");
8191 }
8192 }
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08008193 if (mExitingTokens.size() > 0) {
8194 pw.println(" ");
8195 pw.println(" Exiting tokens:");
8196 for (int i=mExitingTokens.size()-1; i>=0; i--) {
8197 WindowToken token = mExitingTokens.get(i);
8198 pw.println(" Exiting Token #" + i + ":");
8199 token.dump(pw, " ");
8200 }
8201 }
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07008202 if (mExitingAppTokens.size() > 0) {
8203 pw.println(" ");
8204 pw.println(" Exiting application tokens:");
8205 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
8206 WindowToken token = mExitingAppTokens.get(i);
8207 pw.println(" Exiting App Token #" + i + ":");
8208 token.dump(pw, " ");
8209 }
8210 }
8211 pw.println(" ");
8212 pw.println(" mCurrentFocus=" + mCurrentFocus);
8213 pw.println(" mLastFocus=" + mLastFocus);
8214 pw.println(" mFocusedApp=" + mFocusedApp);
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08008215 pw.println(" mInputMethodTarget=" + mInputMethodTarget);
8216 pw.println(" mInputMethodWindow=" + mInputMethodWindow);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07008217 pw.println(" mInTouchMode=" + mInTouchMode);
8218 pw.println(" mSystemBooted=" + mSystemBooted
8219 + " mDisplayEnabled=" + mDisplayEnabled);
8220 pw.println(" mLayoutNeeded=" + mLayoutNeeded
8221 + " mSurfacesChanged=" + mSurfacesChanged
The Android Open Source Projectf013e1a2008-12-17 18:05:43 -08008222 + " mBlurShown=" + mBlurShown);
8223 pw.println(" mDimShown=" + mDimShown
8224 + " current=" + mDimCurrentAlpha
8225 + " target=" + mDimTargetAlpha
8226 + " delta=" + mDimDeltaPerMs
8227 + " lastAnimTime=" + mLastDimAnimTime);
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07008228 pw.println(" mDisplayFrozen=" + mDisplayFrozen
8229 + " mWindowsFreezingScreen=" + mWindowsFreezingScreen
8230 + " mAppsFreezingScreen=" + mAppsFreezingScreen);
8231 pw.println(" mRotation=" + mRotation
8232 + ", mForcedAppOrientation=" + mForcedAppOrientation
8233 + ", mRequestedRotation=" + mRequestedRotation);
8234 pw.println(" mAnimationPending=" + mAnimationPending
8235 + " mWindowAnimationScale=" + mWindowAnimationScale
8236 + " mTransitionWindowAnimationScale=" + mTransitionAnimationScale);
8237 pw.println(" mNextAppTransition=0x"
8238 + Integer.toHexString(mNextAppTransition)
8239 + ", mAppTransitionReady=" + mAppTransitionReady
8240 + ", mAppTransitionTimeout=" + mAppTransitionTimeout);
8241 pw.println(" mStartingIconInTransition=" + mStartingIconInTransition
8242 + ", mSkipAppTransitionAnimation=" + mSkipAppTransitionAnimation);
8243 pw.println(" mOpeningApps=" + mOpeningApps);
8244 pw.println(" mClosingApps=" + mClosingApps);
8245 pw.println(" DisplayWidth=" + mDisplay.getWidth()
8246 + " DisplayHeight=" + mDisplay.getHeight());
8247 pw.println(" KeyWaiter state:");
8248 pw.println(" mLastWin=" + mKeyWaiter.mLastWin
8249 + " mLastBinder=" + mKeyWaiter.mLastBinder);
8250 pw.println(" mFinished=" + mKeyWaiter.mFinished
8251 + " mGotFirstWindow=" + mKeyWaiter.mGotFirstWindow
8252 + " mEventDispatching" + mKeyWaiter.mEventDispatching
8253 + " mTimeToSwitch=" + mKeyWaiter.mTimeToSwitch);
8254 }
8255 }
8256
8257 public void monitor() {
8258 synchronized (mWindowMap) { }
8259 synchronized (mKeyguardDisabled) { }
8260 synchronized (mKeyWaiter) { }
8261 }
8262}